Hi
I was told that if I had a patch to submit for a baseline change that this was the place to do it.
If not, please let me know...

thanks,
morrow

Patched against 2.6.11 baseline
problems fixed:
1) OHCI_INTR_RD not being cleared in ohci interrupt handler
results in interrupt storm and system hang on RD status.
ohci spec indicates this should be done.
2) PORT_CSC not being cleared in ehci_hub_status_data
code attempts to clear bit, but bit is write to clear.
there are other errant clears, since the PORTSCn regs
have 3 RWC bits, and the rest are RW. All stmts of the form:
  writel (v, &ehci->regs->port_status[i])
should clear RWC bits if they do not intend to clear status,
and should set the bits which should be cleared (this case).
3) loop control and subsequent port resume/reset not correct.
unsigned index made detecting port1 active impossible, and
OWNER/POWER status was being ignored on ports assigned
to companion controller.

Signed-off-by: Jordan Crouse <[EMAIL PROTECTED]>

diff -uprN linux-2.6.11.orig/drivers/usb/host/ehci.h 
linux-2.6.11/drivers/usb/host/ehci.h
--- linux-2.6.11.orig/drivers/usb/host/ehci.h   2005-03-02 00:38:25.000000000 
-0700
+++ linux-2.6.11/drivers/usb/host/ehci.h        2005-08-17 08:15:36.000000000 
-0600
@@ -262,6 +262,7 @@ struct ehci_regs {
 #define PORT_PE                (1<<2)          /* port enable */
 #define PORT_CSC       (1<<1)          /* connect status change */
 #define PORT_CONNECT   (1<<0)          /* device connected */
+#define PORT_RWC_BITS   (PORT_CSC | PORT_PEC | PORT_OCC)
 } __attribute__ ((packed));
 
 /* Appendix C, Debug port ... intended for use with special "debug devices"
diff -uprN linux-2.6.11.orig/drivers/usb/host/ehci-hcd.c 
linux-2.6.11/drivers/usb/host/ehci-hcd.c
--- linux-2.6.11.orig/drivers/usb/host/ehci-hcd.c       2005-03-02 
00:38:38.000000000 -0700
+++ linux-2.6.11/drivers/usb/host/ehci-hcd.c    2005-08-17 08:15:36.000000000 
-0600
@@ -722,7 +722,7 @@ static int ehci_suspend (struct usb_hcd 
 static int ehci_resume (struct usb_hcd *hcd)
 {
        struct ehci_hcd         *ehci = hcd_to_ehci (hcd);
-       unsigned                port;
+       int                     port;
        struct usb_device       *root = hcd->self.root_hub;
        int                     retval = -EINVAL;
        int                     powerup = 0;
@@ -733,11 +733,11 @@ static int ehci_resume (struct usb_hcd *
                msleep (100);
 
        /* If any port is suspended, we know we can/must resume the HC. */
-       for (port = HCS_N_PORTS (ehci->hcs_params); port > 0; ) {
+       for (port = HCS_N_PORTS (ehci->hcs_params); --port >= 0; ) {
                u32     status;
-               port--;
                status = readl (&ehci->regs->port_status [port]);
-               if (status & PORT_SUSPEND) {
+               if ( (status & PORT_SUSPEND) != 0 ||
+                   ((status & PORT_OWNER) != 0 && (status & PORT_POWER) != 0) 
) {
                        down (&hcd->self.root_hub->serialize);
                        retval = ehci_hub_resume (hcd);
                        up (&hcd->self.root_hub->serialize);
@@ -755,7 +755,7 @@ static int ehci_resume (struct usb_hcd *
        /* Else reset, to cope with power loss or flush-to-storage
         * style "resume" having activated BIOS during reboot.
         */
-       if (port == 0) {
+       if (port < 0) {
                (void) ehci_halt (ehci);
                (void) ehci_reset (ehci);
                (void) ehci_hc_reset (hcd);
diff -uprN linux-2.6.11.orig/drivers/usb/host/ehci-hub.c 
linux-2.6.11/drivers/usb/host/ehci-hub.c
--- linux-2.6.11.orig/drivers/usb/host/ehci-hub.c       2005-03-02 
00:38:32.000000000 -0700
+++ linux-2.6.11/drivers/usb/host/ehci-hub.c    2005-08-17 08:15:36.000000000 
-0600
@@ -232,7 +232,8 @@ ehci_hub_status_data (struct usb_hcd *hc
                if (temp & PORT_OWNER) {
                        /* don't report this in GetPortStatus */
                        if (temp & PORT_CSC) {
-                               temp &= ~PORT_CSC;
+                               temp &= ~PORT_RWC_BITS;
+                               temp |= PORT_CSC;
                                writel (temp, &ehci->regs->port_status [i]);
                        }
                        continue;
diff -uprN linux-2.6.11.orig/drivers/usb/host/ohci-hcd.c 
linux-2.6.11/drivers/usb/host/ohci-hcd.c
--- linux-2.6.11.orig/drivers/usb/host/ohci-hcd.c       2005-03-02 
00:37:48.000000000 -0700
+++ linux-2.6.11/drivers/usb/host/ohci-hcd.c    2005-08-17 08:15:36.000000000 
-0600
@@ -720,6 +720,7 @@ static irqreturn_t ohci_irq (struct usb_
 
        if (ints & OHCI_INTR_RD) {
                ohci_vdbg (ohci, "resume detect\n");
+               ohci_writel (ohci, OHCI_INTR_RD, &regs->intrstatus);
                schedule_work(&ohci->rh_resume);
        }
 

Reply via email to