* [PATCH 4/4] USB: UDC: Implement udc_async_callbacks in net2272
@ 2021-05-20 20:22 Alan Stern
2021-06-04 5:23 ` Felipe Balbi
0 siblings, 1 reply; 2+ messages in thread
From: Alan Stern @ 2021-05-20 20:22 UTC (permalink / raw)
To: Felipe Balbi; +Cc: USB mailing list
This patch adds a udc_async_callbacks handler to the net2272 UDC
driver, which will prevent a theoretical race during gadget unbinding.
The net2272 driver is sufficiently complicated that I didn't want to
mess around with IRQ settings. Instead, the patch simply adds a new
flag to control async callbacks, and checks the flag before issuing
any of them.
Signed-off-by: Alan Stern <stern@rowland.harvard.edu>
---
[as1959]
drivers/usb/gadget/udc/net2272.c | 41 +++++++++++++++++++++++++--------------
drivers/usb/gadget/udc/net2272.h | 1
2 files changed, 28 insertions(+), 14 deletions(-)
Index: usb-devel/drivers/usb/gadget/udc/net2272.c
===================================================================
--- usb-devel.orig/drivers/usb/gadget/udc/net2272.c
+++ usb-devel/drivers/usb/gadget/udc/net2272.c
@@ -1149,6 +1149,7 @@ net2272_pullup(struct usb_gadget *_gadge
static int net2272_start(struct usb_gadget *_gadget,
struct usb_gadget_driver *driver);
static int net2272_stop(struct usb_gadget *_gadget);
+static void net2272_async_callbacks(struct usb_gadget *_gadget, bool enable);
static const struct usb_gadget_ops net2272_ops = {
.get_frame = net2272_get_frame,
@@ -1157,6 +1158,7 @@ static const struct usb_gadget_ops net22
.pullup = net2272_pullup,
.udc_start = net2272_start,
.udc_stop = net2272_stop,
+ .udc_async_callbacks = net2272_async_callbacks,
};
/*---------------------------------------------------------------------------*/
@@ -1475,7 +1477,7 @@ stop_activity(struct net2272 *dev, struc
net2272_dequeue_all(&dev->ep[i]);
/* report disconnect; the driver is already quiesced */
- if (driver) {
+ if (dev->async_callbacks && driver) {
spin_unlock(&dev->lock);
driver->disconnect(&dev->gadget);
spin_lock(&dev->lock);
@@ -1500,6 +1502,15 @@ static int net2272_stop(struct usb_gadge
return 0;
}
+static void net2272_async_callbacks(struct usb_gadget *_gadget, bool enable)
+{
+ struct net2272 *dev = container_of(_gadget, struct net2272, gadget);
+
+ spin_lock_irq(&dev->lock);
+ dev->async_callbacks = enable;
+ spin_unlock_irq(&dev->lock);
+}
+
/*---------------------------------------------------------------------------*/
/* handle ep-a/ep-b dma completions */
static void
@@ -1909,9 +1920,11 @@ net2272_handle_stat0_irqs(struct net2272
u.r.bRequestType, u.r.bRequest,
u.r.wValue, u.r.wIndex,
net2272_ep_read(ep, EP_CFG));
- spin_unlock(&dev->lock);
- tmp = dev->driver->setup(&dev->gadget, &u.r);
- spin_lock(&dev->lock);
+ if (dev->async_callbacks) {
+ spin_unlock(&dev->lock);
+ tmp = dev->driver->setup(&dev->gadget, &u.r);
+ spin_lock(&dev->lock);
+ }
}
/* stall ep0 on error */
@@ -1993,14 +2006,14 @@ net2272_handle_stat1_irqs(struct net2272
if (disconnect || reset) {
stop_activity(dev, dev->driver);
net2272_ep0_start(dev);
- spin_unlock(&dev->lock);
- if (reset)
- usb_gadget_udc_reset
- (&dev->gadget, dev->driver);
- else
- (dev->driver->disconnect)
- (&dev->gadget);
- spin_lock(&dev->lock);
+ if (dev->async_callbacks) {
+ spin_unlock(&dev->lock);
+ if (reset)
+ usb_gadget_udc_reset(&dev->gadget, dev->driver);
+ else
+ (dev->driver->disconnect)(&dev->gadget);
+ spin_lock(&dev->lock);
+ }
return;
}
}
@@ -2014,14 +2027,14 @@ net2272_handle_stat1_irqs(struct net2272
if (stat & tmp) {
net2272_write(dev, IRQSTAT1, tmp);
if (stat & (1 << SUSPEND_REQUEST_INTERRUPT)) {
- if (dev->driver->suspend)
+ if (dev->async_callbacks && dev->driver->suspend)
dev->driver->suspend(&dev->gadget);
if (!enable_suspend) {
stat &= ~(1 << SUSPEND_REQUEST_INTERRUPT);
dev_dbg(dev->dev, "Suspend disabled, ignoring\n");
}
} else {
- if (dev->driver->resume)
+ if (dev->async_callbacks && dev->driver->resume)
dev->driver->resume(&dev->gadget);
}
stat &= ~tmp;
Index: usb-devel/drivers/usb/gadget/udc/net2272.h
===================================================================
--- usb-devel.orig/drivers/usb/gadget/udc/net2272.h
+++ usb-devel/drivers/usb/gadget/udc/net2272.h
@@ -442,6 +442,7 @@ struct net2272 {
softconnect:1,
wakeup:1,
added:1,
+ async_callbacks:1,
dma_eot_polarity:1,
dma_dack_polarity:1,
dma_dreq_polarity:1,
^ permalink raw reply [flat|nested] 2+ messages in thread
* Re: [PATCH 4/4] USB: UDC: Implement udc_async_callbacks in net2272
2021-05-20 20:22 [PATCH 4/4] USB: UDC: Implement udc_async_callbacks in net2272 Alan Stern
@ 2021-06-04 5:23 ` Felipe Balbi
0 siblings, 0 replies; 2+ messages in thread
From: Felipe Balbi @ 2021-06-04 5:23 UTC (permalink / raw)
To: Alan Stern; +Cc: USB mailing list
[-- Attachment #1: Type: text/plain, Size: 545 bytes --]
Alan Stern <stern@rowland.harvard.edu> writes:
> This patch adds a udc_async_callbacks handler to the net2272 UDC
> driver, which will prevent a theoretical race during gadget unbinding.
>
> The net2272 driver is sufficiently complicated that I didn't want to
> mess around with IRQ settings. Instead, the patch simply adds a new
> flag to control async callbacks, and checks the flag before issuing
> any of them.
>
> Signed-off-by: Alan Stern <stern@rowland.harvard.edu>
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:23 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:22 [PATCH 4/4] USB: UDC: Implement udc_async_callbacks in net2272 Alan Stern
2021-06-04 5:23 ` 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.