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>
This commit is contained in:
committed by
Greg Kroah-Hartman
parent
caca6a03d3
commit
438957f8d4
@@ -68,6 +68,7 @@ static void vhci_recv_ret_submit(struct vhci_device *vdev,
|
|||||||
{
|
{
|
||||||
struct usbip_device *ud = &vdev->ud;
|
struct usbip_device *ud = &vdev->ud;
|
||||||
struct urb *urb;
|
struct urb *urb;
|
||||||
|
unsigned long flags;
|
||||||
|
|
||||||
spin_lock(&vdev->priv_lock);
|
spin_lock(&vdev->priv_lock);
|
||||||
urb = pickup_urb_and_free_priv(vdev, pdu->base.seqnum);
|
urb = pickup_urb_and_free_priv(vdev, pdu->base.seqnum);
|
||||||
@@ -101,9 +102,9 @@ static void vhci_recv_ret_submit(struct vhci_device *vdev,
|
|||||||
|
|
||||||
usbip_dbg_vhci_rx("now giveback urb %p\n", urb);
|
usbip_dbg_vhci_rx("now giveback urb %p\n", urb);
|
||||||
|
|
||||||
spin_lock(&the_controller->lock);
|
spin_lock_irqsave(&the_controller->lock, flags);
|
||||||
usb_hcd_unlink_urb_from_ep(vhci_to_hcd(the_controller), urb);
|
usb_hcd_unlink_urb_from_ep(vhci_to_hcd(the_controller), urb);
|
||||||
spin_unlock(&the_controller->lock);
|
spin_unlock_irqrestore(&the_controller->lock, flags);
|
||||||
|
|
||||||
usb_hcd_giveback_urb(vhci_to_hcd(the_controller), urb, urb->status);
|
usb_hcd_giveback_urb(vhci_to_hcd(the_controller), urb, urb->status);
|
||||||
|
|
||||||
@@ -141,6 +142,7 @@ static void vhci_recv_ret_unlink(struct vhci_device *vdev,
|
|||||||
{
|
{
|
||||||
struct vhci_unlink *unlink;
|
struct vhci_unlink *unlink;
|
||||||
struct urb *urb;
|
struct urb *urb;
|
||||||
|
unsigned long flags;
|
||||||
|
|
||||||
usbip_dump_header(pdu);
|
usbip_dump_header(pdu);
|
||||||
|
|
||||||
@@ -170,9 +172,9 @@ static void vhci_recv_ret_unlink(struct vhci_device *vdev,
|
|||||||
urb->status = pdu->u.ret_unlink.status;
|
urb->status = pdu->u.ret_unlink.status;
|
||||||
pr_info("urb->status %d\n", urb->status);
|
pr_info("urb->status %d\n", urb->status);
|
||||||
|
|
||||||
spin_lock(&the_controller->lock);
|
spin_lock_irqsave(&the_controller->lock, flags);
|
||||||
usb_hcd_unlink_urb_from_ep(vhci_to_hcd(the_controller), urb);
|
usb_hcd_unlink_urb_from_ep(vhci_to_hcd(the_controller), urb);
|
||||||
spin_unlock(&the_controller->lock);
|
spin_unlock_irqrestore(&the_controller->lock, flags);
|
||||||
|
|
||||||
usb_hcd_giveback_urb(vhci_to_hcd(the_controller), urb,
|
usb_hcd_giveback_urb(vhci_to_hcd(the_controller), urb,
|
||||||
urb->status);
|
urb->status);
|
||||||
|
|||||||
Reference in New Issue
Block a user