Hi David !

While looking at the remaining diffs between my tree and Linus,
I found some OHCI related bits.

Here's a patch. It does the following:

 - Move the pmac specific PM bits where they should be (hcd-pci.c)
 - Add a fix for a crash that I had when the HCD died
 - Remove a bogus optimisation in the interrupt code. We _MUST_ read
   the intstatus register, this is what will guarantee that PCI write
   buffers from the device to memory are properly flushed, and so that
   our subsequent reads from memory will return the datas written by
   the chip and not stale crap.
 - Add some additional wmb's in place where I think we need them
 - Guard the root hub against calls during suspend

Please let me know what you think of these, I'd appreciate if you
could feed that to Linus asap provided you agree with the changes.

Ben.

diff -urN linux-2.5/drivers/usb/core/hcd-pci.c 
linuxppc-2.5-benh/drivers/usb/core/hcd-pci.c
--- linux-2.5/drivers/usb/core/hcd-pci.c        2004-03-04 13:48:36.867112872 +1100
+++ linuxppc-2.5-benh/drivers/usb/core/hcd-pci.c        2004-03-04 13:39:20.222735680 
+1100
@@ -32,6 +32,12 @@
 #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 /* CONFIG_PPC_PMAC */
 
 /* PCI-based HCs are normal, but custom bus glue should be ok */
 
@@ -294,8 +300,17 @@
                        dev_dbg (hcd->self.controller, 
                                        "suspend fail, retval %d\n",
                                        retval);
-               else
+               else {
+#ifdef CONFIG_PPC_PMAC
+                       struct device_node      *of_node;
+ 
+                       /* Disable USB PAD & cell clock for Keylargo built-in 
controller */
+                       of_node = pci_device_to_OF_node (dev);
+                       if (of_node)
+                               pmac_call_feature(PMAC_FTR_USB_ENABLE, of_node, 0, 0);
+#endif /* CONFIG_PPC_PMAC */
                        hcd->state = USB_STATE_SUSPENDED;
+               }
        }
 
        pci_set_power_state (dev, state);
@@ -326,6 +341,17 @@
        hcd->state = USB_STATE_RESUMING;
 
        pci_set_power_state (dev, 0);
+#ifdef CONFIG_PPC_PMAC
+       {
+               struct device_node *of_node;
+
+               /* Re-enable USB PAD & cell clock for Keykargo built-in controller */
+               of_node = pci_device_to_OF_node (dev);
+               if (of_node)
+                       pmac_call_feature (PMAC_FTR_USB_ENABLE, of_node, 0, 1);
+       }
+#endif /* CONFIG_PPC_PMAC */
+
        pci_restore_state (dev, hcd->pci_state);
 
        /* remote wakeup needs hub->suspend() cooperation */
diff -urN linux-2.5/drivers/usb/host/ohci-hcd.c 
linuxppc-2.5-benh/drivers/usb/host/ohci-hcd.c
--- linux-2.5/drivers/usb/host/ohci-hcd.c       2004-03-04 13:48:31.154981248 +1100
+++ linuxppc-2.5-benh/drivers/usb/host/ohci-hcd.c       2004-03-04 17:07:47.659316304 
+1100
@@ -334,6 +334,11 @@
        /* ASSERT:  any requests/urbs are being unlinked */
        /* ASSERT:  nobody can be submitting urbs for this any more */
 
+       if (!HCD_IS_RUNNING (ohci->hcd.state)) {
+               ed->state = ED_IDLE;
+               finish_unlinks (ohci, 0, 0);
+       }
+
        epnum <<= 1;
        if (epnum != 0 && !(ep & USB_DIR_IN))
                epnum |= 1;
@@ -583,13 +588,7 @@
        struct ohci_regs        *regs = ohci->regs;
        int                     ints; 
 
-       /* we can eliminate a (slow) readl() if _only_ WDH caused this irq */
-       if ((ohci->hcca->done_head != 0)
-                       && ! (le32_to_cpup (&ohci->hcca->done_head) & 0x01)) {
-               ints =  OHCI_INTR_WDH;
-
-       /* cardbus/... hardware gone before remove() */
-       } else if ((ints = readl (&regs->intrstatus)) == ~(u32)0) {
+       if ((ints = readl (&regs->intrstatus)) == ~(u32)0) {
                disable (ohci);
                ohci_dbg (ohci, "device removed!\n");
                return IRQ_HANDLED;
diff -urN linux-2.5/drivers/usb/host/ohci-hub.c 
linuxppc-2.5-benh/drivers/usb/host/ohci-hub.c
--- linux-2.5/drivers/usb/host/ohci-hub.c       2004-03-04 13:48:31.175978056 +1100
+++ linuxppc-2.5-benh/drivers/usb/host/ohci-hub.c       2004-02-10 17:11:27.000000000 
+1100
@@ -71,6 +71,11 @@
        struct ohci_hcd *ohci = hcd_to_ohci (hcd);
        int             ports, i, changed = 0, length = 1;
 
+       if (HCD_IS_SUSPENDED(hcd->state)) {
+               printk("ohci_hub_status_data() : sleeping\n");
+               return 0;
+       }
+
        ports = roothub_a (ohci) & RH_A_NDP; 
        if (ports > MAX_ROOT_PORTS) {
                if (!HCD_IS_RUNNING(ohci->hcd.state))
@@ -163,6 +168,11 @@
        u32             temp;
        int             retval = 0;
 
+       if (HCD_IS_SUSPENDED(hcd->state)) {
+               printk("ohci_hub_control() : sleeping\n");
+               return -ENODEV;
+       }
+
        switch (typeReq) {
        case ClearHubFeature:
                switch (wValue) {
diff -urN linux-2.5/drivers/usb/host/ohci-pci.c 
linuxppc-2.5-benh/drivers/usb/host/ohci-pci.c
--- linux-2.5/drivers/usb/host/ohci-pci.c       2004-03-04 13:48:31.239968328 +1100
+++ linuxppc-2.5-benh/drivers/usb/host/ohci-pci.c       2004-03-04 17:09:35.749884040 
+1100
@@ -13,16 +13,6 @@
  *
  * This file is licenced under the GPL.
  */
- 
-#ifdef CONFIG_PMAC_PBOOK
-#include <asm/machdep.h>
-#include <asm/pmac_feature.h>
-#include <asm/pci-bridge.h>
-#include <asm/prom.h>
-#ifndef CONFIG_PM
-#      define CONFIG_PM
-#endif
-#endif
 
 #ifndef CONFIG_PCI
 #error "This file is PCI bus glue.  CONFIG_PCI must be defined."
@@ -143,12 +133,6 @@
        mdelay (1);
        if (!readl (&ohci->regs->intrstatus) & OHCI_INTR_SF)
                mdelay (1);
-               
-#ifdef CONFIG_PMAC_PBOOK
-       if (_machine == _MACH_Pmac)
-               disable_irq ((to_pci_dev(hcd->self.controller))->irq);
-       /* else, 2.4 assumes shared irqs -- don't disable */
-#endif
 
        /* Enable remote wakeup */
        writel (readl (&ohci->regs->intrenable) | OHCI_INTR_RD,
@@ -185,16 +169,6 @@
        cmd &= ~PCI_COMMAND_MASTER;
        pci_write_config_word (to_pci_dev(hcd->self.controller), PCI_COMMAND, 
                                cmd);
-#ifdef CONFIG_PMAC_PBOOK
-       {
-               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
        return 0;
 }
 
@@ -205,16 +179,6 @@
        int                     temp;
        int                     retval = 0;
 
-#ifdef CONFIG_PMAC_PBOOK
-       {
-               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
        /* did we suspend, or were we powered off? */
        ohci->hc_control = readl (&ohci->regs->control);
        temp = ohci->hc_control & OHCI_CTRL_HCFS;
@@ -283,10 +247,6 @@
                (void) readl (&ohci->regs->intrdisable);
                spin_unlock_irq (&ohci->lock);
 
-#ifdef CONFIG_PMAC_PBOOK
-               if (_machine == _MACH_Pmac)
-                       enable_irq (to_pci_dev(hcd->self.controller)->irq);
-#endif
 
                /* Check for a pending done list */
                if (ohci->hcca->done_head)
diff -urN linux-2.5/drivers/usb/host/ohci-q.c 
linuxppc-2.5-benh/drivers/usb/host/ohci-q.c
--- linux-2.5/drivers/usb/host/ohci-q.c 2004-03-04 13:48:31.266964224 +1100
+++ linuxppc-2.5-benh/drivers/usb/host/ohci-q.c 2004-03-04 17:06:56.292125304 +1100
@@ -156,6 +156,7 @@
                        wmb ();
                        *prev = ed;
                        *prev_p = cpu_to_le32p (&ed->dma);
+                       wmb();
                }
                ohci->load [i] += ed->load;
        }
@@ -194,6 +195,7 @@
                }
                ed->ed_prev = ohci->ed_controltail;
                if (!ohci->ed_controltail && !ohci->ed_rm_list) {
+                       wmb();
                        ohci->hc_control |= OHCI_CTRL_CLE;
                        writel (0, &ohci->regs->ed_controlcurrent);
                        writel (ohci->hc_control, &ohci->regs->control);
@@ -210,6 +212,7 @@
                }
                ed->ed_prev = ohci->ed_bulktail;
                if (!ohci->ed_bulktail && !ohci->ed_rm_list) {
+                       wmb();
                        ohci->hc_control |= OHCI_CTRL_BLE;
                        writel (0, &ohci->regs->ed_bulkcurrent);
                        writel (ohci->hc_control, &ohci->regs->control);
@@ -839,6 +842,7 @@
 
        td_dma = le32_to_cpup (&ohci->hcca->done_head);
        ohci->hcca->done_head = 0;
+               wmb();
 
        /* get TD from hc's singly linked list, and
         * prepend to ours.  ed->td_list changes later.




-------------------------------------------------------
This SF.Net email is sponsored by: IBM Linux Tutorials
Free Linux tutorial presented by Daniel Robbins, President and CEO of
GenToo technologies. Learn everything from fundamentals to system
administration.http://ads.osdn.com/?ad_id=1470&alloc_id=3638&op=click
_______________________________________________
[EMAIL PROTECTED]
To unsubscribe, use the last form field at:
https://lists.sourceforge.net/lists/listinfo/linux-usb-devel

Reply via email to