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>
This commit is contained in:
committed by
Greg Kroah-Hartman
parent
e13c594f3a
commit
74bb35083d
@@ -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(
|
|||||||
|
|
||||||
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.
|
||||||
|
Reference in New Issue
Block a user