The latest patch that is candidate for upstream is:

Index: 2.6.14-ben/drivers/usb/core/hcd-pci.c
===================================================================
--- 2.6.14-ben.orig/drivers/usb/core/hcd-pci.c
+++ 2.6.14-ben/drivers/usb/core/hcd-pci.c
@@ -32,6 +32,13 @@
 #include <linux/usb.h>
 #include "hcd.h"
 
+#ifdef CONFIG_PPC_PMAC
+#include <asm/machdep.h>
+#include <asm/pmac_feature.h>
+#include <asm/pci-bridge.h>
+#include <asm/prom.h>
+#endif
+
 
 /* PCI-based HCs are common, but plenty of non-PCI HCs are used too */
 
@@ -278,6 +285,18 @@ int usb_hcd_pci_suspend (struct pci_dev 
                break;
        }
 
+#ifdef CONFIG_PPC_PMAC
+       if (retval == 0 && _machine == _MACH_Pmac) {
+               struct device_node      *of_node;
+
+               /* Disable USB PAD & cell clock */
+               of_node = pci_device_to_OF_node (to_pci_dev(hcd->self.
+                                                           controller));
+               if (of_node)
+                       pmac_call_feature(PMAC_FTR_USB_ENABLE, of_node, 0, 0);
+       }
+#endif /* CONFIG_PPC_PMAC */
+
        /* update power_state **ONLY** to make sysfs happier */
        if (retval == 0)
                dev->dev.power.power_state = message;
@@ -303,6 +322,18 @@ int usb_hcd_pci_resume (struct pci_dev *
                return 0;
        }
 
+#ifdef CONFIG_PPC_PMAC
+       if (_machine == _MACH_Pmac) {
+               struct device_node *of_node;
+
+               /* Re-enable USB PAD & cell clock */
+               of_node = pci_device_to_OF_node (to_pci_dev(hcd->self.
+                                                           controller));
+               if (of_node)
+                       pmac_call_feature(PMAC_FTR_USB_ENABLE, of_node, 0, 1);
+       }
+#endif /* CONFIG_PPC_PMAC */
+
        /* NOTE:  chip docs cover clean "real suspend" cases (what Linux
         * calls "standby", "suspend to RAM", and so on).  There are also
         * dirty cases when swsusp fakes a suspend in "shutdown" mode.
Index: 2.6.14-ben/drivers/usb/core/hcd.c
===================================================================
--- 2.6.14-ben.orig/drivers/usb/core/hcd.c
+++ 2.6.14-ben/drivers/usb/core/hcd.c
@@ -1600,7 +1600,8 @@ irqreturn_t usb_hcd_irq (int irq, void *
        struct usb_hcd          *hcd = __hcd;
        int                     start = hcd->state;
 
-       if (start == HC_STATE_HALT)
+       if (start == HC_STATE_HALT ||
+           !test_bit(HC_FLAG_IRQ_ON, &hcd->bitflags))
                return IRQ_NONE;
        if (hcd->driver->irq (hcd, r) == IRQ_NONE)
                return IRQ_NONE;
@@ -1736,6 +1737,9 @@ int usb_add_hcd(struct usb_hcd *hcd,
        if (hcd->driver->irq) {
                char    buf[8], *bufp = buf;
 
+               set_bit(HC_FLAG_IRQ_ON, &hcd->bitflags);
+               mb();
+
 #ifdef __sparc__
                bufp = __irq_itoa(irqnum);
 #else
Index: 2.6.14-ben/drivers/usb/core/hcd.h
===================================================================
--- 2.6.14-ben.orig/drivers/usb/core/hcd.h
+++ 2.6.14-ben/drivers/usb/core/hcd.h
@@ -71,6 +71,9 @@ struct usb_hcd {      /* usb_bus.hcpriv point
        /*
         * hardware info/state
         */
+       unsigned long           bitflags;       /* various single-bit flags */
+#define HC_FLAG_IRQ_ON         0
+
        const struct hc_driver  *driver;        /* hw-specific hooks */
        unsigned                saw_irq : 1;
        unsigned                can_wakeup:1;   /* hw supports wakeup? */
Index: 2.6.14-ben/drivers/usb/host/ehci-hcd.c
===================================================================
--- 2.6.14-ben.orig/drivers/usb/host/ehci-hcd.c
+++ 2.6.14-ben/drivers/usb/host/ehci-hcd.c
@@ -750,6 +750,12 @@ static int ehci_suspend (struct usb_hcd 
        if (time_before (jiffies, ehci->next_statechange))
                msleep (100);
 
+       /* Disable emission of interrupts during suspend */
+       writel(0, &ehci->regs->intr_enable);
+       mb();
+       clear_bit(HC_FLAG_IRQ_ON, &hcd->bitflags);
+       synchronize_irq(to_pci_dev(hcd->self.controller)->irq);
+
 #ifdef CONFIG_USB_SUSPEND
        (void) usb_suspend_device (hcd->self.root_hub, message);
 #else
@@ -776,6 +782,8 @@ static int ehci_resume (struct usb_hcd *
        if (time_before (jiffies, ehci->next_statechange))
                msleep (100);
 
+       set_bit(HC_FLAG_IRQ_ON, &hcd->bitflags);
+
        /* If any port is suspended (or owned by the companion),
         * we know we can/must resume the HC (and mustn't reset it).
         */
Index: 2.6.14-ben/drivers/usb/host/ehci-q.c
===================================================================
--- 2.6.14-ben.orig/drivers/usb/host/ehci-q.c
+++ 2.6.14-ben/drivers/usb/host/ehci-q.c
@@ -926,6 +926,11 @@ submit_async (
 #endif
 
        spin_lock_irqsave (&ehci->lock, flags);
+       if (HC_IS_SUSPENDED(ehci_to_hcd(ehci)->state)) {
+               spin_unlock_irqrestore (&ehci->lock, flags);
+               return -ESHUTDOWN;
+       }
+
        qh = qh_append_tds (ehci, urb, qtd_list, epnum, &ep->hcpriv);
 
        /* Control/bulk operations through TTs don't need scheduling,
Index: 2.6.14-ben/drivers/usb/host/ehci-sched.c
===================================================================
--- 2.6.14-ben.orig/drivers/usb/host/ehci-sched.c
+++ 2.6.14-ben/drivers/usb/host/ehci-sched.c
@@ -602,6 +602,11 @@ static int intr_submit (
 
        spin_lock_irqsave (&ehci->lock, flags);
 
+       if (HC_IS_SUSPENDED(ehci_to_hcd(ehci)->state)) {
+               spin_unlock_irqrestore (&ehci->lock, flags);
+               return -ESHUTDOWN;
+       }
+
        /* get qh and force any scheduling errors */
        INIT_LIST_HEAD (&empty);
        qh = qh_append_tds (ehci, urb, &empty, epnum, &ep->hcpriv);
@@ -1456,6 +1461,11 @@ static int itd_submit (struct ehci_hcd *
 
        /* schedule ... need to lock */
        spin_lock_irqsave (&ehci->lock, flags);
+       if (HC_IS_SUSPENDED(ehci_to_hcd(ehci)->state)) {
+               spin_unlock_irqrestore (&ehci->lock, flags);
+               status = -ESHUTDOWN;
+               goto done;
+       }
        status = iso_stream_schedule (ehci, urb, stream);
        if (likely (status == 0))
                itd_link_urb (ehci, urb, ehci->periodic_size << 3, stream);
@@ -1815,6 +1825,11 @@ static int sitd_submit (struct ehci_hcd 
 
        /* schedule ... need to lock */
        spin_lock_irqsave (&ehci->lock, flags);
+       if (HC_IS_SUSPENDED(ehci_to_hcd(ehci)->state)) {
+               spin_unlock_irqrestore (&ehci->lock, flags);
+               status = -ESHUTDOWN;
+               goto done;
+       }
        status = iso_stream_schedule (ehci, urb, stream);
        if (status == 0)
                sitd_link_urb (ehci, urb, ehci->periodic_size << 3, stream);
Index: 2.6.14-ben/drivers/usb/host/ohci-hcd.c
===================================================================
--- 2.6.14-ben.orig/drivers/usb/host/ohci-hcd.c
+++ 2.6.14-ben/drivers/usb/host/ohci-hcd.c
@@ -252,6 +252,10 @@ static int ohci_urb_enqueue (
 
        spin_lock_irqsave (&ohci->lock, flags);
 
+       if (HC_IS_SUSPENDED(hcd->state)) {
+               retval = -ESHUTDOWN;
+               goto fail;
+       }
        /* don't submit to a dead HC */
        if (!HC_IS_RUNNING(hcd->state)) {
                retval = -ENODEV;
Index: 2.6.14-ben/drivers/usb/host/ohci-hub.c
===================================================================
--- 2.6.14-ben.orig/drivers/usb/host/ohci-hub.c
+++ 2.6.14-ben/drivers/usb/host/ohci-hub.c
@@ -219,13 +219,6 @@ static int ohci_hub_resume (struct usb_h
        /* Sometimes PCI D3 suspend trashes frame timings ... */
        periodic_reinit (ohci);
 
-       /* interrupts might have been disabled */
-       ohci_writel (ohci, OHCI_INTR_INIT, &ohci->regs->intrenable);
-       if (ohci->ed_rm_list)
-               ohci_writel (ohci, OHCI_INTR_SF, &ohci->regs->intrenable);
-       ohci_writel (ohci, ohci_readl (ohci, &ohci->regs->intrstatus),
-                       &ohci->regs->intrstatus);
-
        /* Then re-enable operations */
        ohci_writel (ohci, OHCI_USB_OPER, &ohci->regs->control);
        (void) ohci_readl (ohci, &ohci->regs->control);
@@ -241,6 +234,13 @@ static int ohci_hub_resume (struct usb_h
        /* TRSMRCY */
        msleep (10);
 
+       /* interrupts might have been disabled */
+       ohci_writel (ohci, OHCI_INTR_INIT, &ohci->regs->intrenable);
+       if (ohci->ed_rm_list)
+               ohci_writel (ohci, OHCI_INTR_SF, &ohci->regs->intrenable);
+       ohci_writel (ohci, ohci_readl (ohci, &ohci->regs->intrstatus),
+                       &ohci->regs->intrstatus);
+
        /* keep it alive for ~5x suspend + resume costs */
        ohci->next_statechange = jiffies + msecs_to_jiffies (250);
 
Index: 2.6.14-ben/drivers/usb/host/ohci-pci.c
===================================================================
--- 2.6.14-ben.orig/drivers/usb/host/ohci-pci.c
+++ 2.6.14-ben/drivers/usb/host/ohci-pci.c
@@ -14,13 +14,6 @@
  * This file is licenced under the GPL.
  */
  
-#ifdef CONFIG_PPC_PMAC
-#include <asm/machdep.h>
-#include <asm/pmac_feature.h>
-#include <asm/pci-bridge.h>
-#include <asm/prom.h>
-#endif
-
 #ifndef CONFIG_PCI
 #error "This file is PCI bus glue.  CONFIG_PCI must be defined."
 #endif
@@ -118,6 +111,12 @@ static int ohci_pci_suspend (struct usb_
        if (time_before (jiffies, ohci->next_statechange))
                msleep (100);
 
+       /* Disable emission of interrupts during suspend */
+       ohci_writel(ohci, OHCI_INTR_MIE, &ohci->regs->intrdisable);
+       mb();
+       clear_bit(HC_FLAG_IRQ_ON, &hcd->bitflags);
+       synchronize_irq(to_pci_dev(hcd->self.controller)->irq);
+
 #ifdef CONFIG_USB_SUSPEND
        (void) usb_suspend_device (hcd->self.root_hub, message);
 #else
@@ -129,16 +128,6 @@ static int ohci_pci_suspend (struct usb_
        /* let things settle down a bit */
        msleep (100);
        
-#ifdef CONFIG_PPC_PMAC
-       if (_machine == _MACH_Pmac) {
-               struct device_node      *of_node;
- 
-               /* Disable USB PAD & cell clock */
-               of_node = pci_device_to_OF_node 
(to_pci_dev(hcd->self.controller));
-               if (of_node)
-                       pmac_call_feature(PMAC_FTR_USB_ENABLE, of_node, 0, 0);
-       }
-#endif /* CONFIG_PPC_PMAC */
        return 0;
 }
 
@@ -148,20 +137,11 @@ static int ohci_pci_resume (struct usb_h
        struct ohci_hcd         *ohci = hcd_to_ohci (hcd);
        int                     retval = 0;
 
-#ifdef CONFIG_PPC_PMAC
-       if (_machine == _MACH_Pmac) {
-               struct device_node *of_node;
-
-               /* Re-enable USB PAD & cell clock */
-               of_node = pci_device_to_OF_node 
(to_pci_dev(hcd->self.controller));
-               if (of_node)
-                       pmac_call_feature (PMAC_FTR_USB_ENABLE, of_node, 0, 1);
-       }
-#endif /* CONFIG_PPC_PMAC */
-
        /* resume root hub */
        if (time_before (jiffies, ohci->next_statechange))
                msleep (100);
+       set_bit(HC_FLAG_IRQ_ON, &hcd->bitflags);
+
 #ifdef CONFIG_USB_SUSPEND
        /* get extra cleanup even if remote wakeup isn't in use */
        retval = usb_resume_device (hcd->self.root_hub);
Index: 2.6.14-ben/drivers/usb/host/uhci-hcd.c
===================================================================
--- 2.6.14-ben.orig/drivers/usb/host/uhci-hcd.c
+++ 2.6.14-ben/drivers/usb/host/uhci-hcd.c
@@ -797,6 +797,11 @@ static int uhci_suspend(struct usb_hcd *
 
 done:
        spin_unlock_irq(&uhci->lock);
+       if (rc == 0) {
+               mb();
+               clear_bit(HC_FLAG_IRQ_ON, &hcd->bitflags);
+               synchronize_irq(hcd->irq);
+       }
        return rc;
 }
 
@@ -818,6 +823,8 @@ static int uhci_resume(struct usb_hcd *h
         * system wakeup.  Check it and reconfigure to avoid problems.
         */
        check_and_reset_hc(uhci);
+       set_bit(HC_FLAG_IRQ_ON, &hcd->bitflags);
+       mb();
        configure_hc(uhci);
 
 #ifndef CONFIG_USB_SUSPEND



-- 
To UNSUBSCRIBE, email to [EMAIL PROTECTED]
with a subject of "unsubscribe". Trouble? Contact [EMAIL PROTECTED]

Reply via email to