[RFC PATCH 7/9] rust: usb: add usb::Device::reset_configuration()

From: Mike Lothian

Date: Wed Jun 17 2026 - 11:12:50 EST


Add a safe wrapper over usb_reset_configuration() so a Rust driver can
re-issue SET_CONFIGURATION for the device's current configuration,
resetting every endpoint's data toggle and returning each interface to
alternate setting 0 (clearing stalls) without re-enumerating the device.
It sleeps, so it must be called from process context.

This is the in-kernel-coordinated way to recover a device whose endpoint
toggles or stall state have become inconsistent with the host -- e.g.
after another driver was forcibly unbound, after error recovery, or to
return a multi-function device to a known state before re-driving it.
Drivers must not open-code it by sending a raw SET_CONFIGURATION control
request: usb_reset_configuration() also re-installs the host-side
endpoint state and is serialised against the USB core, whereas a bare
control transfer is not and is unsafe on a composite device.

Because it re-issues SET_CONFIGURATION it resets the toggles of all the
device's endpoints, so on a composite device it disturbs sibling
functions; callers should treat it as a heavy reset, not a per-endpoint
operation (for a single stalled endpoint, prefer clear_halt()).

Signed-off-by: Mike Lothian <mike@xxxxxxxxxxxxxx>
Assisted-by: Claude:claude-opus-4-8 [Claude-Code]
---
rust/kernel/usb.rs | 17 +++++++++++++++++
1 file changed, 17 insertions(+)

diff --git a/rust/kernel/usb.rs b/rust/kernel/usb.rs
index c7bf4637ee90..5dc5b496b970 100644
--- a/rust/kernel/usb.rs
+++ b/rust/kernel/usb.rs
@@ -697,6 +697,23 @@ pub fn set_interface(&self, interface: u8, alternate: u8) -> Result {
bindings::usb_set_interface(self.as_raw(), interface.into(), alternate.into())
})
}
+
+ /// Re-issues `SET_CONFIGURATION` for the device's current configuration, resetting
+ /// per-endpoint data toggles and returning every interface to alternate setting 0
+ /// (clearing any stalls) WITHOUT re-enumerating the device.
+ ///
+ /// Wraps [`usb_reset_configuration()`]. This is a blocking, sleeping call and must
+ /// only be invoked from process context. Note: it resets the toggles of ALL of the
+ /// device's endpoints, so on a composite device it can disturb sibling-interface
+ /// drivers that are mid-transfer.
+ ///
+ /// [`usb_reset_configuration()`]: https://docs.kernel.org/driver-api/usb/usb.html#c.usb_reset_configuration
+ pub fn reset_configuration(&self) -> Result {
+ // SAFETY: `self.as_raw()` is a valid `struct usb_device` by the type invariant;
+ // `usb_reset_configuration()` only re-issues SET_CONFIGURATION and updates the
+ // host-side endpoint state for this device.
+ to_result(unsafe { bindings::usb_reset_configuration(self.as_raw()) })
+ }
}

// SAFETY: `Device` is a transparent wrapper of a type that doesn't depend on `Device`'s generic
--
2.54.0