[PATCH] USB: Fix USB suspend/resume crasher (#2)
This patch closes the IRQ race and makes various other OHCI & EHCI code path safer vs. suspend/resume. I've been able to (finally !) successfully suspend and resume various Mac models, with or without USB mouse plugged, or plugging while asleep, or unplugging while asleep etc... all without a crash. Alan, please verify the UHCI bit I did, I only verified that it builds. It's very simple so I wouldn't expect any issue there. If you aren't confident, then just drop the hunks that change uhci-hcd.c I also made the patch a little bit more "safer" by making sure the store to the interrupt register that disables interrupts is not posted before I set the flag and drop the spinlock. Without this patch, you cannot reliably sleep/wakeup any recent Mac, and I suspect PCs have some more sneaky issues too (they don't frankly crash with machine checks because x86 tend to silently swallow PCI errors but that won't last afaik, at least PCI Express will blow up in those situations, but the USB code may still misbehave). Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
This commit is contained in:

zatwierdzone przez
Greg Kroah-Hartman

rodzic
d3420ba493
commit
8de9840265
@@ -602,6 +602,12 @@ static int intr_submit (
|
||||
|
||||
spin_lock_irqsave (&ehci->lock, flags);
|
||||
|
||||
if (unlikely(!test_bit(HCD_FLAG_HW_ACCESSIBLE,
|
||||
&ehci_to_hcd(ehci)->flags))) {
|
||||
status = -ESHUTDOWN;
|
||||
goto done;
|
||||
}
|
||||
|
||||
/* get qh and force any scheduling errors */
|
||||
INIT_LIST_HEAD (&empty);
|
||||
qh = qh_append_tds (ehci, urb, &empty, epnum, &ep->hcpriv);
|
||||
@@ -1456,7 +1462,11 @@ static int itd_submit (struct ehci_hcd *ehci, struct urb *urb,
|
||||
|
||||
/* schedule ... need to lock */
|
||||
spin_lock_irqsave (&ehci->lock, flags);
|
||||
status = iso_stream_schedule (ehci, urb, stream);
|
||||
if (unlikely(!test_bit(HCD_FLAG_HW_ACCESSIBLE,
|
||||
&ehci_to_hcd(ehci)->flags)))
|
||||
status = -ESHUTDOWN;
|
||||
else
|
||||
status = iso_stream_schedule (ehci, urb, stream);
|
||||
if (likely (status == 0))
|
||||
itd_link_urb (ehci, urb, ehci->periodic_size << 3, stream);
|
||||
spin_unlock_irqrestore (&ehci->lock, flags);
|
||||
@@ -1815,7 +1825,11 @@ static int sitd_submit (struct ehci_hcd *ehci, struct urb *urb,
|
||||
|
||||
/* schedule ... need to lock */
|
||||
spin_lock_irqsave (&ehci->lock, flags);
|
||||
status = iso_stream_schedule (ehci, urb, stream);
|
||||
if (unlikely(!test_bit(HCD_FLAG_HW_ACCESSIBLE,
|
||||
&ehci_to_hcd(ehci)->flags)))
|
||||
status = -ESHUTDOWN;
|
||||
else
|
||||
status = iso_stream_schedule (ehci, urb, stream);
|
||||
if (status == 0)
|
||||
sitd_link_urb (ehci, urb, ehci->periodic_size << 3, stream);
|
||||
spin_unlock_irqrestore (&ehci->lock, flags);
|
||||
|
Reference in New Issue
Block a user