aboutsummaryrefslogtreecommitdiffstats
path: root/usb
diff options
context:
space:
mode:
authorGreg Kroah-Hartman <gregkh@suse.de>2005-11-23 14:34:10 -0800
committerGreg Kroah-Hartman <gregkh@suse.de>2005-11-23 14:34:10 -0800
commitf5fdb9b98ea0c566f299a8cbd9b3b9f65020f5d8 (patch)
treeea4d73f274bbe6e9a3e6a50aa1d0e018655e396a /usb
parentb493d45d58c5b347d2d62f8aa18dec9a8dea6032 (diff)
downloadpatches-f5fdb9b98ea0c566f299a8cbd9b3b9f65020f5d8.tar.gz
usb, pci, and other patches
Diffstat (limited to 'usb')
-rw-r--r--usb/isp116x-hcd-cleanup.patch57
-rw-r--r--usb/remove-usb-private-semaphore.patch4
-rw-r--r--usb/usb-fix-usb-suspend-resume-crasher.patch390
-rw-r--r--usb/usbcore-central-handling-for-host-controllers-that-were-reset-during-suspend-resume.patch10
-rw-r--r--usb/usbcore-consider-power-budget-when-choosing-configuration.patch4
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;