[PATCH v3 5/5] rust: usb: let a driver keep its interface usable while unbinding

Mike Lothian <[email protected]>
Newsgroups org.kernel.vger.rust-for-linux,org.kernel.vger.linux-kernel,org.kernel.vger.linux-usb
Message-ID <[email protected]>
The USB core kills every outstanding URB and disables an interface's
endpoints before it calls any driver callback. A driver with something
left to say to the device on the way out therefore cannot say it: the
transfer names an endpoint that no longer exists and is refused.

Expose the core's soft-unbind flag as a driver constant. Setting it
defers that teardown until the callbacks return, which makes cancelling
outstanding transfers the driver's own responsibility.

This matters to a driver that leaves the device in a state a user can
see. A display bridge that simply stops sending pixels leaves the
monitor lit on whatever it decoded last.

Assisted-by: Claude:claude-opus-5
Signed-off-by: Mike Lothian <[email protected]>
---
 rust/kernel/usb.rs | 14 ++++++++++++++
 1 file changed, 14 insertions(+)

diff --git a/rust/kernel/usb.rs b/rust/kernel/usb.rs
index b2a0fb104ddf..1d8f5bc8a545 100644
--- a/rust/kernel/usb.rs
+++ b/rust/kernel/usb.rs
@@ -107,6 +107,7 @@ unsafe fn register(
             (*udrv.get()).pre_reset = Some(Self::pre_reset_callback);
             (*udrv.get()).post_reset = Some(Self::post_reset_callback);
             (*udrv.get()).id_table = T::ID_TABLE.as_ptr();
+            (*udrv.get()).set_soft_unbind(T::SOFT_UNBIND as core::ffi::c_uint);
         }
 
         // SAFETY: `udrv` is guaranteed to be a valid `DriverType`.
@@ -474,6 +475,19 @@ pub trait Driver {
     /// The table of device ids supported by the driver.
     const ID_TABLE: IdTable<Self::IdInfo>;
 
+    /// Whether the USB core must leave this interface usable until the driver has let go of it.
+    ///
+    /// By default the core kills every outstanding URB and disables the interface's endpoints
+    /// *before* it calls any driver callback, so a driver that has something to say to the device
+    /// on the way out cannot say it: the transfer is refused with [`ENOENT`] because the endpoint
+    /// it names no longer exists. Setting this defers that teardown until after the callbacks
+    /// return, which makes cancelling outstanding transfers the driver's own responsibility.
+    ///
+    /// Only useful to a driver that leaves the device in a state a user can see -- a display that
+    /// otherwise goes on scanning out its last frame, an interface that must be told to power
+    /// down.
+    const SOFT_UNBIND: bool = false;
+
     /// USB driver probe.
     ///
     /// Called when a new USB interface is bound to this driver.
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.