@@ -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);
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@quicinc.com> --- drivers/usb/gadget/udc/core.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-)