[PATCH 2/2] usb: gadget: udc: Update USB gadget state during soft disconnect
From: Wesley Cheng
Date: Fri Feb 28 2025 - 19:35:23 EST
In the soft disconnect scenarios, the USB connection will be lost
momentarily, so the proper gadget state should be reflected during the time
the connection is unavailable. Add a flush_work() call, to ensure that
gadget->work is completed before continuing with the UDC unbind sequence.
Since usb_gadget_set_state() queues work to a workqueue, depending on when
the queue is scheduled, this avoids a possible use after freed scenario as
the USB gadget will most likely be freed shortly after the UDC driver is
unbounded.
Signed-off-by: Wesley Cheng <quic_wcheng@xxxxxxxxxxx>
---
drivers/usb/gadget/udc/core.c | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)
diff --git a/drivers/usb/gadget/udc/core.c b/drivers/usb/gadget/udc/core.c
index 4b3d5075621a..7e401cb5a265 100644
--- a/drivers/usb/gadget/udc/core.c
+++ b/drivers/usb/gadget/udc/core.c
@@ -775,8 +775,10 @@ static int usb_gadget_disconnect_locked(struct usb_gadget *gadget)
}
ret = gadget->ops->pullup(gadget, 0);
- if (!ret)
+ if (!ret) {
gadget->connected = 0;
+ usb_gadget_set_state(gadget, USB_STATE_NOTATTACHED);
+ }
mutex_lock(&udc_lock);
if (gadget->udc->driver)
@@ -1669,6 +1671,7 @@ static void gadget_unbind_driver(struct device *dev)
synchronize_irq(gadget->irq);
mutex_unlock(&udc->connect_lock);
+ flush_work(&gadget->work);
udc->driver->unbind(gadget);
mutex_lock(&udc->connect_lock);