diff options
| author | Bart Westgeest <bart@elbrys.com> | 2011-11-01 15:01:28 -0400 |
|---|---|---|
| committer | Greg Kroah-Hartman <gregkh@suse.de> | 2011-11-26 20:37:38 -0500 |
| commit | 438957f8d4a84daa7fa5be6978ad5897a2e9e5e5 (patch) | |
| tree | c4a872aae2865395369f1572288cef3ece388c3b | |
| parent | caca6a03d365883564885f2c1da3e88dcf65d139 (diff) | |
staging: usbip: bugfix for deadlock
Interrupts must be disabled prior to calling usb_hcd_unlink_urb_from_ep.
If interrupts are not disabled, it can potentially lead to a deadlock.
The deadlock is readily reproduceable on a slower (ARM based) device
such as the TI Pandaboard.
Signed-off-by: Bart Westgeest <bart@elbrys.com>
Cc: stable <stable@vger.kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
| -rw-r--r-- | drivers/staging/usbip/vhci_rx.c | 10 |
1 files changed, 6 insertions, 4 deletions
diff --git a/drivers/staging/usbip/vhci_rx.c b/drivers/staging/usbip/vhci_rx.c index 09c44abb89e8..3872b8cccdcf 100644 --- a/drivers/staging/usbip/vhci_rx.c +++ b/drivers/staging/usbip/vhci_rx.c | |||
| @@ -68,6 +68,7 @@ static void vhci_recv_ret_submit(struct vhci_device *vdev, | |||
| 68 | { | 68 | { |
| 69 | struct usbip_device *ud = &vdev->ud; | 69 | struct usbip_device *ud = &vdev->ud; |
| 70 | struct urb *urb; | 70 | struct urb *urb; |
| 71 | unsigned long flags; | ||
| 71 | 72 | ||
| 72 | spin_lock(&vdev->priv_lock); | 73 | spin_lock(&vdev->priv_lock); |
| 73 | urb = pickup_urb_and_free_priv(vdev, pdu->base.seqnum); | 74 | urb = pickup_urb_and_free_priv(vdev, pdu->base.seqnum); |
| @@ -101,9 +102,9 @@ static void vhci_recv_ret_submit(struct vhci_device *vdev, | |||
| 101 | 102 | ||
| 102 | usbip_dbg_vhci_rx("now giveback urb %p\n", urb); | 103 | usbip_dbg_vhci_rx("now giveback urb %p\n", urb); |
| 103 | 104 | ||
| 104 | spin_lock(&the_controller->lock); | 105 | spin_lock_irqsave(&the_controller->lock, flags); |
| 105 | usb_hcd_unlink_urb_from_ep(vhci_to_hcd(the_controller), urb); | 106 | usb_hcd_unlink_urb_from_ep(vhci_to_hcd(the_controller), urb); |
| 106 | spin_unlock(&the_controller->lock); | 107 | spin_unlock_irqrestore(&the_controller->lock, flags); |
| 107 | 108 | ||
| 108 | usb_hcd_giveback_urb(vhci_to_hcd(the_controller), urb, urb->status); | 109 | usb_hcd_giveback_urb(vhci_to_hcd(the_controller), urb, urb->status); |
| 109 | 110 | ||
| @@ -141,6 +142,7 @@ static void vhci_recv_ret_unlink(struct vhci_device *vdev, | |||
| 141 | { | 142 | { |
| 142 | struct vhci_unlink *unlink; | 143 | struct vhci_unlink *unlink; |
| 143 | struct urb *urb; | 144 | struct urb *urb; |
| 145 | unsigned long flags; | ||
| 144 | 146 | ||
| 145 | usbip_dump_header(pdu); | 147 | usbip_dump_header(pdu); |
| 146 | 148 | ||
| @@ -170,9 +172,9 @@ static void vhci_recv_ret_unlink(struct vhci_device *vdev, | |||
| 170 | urb->status = pdu->u.ret_unlink.status; | 172 | urb->status = pdu->u.ret_unlink.status; |
| 171 | pr_info("urb->status %d\n", urb->status); | 173 | pr_info("urb->status %d\n", urb->status); |
| 172 | 174 | ||
| 173 | spin_lock(&the_controller->lock); | 175 | spin_lock_irqsave(&the_controller->lock, flags); |
| 174 | usb_hcd_unlink_urb_from_ep(vhci_to_hcd(the_controller), urb); | 176 | usb_hcd_unlink_urb_from_ep(vhci_to_hcd(the_controller), urb); |
| 175 | spin_unlock(&the_controller->lock); | 177 | spin_unlock_irqrestore(&the_controller->lock, flags); |
| 176 | 178 | ||
| 177 | usb_hcd_giveback_urb(vhci_to_hcd(the_controller), urb, | 179 | usb_hcd_giveback_urb(vhci_to_hcd(the_controller), urb, |
| 178 | urb->status); | 180 | urb->status); |
