diff options
author | David Brownell <dbrownell@users.sourceforge.net> | 2009-03-27 01:36:57 +0100 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@suse.de> | 2009-04-17 19:50:25 +0200 |
commit | 74bb35083d889c696a0f54be76ffe85a66dcbdc1 (patch) | |
tree | 9cb99faa41416c1af594a76345469fea57a9fd9e /drivers/usb | |
parent | USB: fix oops in cdc-wdm in case of malformed descriptors (diff) | |
download | linux-74bb35083d889c696a0f54be76ffe85a66dcbdc1.tar.xz linux-74bb35083d889c696a0f54be76ffe85a66dcbdc1.zip |
USB: musb_host, minor enqueue locking fix (v2)
Someone noted that the enqueue path used an unlocked access
for usb_host_endpoint->hcpriv ... fix that, by being safe
and always accessing it under spinlock protection.
Signed-off-by: David Brownell <dbrownell@users.sourceforge.net>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers/usb')
-rw-r--r-- | drivers/usb/musb/musb_host.c | 17 |
1 files changed, 8 insertions, 9 deletions
diff --git a/drivers/usb/musb/musb_host.c b/drivers/usb/musb/musb_host.c index 499c431a6d62..ff095956ca96 100644 --- a/drivers/usb/musb/musb_host.c +++ b/drivers/usb/musb/musb_host.c @@ -1841,7 +1841,7 @@ static int musb_urb_enqueue( unsigned long flags; struct musb *musb = hcd_to_musb(hcd); struct usb_host_endpoint *hep = urb->ep; - struct musb_qh *qh = hep->hcpriv; + struct musb_qh *qh; struct usb_endpoint_descriptor *epd = &hep->desc; int ret; unsigned type_reg; @@ -1853,22 +1853,21 @@ static int musb_urb_enqueue( spin_lock_irqsave(&musb->lock, flags); ret = usb_hcd_link_urb_to_ep(hcd, urb); + qh = ret ? NULL : hep->hcpriv; + if (qh) + urb->hcpriv = qh; spin_unlock_irqrestore(&musb->lock, flags); - if (ret) - return ret; /* DMA mapping was already done, if needed, and this urb is on - * hep->urb_list ... so there's little to do unless hep wasn't - * yet scheduled onto a live qh. + * hep->urb_list now ... so we're done, unless hep wasn't yet + * scheduled onto a live qh. * * REVISIT best to keep hep->hcpriv valid until the endpoint gets * disabled, testing for empty qh->ring and avoiding qh setup costs * except for the first urb queued after a config change. */ - if (qh) { - urb->hcpriv = qh; - return 0; - } + if (qh || ret) + return ret; /* Allocate and initialize qh, minimizing the work done each time * hw_ep gets reprogrammed, or with irqs blocked. Then schedule it. |