* [PATCH 1/4] USB: UDC core: Add udc_async_callbacks gadget op
@ 2021-05-20 20:21 Alan Stern
2021-06-04 5:18 ` Felipe Balbi
0 siblings, 1 reply; 2+ messages in thread
From: Alan Stern @ 2021-05-20 20:21 UTC (permalink / raw)
To: Felipe Balbi; +Cc: USB mailing list
The Gadget API has a theoretical race when a gadget driver is unbound.
Although the pull-up is turned off before the driver's ->unbind
callback runs, if the USB cable were to be unplugged at just the wrong
moment there would be nothing to prevent the UDC driver from invoking
the ->disconnect callback after the unbind has finished. In theory,
other asynchronous callbacks could also happen during the time before
the UDC driver's udc_stop routine is called, and the gadget driver
would not be prepared to handle any of them.
We need a way to tell UDC drivers to stop issuing asynchronous (that is,
->suspend, ->resume, ->disconnect, ->reset, or ->setup) callbacks at
some point after the pull-up has been turned off and before the
->unbind callback runs. This patch adds a new ->udc_async_callbacks
callback to the usb_gadget_ops structure for precisely this purpose,
and it adds the corresponding support to the UDC core.
Later patches in this series add support for udc_async_callbacks to
several UDC drivers.
Signed-off-by: Alan Stern <stern@rowland.harvard.edu>
---
[as1956]
drivers/usb/gadget/udc/core.c | 49 ++++++++++++++++++++++++++++++++++++++++++
include/linux/usb/gadget.h | 1
2 files changed, 50 insertions(+)
Index: usb-devel/drivers/usb/gadget/udc/core.c
===================================================================
--- usb-devel.orig/drivers/usb/gadget/udc/core.c
+++ usb-devel/drivers/usb/gadget/udc/core.c
@@ -1148,6 +1148,53 @@ static inline void usb_gadget_udc_set_sp
}
/**
+ * usb_gadget_enable_async_callbacks - tell usb device controller to enable asynchronous callbacks
+ * @udc: The UDC which should enable async callbacks
+ *
+ * This routine is used when binding gadget drivers. It undoes the effect
+ * of usb_gadget_disable_async_callbacks(); the UDC driver should enable IRQs
+ * (if necessary) and resume issuing callbacks.
+ *
+ * This routine will always be called in process context.
+ */
+static inline void usb_gadget_enable_async_callbacks(struct usb_udc *udc)
+{
+ struct usb_gadget *gadget = udc->gadget;
+
+ if (gadget->ops->udc_async_callbacks)
+ gadget->ops->udc_async_callbacks(gadget, true);
+}
+
+/**
+ * usb_gadget_disable_async_callbacks - tell usb device controller to disable asynchronous callbacks
+ * @udc: The UDC which should disable async callbacks
+ *
+ * This routine is used when unbinding gadget drivers. It prevents a race:
+ * The UDC driver doesn't know when the gadget driver's ->unbind callback
+ * runs, so unless it is told to disable asynchronous callbacks, it might
+ * issue a callback (such as ->disconnect) after the unbind has completed.
+ *
+ * After this function runs, the UDC driver must suppress all ->suspend,
+ * ->resume, ->disconnect, ->reset, and ->setup callbacks to the gadget driver
+ * until async callbacks are again enabled. A simple-minded but effective
+ * way to accomplish this is to tell the UDC hardware not to generate any
+ * more IRQs.
+ *
+ * Request completion callbacks must still be issued. However, it's okay
+ * to defer them until the request is cancelled, since the pull-up will be
+ * turned off during the time period when async callbacks are disabled.
+ *
+ * This routine will always be called in process context.
+ */
+static inline void usb_gadget_disable_async_callbacks(struct usb_udc *udc)
+{
+ struct usb_gadget *gadget = udc->gadget;
+
+ if (gadget->ops->udc_async_callbacks)
+ gadget->ops->udc_async_callbacks(gadget, false);
+}
+
+/**
* usb_udc_release - release the usb_udc struct
* @dev: the dev member within usb_udc
*
@@ -1361,6 +1408,7 @@ static void usb_gadget_remove_driver(str
kobject_uevent(&udc->dev.kobj, KOBJ_CHANGE);
usb_gadget_disconnect(udc->gadget);
+ usb_gadget_disable_async_callbacks(udc);
if (udc->gadget->irq)
synchronize_irq(udc->gadget->irq);
udc->driver->unbind(udc->gadget);
@@ -1442,6 +1490,7 @@ static int udc_bind_to_driver(struct usb
driver->unbind(udc->gadget);
goto err1;
}
+ usb_gadget_enable_async_callbacks(udc);
usb_udc_connect_control(udc);
kobject_uevent(&udc->dev.kobj, KOBJ_CHANGE);
Index: usb-devel/include/linux/usb/gadget.h
===================================================================
--- usb-devel.orig/include/linux/usb/gadget.h
+++ usb-devel/include/linux/usb/gadget.h
@@ -325,6 +325,7 @@ struct usb_gadget_ops {
void (*udc_set_speed)(struct usb_gadget *, enum usb_device_speed);
void (*udc_set_ssp_rate)(struct usb_gadget *gadget,
enum usb_ssp_rate rate);
+ void (*udc_async_callbacks)(struct usb_gadget *gadget, bool enable);
struct usb_ep *(*match_ep)(struct usb_gadget *,
struct usb_endpoint_descriptor *,
struct usb_ss_ep_comp_descriptor *);
^ permalink raw reply [flat|nested] 2+ messages in thread
* Re: [PATCH 1/4] USB: UDC core: Add udc_async_callbacks gadget op
2021-05-20 20:21 [PATCH 1/4] USB: UDC core: Add udc_async_callbacks gadget op Alan Stern
@ 2021-06-04 5:18 ` Felipe Balbi
0 siblings, 0 replies; 2+ messages in thread
From: Felipe Balbi @ 2021-06-04 5:18 UTC (permalink / raw)
To: Alan Stern; +Cc: USB mailing list
[-- Attachment #1: Type: text/plain, Size: 1278 bytes --]
Alan Stern <stern@rowland.harvard.edu> writes:
> The Gadget API has a theoretical race when a gadget driver is unbound.
> Although the pull-up is turned off before the driver's ->unbind
> callback runs, if the USB cable were to be unplugged at just the wrong
> moment there would be nothing to prevent the UDC driver from invoking
> the ->disconnect callback after the unbind has finished. In theory,
> other asynchronous callbacks could also happen during the time before
> the UDC driver's udc_stop routine is called, and the gadget driver
> would not be prepared to handle any of them.
>
> We need a way to tell UDC drivers to stop issuing asynchronous (that is,
> ->suspend, ->resume, ->disconnect, ->reset, or ->setup) callbacks at
> some point after the pull-up has been turned off and before the
> ->unbind callback runs. This patch adds a new ->udc_async_callbacks
> callback to the usb_gadget_ops structure for precisely this purpose,
> and it adds the corresponding support to the UDC core.
>
> Later patches in this series add support for udc_async_callbacks to
> several UDC drivers.
>
> Signed-off-by: Alan Stern <stern@rowland.harvard.edu>
Thank you for working on this, Alan.
Acked-by: Felipe Balbi <balbi@kernel.org>
--
balbi
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 511 bytes --]
^ permalink raw reply [flat|nested] 2+ messages in thread
end of thread, other threads:[~2021-06-04 5:19 UTC | newest]
Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-05-20 20:21 [PATCH 1/4] USB: UDC core: Add udc_async_callbacks gadget op Alan Stern
2021-06-04 5:18 ` Felipe Balbi
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.