Commit 89e62afe authored by Johannes Erdfelt's avatar Johannes Erdfelt Committed by Greg Kroah-Hartman

[PATCH] uhci.c SMP deadlock

This patch fixes a bug reported by Greg and David, as well as some other
people recently.

uhci.c would call wait_ms, which can sleep, with spinlocks held. There
are two places where this happens, but only one was the cause of the
problem.
parent 806af7cc
...@@ -1820,6 +1820,9 @@ static int uhci_unlink_urb(struct urb *urb) ...@@ -1820,6 +1820,9 @@ static int uhci_unlink_urb(struct urb *urb)
} else { } else {
urb->status = -ENOENT; urb->status = -ENOENT;
spin_unlock(&urb->lock);
spin_unlock_irqrestore(&uhci->urb_list_lock, flags);
if (in_interrupt()) { /* wait at least 1 frame */ if (in_interrupt()) { /* wait at least 1 frame */
static int errorcount = 10; static int errorcount = 10;
...@@ -1829,9 +1832,6 @@ static int uhci_unlink_urb(struct urb *urb) ...@@ -1829,9 +1832,6 @@ static int uhci_unlink_urb(struct urb *urb)
} else } else
schedule_timeout(1+1*HZ/1000); schedule_timeout(1+1*HZ/1000);
spin_unlock(&urb->lock);
spin_unlock_irqrestore(&uhci->urb_list_lock, flags);
uhci_call_completion(urb); uhci_call_completion(urb);
} }
} }
...@@ -2202,12 +2202,12 @@ static int rh_submit_urb(struct urb *urb) ...@@ -2202,12 +2202,12 @@ static int rh_submit_urb(struct urb *urb)
OK(0); OK(0);
case RH_PORT_RESET: case RH_PORT_RESET:
SET_RH_PORTSTAT(USBPORTSC_PR); SET_RH_PORTSTAT(USBPORTSC_PR);
wait_ms(50); /* USB v1.1 7.1.7.3 */ mdelay(50); /* USB v1.1 7.1.7.3 */
uhci->rh.c_p_r[wIndex - 1] = 1; uhci->rh.c_p_r[wIndex - 1] = 1;
CLR_RH_PORTSTAT(USBPORTSC_PR); CLR_RH_PORTSTAT(USBPORTSC_PR);
udelay(10); udelay(10);
SET_RH_PORTSTAT(USBPORTSC_PE); SET_RH_PORTSTAT(USBPORTSC_PE);
wait_ms(10); mdelay(10);
SET_RH_PORTSTAT(0xa); SET_RH_PORTSTAT(0xa);
OK(0); OK(0);
case RH_PORT_POWER: case RH_PORT_POWER:
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment