Commit 74bb3508 authored by David Brownell's avatar David Brownell Committed by Greg Kroah-Hartman

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: default avatarDavid Brownell <dbrownell@users.sourceforge.net>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@suse.de>
parent e13c594f
...@@ -1841,7 +1841,7 @@ static int musb_urb_enqueue( ...@@ -1841,7 +1841,7 @@ static int musb_urb_enqueue(
unsigned long flags; unsigned long flags;
struct musb *musb = hcd_to_musb(hcd); struct musb *musb = hcd_to_musb(hcd);
struct usb_host_endpoint *hep = urb->ep; struct usb_host_endpoint *hep = urb->ep;
struct musb_qh *qh = hep->hcpriv; struct musb_qh *qh;
struct usb_endpoint_descriptor *epd = &hep->desc; struct usb_endpoint_descriptor *epd = &hep->desc;
int ret; int ret;
unsigned type_reg; unsigned type_reg;
...@@ -1853,22 +1853,21 @@ static int musb_urb_enqueue( ...@@ -1853,22 +1853,21 @@ static int musb_urb_enqueue(
spin_lock_irqsave(&musb->lock, flags); spin_lock_irqsave(&musb->lock, flags);
ret = usb_hcd_link_urb_to_ep(hcd, urb); 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); spin_unlock_irqrestore(&musb->lock, flags);
if (ret)
return ret;
/* DMA mapping was already done, if needed, and this urb is on /* 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 * hep->urb_list now ... so we're done, unless hep wasn't yet
* yet scheduled onto a live qh. * scheduled onto a live qh.
* *
* REVISIT best to keep hep->hcpriv valid until the endpoint gets * REVISIT best to keep hep->hcpriv valid until the endpoint gets
* disabled, testing for empty qh->ring and avoiding qh setup costs * disabled, testing for empty qh->ring and avoiding qh setup costs
* except for the first urb queued after a config change. * except for the first urb queued after a config change.
*/ */
if (qh) { if (qh || ret)
urb->hcpriv = qh; return ret;
return 0;
}
/* Allocate and initialize qh, minimizing the work done each time /* Allocate and initialize qh, minimizing the work done each time
* hw_ep gets reprogrammed, or with irqs blocked. Then schedule it. * hw_ep gets reprogrammed, or with irqs blocked. Then schedule it.
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment