diff options
author | Greg Kroah-Hartman <gregkh@suse.de> | 2005-11-23 14:34:10 -0800 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@suse.de> | 2005-11-23 14:34:10 -0800 |
commit | f5fdb9b98ea0c566f299a8cbd9b3b9f65020f5d8 (patch) | |
tree | ea4d73f274bbe6e9a3e6a50aa1d0e018655e396a /usb | |
parent | b493d45d58c5b347d2d62f8aa18dec9a8dea6032 (diff) | |
download | patches-f5fdb9b98ea0c566f299a8cbd9b3b9f65020f5d8.tar.gz |
usb, pci, and other patches
Diffstat (limited to 'usb')
5 files changed, 428 insertions, 37 deletions
diff --git a/usb/isp116x-hcd-cleanup.patch b/usb/isp116x-hcd-cleanup.patch index 1621512681754..8efda5f5e1313 100644 --- a/usb/isp116x-hcd-cleanup.patch +++ b/usb/isp116x-hcd-cleanup.patch @@ -35,9 +35,10 @@ Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> drivers/usb/host/isp116x.h | 83 +++++-- 3 files changed, 230 insertions(+), 288 deletions(-) ---- gregkh-2.6.orig/drivers/usb/host/isp116x.h 2005-11-20 16:31:05.000000000 -0800 -+++ gregkh-2.6/drivers/usb/host/isp116x.h 2005-11-20 16:32:52.000000000 -0800 -@@ -259,7 +259,7 @@ +--- +--- gregkh-2.6.orig/drivers/usb/host/isp116x.h ++++ gregkh-2.6/drivers/usb/host/isp116x.h +@@ -259,7 +259,7 @@ struct isp116x { struct isp116x_platform_data *board; @@ -46,7 +47,7 @@ Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> unsigned long stat1, stat2, stat4, stat8, stat16; /* HC registers */ -@@ -450,7 +450,7 @@ +@@ -450,7 +450,7 @@ static void isp116x_write_reg32(struct i isp116x_write_data32(isp116x, (u32) val); } @@ -55,7 +56,7 @@ Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> if ((r) < 0x20) { \ DBG("%-12s[%02x]: %08x\n", #r, \ r, isp116x_read_reg32(d, r)); \ -@@ -459,35 +459,60 @@ +@@ -459,35 +459,60 @@ static void isp116x_write_reg32(struct i r, isp116x_read_reg16(d, r)); \ } \ } @@ -143,8 +144,8 @@ Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> } #if defined(URB_TRACE) ---- gregkh-2.6.orig/drivers/usb/host/isp116x-hcd.c 2005-11-20 16:32:51.000000000 -0800 -+++ gregkh-2.6/drivers/usb/host/isp116x-hcd.c 2005-11-20 16:32:52.000000000 -0800 +--- gregkh-2.6.orig/drivers/usb/host/isp116x-hcd.c ++++ gregkh-2.6/drivers/usb/host/isp116x-hcd.c @@ -55,19 +55,13 @@ /* enqueuing/finishing log of urbs */ //#define URB_TRACE @@ -183,7 +184,7 @@ Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> #define DRIVER_DESC "ISP116x USB Host Controller Driver" MODULE_DESCRIPTION(DRIVER_DESC); -@@ -305,9 +295,8 @@ +@@ -305,9 +295,8 @@ static void postproc_atl_queue(struct is udev = urb->dev; ptd = &ep->ptd; cc = PTD_GET_CC(ptd); @@ -194,7 +195,7 @@ Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> /* Data underrun is special. For allowed underrun we clear the error and continue as normal. For -@@ -420,7 +409,7 @@ +@@ -420,7 +409,7 @@ static void postproc_atl_queue(struct is ep->nextpid = 0; break; default: @@ -203,7 +204,7 @@ Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> } spin_unlock(&urb->lock); } -@@ -628,8 +617,12 @@ +@@ -628,8 +617,12 @@ static irqreturn_t isp116x_irq(struct us u32 intstat = isp116x_read_reg32(isp116x, HCINTSTAT); isp116x_write_reg32(isp116x, HCINTSTAT, intstat); if (intstat & HCINT_UE) { @@ -218,7 +219,7 @@ Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> } if (intstat & HCINT_RHSC) /* When root hub or any of its ports is going -@@ -640,7 +633,6 @@ +@@ -640,7 +633,6 @@ static irqreturn_t isp116x_irq(struct us if (intstat & HCINT_RD) { DBG("---- remote wakeup\n"); usb_hcd_resume_root_hub(hcd); @@ -226,7 +227,7 @@ Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> } irqstat &= ~HCuPINT_OPR; ret = IRQ_HANDLED; -@@ -651,6 +643,7 @@ +@@ -651,6 +643,7 @@ static irqreturn_t isp116x_irq(struct us } isp116x_write_reg16(isp116x, HCuPINTENB, isp116x->irqenb); @@ -234,7 +235,7 @@ Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> spin_unlock(&isp116x->lock); return ret; } -@@ -724,6 +717,7 @@ +@@ -724,6 +717,7 @@ static int isp116x_urb_enqueue(struct us spin_lock_irqsave(&isp116x->lock, flags); if (!HC_IS_RUNNING(hcd->state)) { @@ -242,7 +243,7 @@ Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> ret = -ENODEV; goto fail; } -@@ -888,7 +882,7 @@ +@@ -888,7 +882,7 @@ static void isp116x_endpoint_disable(str struct usb_host_endpoint *hep) { int i; @@ -251,7 +252,7 @@ Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> if (!ep) return; -@@ -916,8 +910,6 @@ +@@ -916,8 +910,6 @@ static int isp116x_get_frame(struct usb_ return (int)fmnum; } @@ -260,7 +261,7 @@ Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> /* Adapted from ohci-hub.c. Currently we don't support autosuspend. */ -@@ -968,11 +960,10 @@ +@@ -968,11 +960,10 @@ static void isp116x_hub_descriptor(struc desc->bHubContrCurrent = 0; desc->bNbrPorts = (u8) (reg & 0x3); /* Power switching, device type, overcurrent. */ @@ -274,7 +275,7 @@ Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> desc->bitmap[1] = ~0; } -@@ -1159,145 +1150,9 @@ +@@ -1159,145 +1150,9 @@ static int isp116x_hub_control(struct us return ret; } @@ -421,7 +422,7 @@ Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> static void dump_irq(struct seq_file *s, char *label, u16 mask) { -@@ -1321,13 +1176,9 @@ +@@ -1321,13 +1176,9 @@ static void dump_int(struct seq_file *s, mask & HCINT_SF ? " sof" : "", mask & HCINT_SO ? " so" : ""); } @@ -436,7 +437,7 @@ Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> seq_printf(s, "%s\n%s version %s\n", isp116x_to_hcd(isp116x)->product_desc, hcd_name, -@@ -1343,105 +1194,50 @@ +@@ -1343,105 +1194,50 @@ static int proc_isp116x_show(struct seq_ } spin_lock_irq(&isp116x->lock); @@ -561,7 +562,7 @@ Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> /*-----------------------------------------------------------------*/ -@@ -1476,7 +1272,7 @@ +@@ -1476,7 +1272,7 @@ static int isp116x_reset(struct usb_hcd struct isp116x *isp116x = hcd_to_isp116x(hcd); unsigned long t; u16 clkrdy = 0; @@ -570,7 +571,7 @@ Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> ret = isp116x_sw_reset(isp116x); if (ret) -@@ -1492,7 +1288,7 @@ +@@ -1492,7 +1288,7 @@ static int isp116x_reset(struct usb_hcd break; } if (!clkrdy) { @@ -579,7 +580,7 @@ Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> /* After sw_reset the clock won't report to be ready, if H_WAKEUP pin is high. */ ERR("Please make sure that the H_WAKEUP pin is pulled low!\n"); -@@ -1610,12 +1406,128 @@ +@@ -1610,12 +1406,128 @@ static int isp116x_start(struct usb_hcd isp116x_write_reg32(isp116x, HCRHPORT1, RH_PS_CCS); isp116x_write_reg32(isp116x, HCRHPORT2, RH_PS_CCS); @@ -710,7 +711,7 @@ Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> static struct hc_driver isp116x_hc_driver = { .description = hcd_name, -@@ -1745,12 +1657,19 @@ +@@ -1745,12 +1657,19 @@ static int __init isp116x_probe(struct p } ret = usb_add_hcd(hcd, irq, SA_INTERRUPT); @@ -732,7 +733,7 @@ Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> err6: usb_put_hcd(hcd); err5: -@@ -1772,13 +1691,9 @@ +@@ -1772,13 +1691,9 @@ static int __init isp116x_probe(struct p */ static int isp116x_suspend(struct platform_device *dev, pm_message_t state) { @@ -748,7 +749,7 @@ Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> } /* -@@ -1786,13 +1701,9 @@ +@@ -1786,13 +1701,9 @@ static int isp116x_suspend(struct platfo */ static int isp116x_resume(struct platform_device *dev) { @@ -764,9 +765,9 @@ Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> } #else ---- gregkh-2.6.orig/MAINTAINERS 2005-11-20 16:32:28.000000000 -0800 -+++ gregkh-2.6/MAINTAINERS 2005-11-20 16:32:52.000000000 -0800 -@@ -2613,6 +2613,12 @@ +--- gregkh-2.6.orig/MAINTAINERS ++++ gregkh-2.6/MAINTAINERS +@@ -2630,6 +2630,12 @@ L: linux-usb-users@lists.sourceforge.net L: linux-usb-devel@lists.sourceforge.net S: Maintained diff --git a/usb/remove-usb-private-semaphore.patch b/usb/remove-usb-private-semaphore.patch index 8d74a19c855d1..3183dd4117bb8 100644 --- a/usb/remove-usb-private-semaphore.patch +++ b/usb/remove-usb-private-semaphore.patch @@ -233,7 +233,7 @@ Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> if (retval) { usb_dev->bus->root_hub = NULL; dev_err (parent_dev, "can't register root hub for %s, %d\n", -@@ -1886,7 +1884,10 @@ void usb_remove_hcd(struct usb_hcd *hcd) +@@ -1891,7 +1889,10 @@ void usb_remove_hcd(struct usb_hcd *hcd) spin_lock_irq (&hcd_root_hub_lock); hcd->rh_registered = 0; spin_unlock_irq (&hcd_root_hub_lock); @@ -297,7 +297,7 @@ Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> } --- gregkh-2.6.orig/drivers/usb/host/ohci-hub.c +++ gregkh-2.6/drivers/usb/host/ohci-hub.c -@@ -359,7 +359,7 @@ done: +@@ -372,7 +372,7 @@ done: & ohci->hc_control) == OHCI_USB_OPER && time_after (jiffies, ohci->next_statechange) diff --git a/usb/usb-fix-usb-suspend-resume-crasher.patch b/usb/usb-fix-usb-suspend-resume-crasher.patch new file mode 100644 index 0000000000000..9964f7e486a72 --- /dev/null +++ b/usb/usb-fix-usb-suspend-resume-crasher.patch @@ -0,0 +1,390 @@ +From benh@kernel.crashing.org Tue Nov 22 22:47:24 2005 +Subject: USB: Fix USB suspend/resume crasher +From: Benjamin Herrenschmidt <benh@kernel.crashing.org> +To: David Brownell <david-b@pacbell.net> +Cc: Paul Mackerras <paulus@samba.org>, Andrew Morton <akpm@osdl.org>, Greg KH <greg@kroah.com>, Alan Stern <stern@rowland.harvard.edu> +Date: Wed, 23 Nov 2005 14:08:07 +1100 +Message-Id: <1132715288.26560.262.camel@gaston> + +This is my latest patch against current linus -git, it 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. There are still some races here or there in the USB code, but at +least the main cause of crash is now fixes by this patch (access to a +controller that has been suspended, due to either shared interrupts or +other code path). + +I haven't fixed UHCI as I don't have any HW to test, though I hope I +haven't broken it neither. Alan, I would appreciate if you could have a +look. + +This patch applies on top of the patch that moves the PowerMac specific +code out of ohci-pci.c to hcd-pci.c where it belongs. This patch isn't +upstream yet for reasons I don't fully understand (why does USB stuffs +has such a high latency for going upstream ?), I'm sending it as a reply +to this email for completeness. + +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> +--- + drivers/usb/core/hcd-pci.c | 3 ++- + drivers/usb/core/hcd.c | 15 ++++++++++----- + drivers/usb/core/hcd.h | 7 ++++++- + drivers/usb/host/ehci-pci.c | 24 +++++++++++++++++++++++- + drivers/usb/host/ehci-q.c | 24 ++++++++++++++++-------- + drivers/usb/host/ehci-sched.c | 18 ++++++++++++++++-- + drivers/usb/host/ohci-hcd.c | 6 +++++- + drivers/usb/host/ohci-hub.c | 24 ++++++++++++++++++++---- + drivers/usb/host/ohci-pci.c | 26 ++++++++++++++++++++++++-- + 9 files changed, 122 insertions(+), 25 deletions(-) + +--- gregkh-2.6.orig/drivers/usb/core/hcd-pci.c ++++ gregkh-2.6/drivers/usb/core/hcd-pci.c +@@ -219,6 +219,7 @@ int usb_hcd_pci_suspend (struct pci_dev + goto done; + } + } ++ synchronize_irq(dev->irq); + + /* FIXME until the generic PM interfaces change a lot more, this + * can't use PCI D1 and D2 states. For example, the confusion +@@ -392,7 +393,7 @@ int usb_hcd_pci_resume (struct pci_dev * + + dev->dev.power.power_state = PMSG_ON; + +- hcd->saw_irq = 0; ++ clear_bit(HCD_FLAG_SAW_IRQ, &hcd->flags); + + if (hcd->driver->resume) { + retval = hcd->driver->resume(hcd); +--- gregkh-2.6.orig/drivers/usb/core/hcd.c ++++ gregkh-2.6/drivers/usb/core/hcd.c +@@ -1315,11 +1315,12 @@ static int hcd_unlink_urb (struct urb *u + * finish unlinking the initial failed usb_set_address() + * or device descriptor fetch. + */ +- if (!hcd->saw_irq && hcd->self.root_hub != urb->dev) { ++ if (!test_bit(HCD_FLAG_SAW_IRQ, &hcd->flags) ++ && hcd->self.root_hub != urb->dev) { + dev_warn (hcd->self.controller, "Unlink after no-IRQ? " + "Controller is probably using the wrong IRQ." + "\n"); +- hcd->saw_irq = 1; ++ set_bit(HCD_FLAG_SAW_IRQ, &hcd->flags); + } + + urb->status = status; +@@ -1649,13 +1650,15 @@ irqreturn_t usb_hcd_irq (int irq, void * + struct usb_hcd *hcd = __hcd; + int start = hcd->state; + +- if (start == HC_STATE_HALT) ++ if (unlikely(start == HC_STATE_HALT || ++ !test_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags))) + return IRQ_NONE; + if (hcd->driver->irq (hcd, r) == IRQ_NONE) + return IRQ_NONE; + +- hcd->saw_irq = 1; +- if (hcd->state == HC_STATE_HALT) ++ set_bit(HCD_FLAG_SAW_IRQ, &hcd->flags); ++ ++ if (unlikely(hcd->state == HC_STATE_HALT)) + usb_hc_died (hcd); + return IRQ_HANDLED; + } +@@ -1768,6 +1771,8 @@ int usb_add_hcd(struct usb_hcd *hcd, + + dev_info(hcd->self.controller, "%s\n", hcd->product_desc); + ++ set_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags); ++ + /* till now HC has been in an indeterminate state ... */ + if (hcd->driver->reset && (retval = hcd->driver->reset(hcd)) < 0) { + dev_err(hcd->self.controller, "can't reset\n"); +--- gregkh-2.6.orig/drivers/usb/core/hcd.h ++++ gregkh-2.6/drivers/usb/core/hcd.h +@@ -72,7 +72,12 @@ struct usb_hcd { /* usb_bus.hcpriv point + * hardware info/state + */ + const struct hc_driver *driver; /* hw-specific hooks */ +- unsigned saw_irq : 1; ++ ++ /* Flags that need to be manipulated atomically */ ++ unsigned long flags; ++#define HCD_FLAG_HW_ACCESSIBLE 0x00000001 ++#define HCD_FLAG_SAW_IRQ 0x00000002 ++ + unsigned can_wakeup:1; /* hw supports wakeup? */ + unsigned remote_wakeup:1;/* sw should use wakeup? */ + unsigned rh_registered:1;/* is root hub registered? */ +--- gregkh-2.6.orig/drivers/usb/host/ehci-pci.c ++++ gregkh-2.6/drivers/usb/host/ehci-pci.c +@@ -228,14 +228,34 @@ static int ehci_pci_reset(struct usb_hcd + static int ehci_pci_suspend(struct usb_hcd *hcd, pm_message_t message) + { + struct ehci_hcd *ehci = hcd_to_ehci(hcd); ++ unsigned long flags; ++ int rc = 0; + + if (time_before(jiffies, ehci->next_statechange)) + msleep(10); + ++ /* Root hub was already suspended. Disable irq emission and ++ * mark HW unaccessible, bail out if RH has been resumed. Use ++ * the spinlock to properly synchronize with possible pending ++ * RH suspend or resume activity. ++ * ++ * This is still racy as hcd->state is manipulated outside of ++ * any locks =P But that will be a different fix. ++ */ ++ spin_lock_irqsave (&ehci->lock, flags); ++ if (hcd->state != HC_STATE_SUSPENDED) { ++ rc = -EINVAL; ++ goto bail; ++ } ++ writel (0, &ehci->regs->intr_enable); ++ clear_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags); ++ bail: ++ spin_unlock_irqrestore (&ehci->lock, flags); ++ + // could save FLADJ in case of Vaux power loss + // ... we'd only use it to handle clock skew + +- return 0; ++ return rc; + } + + static int ehci_pci_resume(struct usb_hcd *hcd) +@@ -255,6 +275,8 @@ static int ehci_pci_resume(struct usb_hc + if (readl(&ehci->regs->configured_flag) != FLAG_CF) + goto restart; + ++ set_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags); ++ + /* If any port is suspended (or owned by the companion), + * we know we can/must resume the HC (and mustn't reset it). + * We just defer that to the root hub code. +--- gregkh-2.6.orig/drivers/usb/host/ehci-q.c ++++ gregkh-2.6/drivers/usb/host/ehci-q.c +@@ -912,6 +912,7 @@ submit_async ( + int epnum; + unsigned long flags; + struct ehci_qh *qh = NULL; ++ int rc = 0; + + qtd = list_entry (qtd_list->next, struct ehci_qtd, qtd_list); + epnum = ep->desc.bEndpointAddress; +@@ -926,21 +927,28 @@ submit_async ( + #endif + + spin_lock_irqsave (&ehci->lock, flags); ++ if (unlikely(!test_bit(HCD_FLAG_HW_ACCESSIBLE, ++ &ehci_to_hcd(ehci)->flags))) { ++ rc = -ESHUTDOWN; ++ goto done; ++ } ++ + qh = qh_append_tds (ehci, urb, qtd_list, epnum, &ep->hcpriv); ++ if (unlikely(qh == NULL)) { ++ rc = -ENOMEM; ++ goto done; ++ } + + /* Control/bulk operations through TTs don't need scheduling, + * the HC and TT handle it when the TT has a buffer ready. + */ +- if (likely (qh != NULL)) { +- if (likely (qh->qh_state == QH_STATE_IDLE)) +- qh_link_async (ehci, qh_get (qh)); +- } ++ if (likely (qh->qh_state == QH_STATE_IDLE)) ++ qh_link_async (ehci, qh_get (qh)); ++ done: + spin_unlock_irqrestore (&ehci->lock, flags); +- if (unlikely (qh == NULL)) { ++ if (unlikely (qh == NULL)) + qtd_list_free (ehci, urb, qtd_list); +- return -ENOMEM; +- } +- return 0; ++ return rc; + } + + /*-------------------------------------------------------------------------*/ +--- gregkh-2.6.orig/drivers/usb/host/ehci-sched.c ++++ gregkh-2.6/drivers/usb/host/ehci-sched.c +@@ -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 * + + /* 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 + + /* 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); +--- gregkh-2.6.orig/drivers/usb/host/ohci-hcd.c ++++ gregkh-2.6/drivers/usb/host/ohci-hcd.c +@@ -115,7 +115,7 @@ + + /*-------------------------------------------------------------------------*/ + +-// #define OHCI_VERBOSE_DEBUG /* not always helpful */ ++#undef OHCI_VERBOSE_DEBUG /* not always helpful */ + + /* For initializing controller (mask in an HCFS mode too) */ + #define OHCI_CONTROL_INIT OHCI_CTRL_CBSR +@@ -253,6 +253,10 @@ static int ohci_urb_enqueue ( + spin_lock_irqsave (&ohci->lock, flags); + + /* don't submit to a dead HC */ ++ if (!test_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags)) { ++ retval = -ENODEV; ++ goto fail; ++ } + if (!HC_IS_RUNNING(hcd->state)) { + retval = -ENODEV; + goto fail; +--- gregkh-2.6.orig/drivers/usb/host/ohci-hub.c ++++ gregkh-2.6/drivers/usb/host/ohci-hub.c +@@ -53,6 +53,11 @@ static int ohci_bus_suspend (struct usb_ + + spin_lock_irqsave (&ohci->lock, flags); + ++ if (unlikely(!test_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags))) { ++ spin_unlock_irqrestore (&ohci->lock, flags); ++ return -ESHUTDOWN; ++ } ++ + ohci->hc_control = ohci_readl (ohci, &ohci->regs->control); + switch (ohci->hc_control & OHCI_CTRL_HCFS) { + case OHCI_USB_RESUME: +@@ -140,11 +145,19 @@ static int ohci_bus_resume (struct usb_h + struct ohci_hcd *ohci = hcd_to_ohci (hcd); + u32 temp, enables; + int status = -EINPROGRESS; ++ unsigned long flags; + + if (time_before (jiffies, ohci->next_statechange)) + msleep(5); + +- spin_lock_irq (&ohci->lock); ++ spin_lock_irqsave (&ohci->lock, flags); ++ ++ if (unlikely(!test_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags))) { ++ spin_unlock_irqrestore (&ohci->lock, flags); ++ return -ESHUTDOWN; ++ } ++ ++ + ohci->hc_control = ohci_readl (ohci, &ohci->regs->control); + + if (ohci->hc_control & (OHCI_CTRL_IR | OHCI_SCHED_ENABLES)) { +@@ -179,7 +192,7 @@ static int ohci_bus_resume (struct usb_h + ohci_dbg (ohci, "lost power\n"); + status = -EBUSY; + } +- spin_unlock_irq (&ohci->lock); ++ spin_unlock_irqrestore (&ohci->lock, flags); + if (status == -EBUSY) { + (void) ohci_init (ohci); + return ohci_restart (ohci); +@@ -297,8 +310,8 @@ ohci_hub_status_data (struct usb_hcd *hc + /* handle autosuspended root: finish resuming before + * letting khubd or root hub timer see state changes. + */ +- if ((ohci->hc_control & OHCI_CTRL_HCFS) != OHCI_USB_OPER +- || !HC_IS_RUNNING(hcd->state)) { ++ if (unlikely((ohci->hc_control & OHCI_CTRL_HCFS) != OHCI_USB_OPER ++ || !HC_IS_RUNNING(hcd->state))) { + can_suspend = 0; + goto done; + } +@@ -508,6 +521,9 @@ static int ohci_hub_control ( + u32 temp; + int retval = 0; + ++ if (unlikely(!test_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags))) ++ return -ESHUTDOWN; ++ + switch (typeReq) { + case ClearHubFeature: + switch (wValue) { +--- gregkh-2.6.orig/drivers/usb/host/ohci-pci.c ++++ gregkh-2.6/drivers/usb/host/ohci-pci.c +@@ -105,13 +105,35 @@ ohci_pci_start (struct usb_hcd *hcd) + + static int ohci_pci_suspend (struct usb_hcd *hcd, pm_message_t message) + { +- /* root hub was already suspended */ +- return 0; ++ struct ohci_hcd *ohci = hcd_to_ohci (hcd); ++ unsigned long flags; ++ int rc = 0; ++ ++ /* Root hub was already suspended. Disable irq emission and ++ * mark HW unaccessible, bail out if RH has been resumed. Use ++ * the spinlock to properly synchronize with possible pending ++ * RH suspend or resume activity. ++ * ++ * This is still racy as hcd->state is manipulated outside of ++ * any locks =P But that will be a different fix. ++ */ ++ spin_lock_irqsave (&ohci->lock, flags); ++ if (hcd->state != HC_STATE_SUSPENDED) { ++ rc = -EINVAL; ++ goto bail; ++ } ++ ohci_writel(ohci, OHCI_INTR_MIE, &ohci->regs->intrdisable); ++ clear_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags); ++ bail: ++ spin_unlock_irqrestore (&ohci->lock, flags); ++ ++ return rc; + } + + + static int ohci_pci_resume (struct usb_hcd *hcd) + { ++ set_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags); + usb_hcd_resume_root_hub(hcd); + return 0; + } diff --git a/usb/usbcore-central-handling-for-host-controllers-that-were-reset-during-suspend-resume.patch b/usb/usbcore-central-handling-for-host-controllers-that-were-reset-during-suspend-resume.patch index 537f30b6befeb..0c9361261daa6 100644 --- a/usb/usbcore-central-handling-for-host-controllers-that-were-reset-during-suspend-resume.patch +++ b/usb/usbcore-central-handling-for-host-controllers-that-were-reset-during-suspend-resume.patch @@ -67,7 +67,7 @@ Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> int devnum; --- gregkh-2.6.orig/drivers/usb/core/hcd.h +++ gregkh-2.6/drivers/usb/core/hcd.h -@@ -375,6 +375,7 @@ extern int usb_find_interface_driver (st +@@ -380,6 +380,7 @@ extern int usb_find_interface_driver (st #ifdef CONFIG_PM extern void usb_hcd_suspend_root_hub (struct usb_hcd *hcd); extern void usb_hcd_resume_root_hub (struct usb_hcd *hcd); @@ -77,7 +77,7 @@ Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> #else --- gregkh-2.6.orig/drivers/usb/host/ehci-pci.c +++ gregkh-2.6/drivers/usb/host/ehci-pci.c -@@ -251,7 +251,6 @@ static int ehci_pci_resume(struct usb_hc +@@ -271,7 +271,6 @@ static int ehci_pci_resume(struct usb_hc { struct ehci_hcd *ehci = hcd_to_ehci(hcd); unsigned port; @@ -85,7 +85,7 @@ Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> struct pci_dev *pdev = to_pci_dev(hcd->self.controller); int retval = -EINVAL; -@@ -282,13 +281,7 @@ static int ehci_pci_resume(struct usb_hc +@@ -304,13 +303,7 @@ static int ehci_pci_resume(struct usb_hc restart: ehci_dbg(ehci, "lost power, restarting\n"); @@ -118,7 +118,7 @@ Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> --- gregkh-2.6.orig/drivers/usb/host/ohci-hcd.c +++ gregkh-2.6/drivers/usb/host/ohci-hcd.c -@@ -791,7 +791,6 @@ static int ohci_restart (struct ohci_hcd +@@ -795,7 +795,6 @@ static int ohci_restart (struct ohci_hcd int temp; int i; struct urb_priv *priv; @@ -126,7 +126,7 @@ Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> /* mark any devices gone, so they do nothing till khubd disconnects. * recycle any "live" eds/tds (and urbs) right away. -@@ -800,11 +799,7 @@ static int ohci_restart (struct ohci_hcd +@@ -804,11 +803,7 @@ static int ohci_restart (struct ohci_hcd */ spin_lock_irq(&ohci->lock); disable (ohci); diff --git a/usb/usbcore-consider-power-budget-when-choosing-configuration.patch b/usb/usbcore-consider-power-budget-when-choosing-configuration.patch index 58f3ff10802a7..ce66ba1ab63fa 100644 --- a/usb/usbcore-consider-power-budget-when-choosing-configuration.patch +++ b/usb/usbcore-consider-power-budget-when-choosing-configuration.patch @@ -407,7 +407,7 @@ Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> unsigned resume_root_hub:1; --- gregkh-2.6.orig/drivers/usb/core/hcd.c +++ gregkh-2.6/drivers/usb/core/hcd.c -@@ -1820,8 +1820,6 @@ int usb_add_hcd(struct usb_hcd *hcd, +@@ -1825,8 +1825,6 @@ int usb_add_hcd(struct usb_hcd *hcd, retval = -ENOMEM; goto err_allocate_root_hub; } @@ -416,7 +416,7 @@ Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> /* Although in principle hcd->driver->start() might need to use rhdev, * none of the current drivers do. -@@ -1839,6 +1837,9 @@ int usb_add_hcd(struct usb_hcd *hcd, +@@ -1844,6 +1842,9 @@ int usb_add_hcd(struct usb_hcd *hcd, dev_dbg(hcd->self.controller, "supports USB remote wakeup\n"); hcd->remote_wakeup = hcd->can_wakeup; |