aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBart Westgeest <bart@elbrys.com>2011-11-01 15:01:28 -0400
committerGreg Kroah-Hartman <gregkh@suse.de>2011-11-26 20:37:38 -0500
commit438957f8d4a84daa7fa5be6978ad5897a2e9e5e5 (patch)
treec4a872aae2865395369f1572288cef3ece388c3b
parentcaca6a03d365883564885f2c1da3e88dcf65d139 (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.c10
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);