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); |