This fixes two small and unrelated bugs in the current OHCI code:

 - Certain initialization sequences had problems with IRQs.
   Fixed last month in EHCI, but this ohci patch didn't seem
   needed back then.  OK, so now I saw the same bug in OHCI.
   (I could believe UHCI needs it too, sigh.)

 - When restarting endpoint i/o after a queue fault, the HC
   needs to be told the control (or bulk) list filled (CLF/BLF).
   Likely this wasn't common (usbtest test10 subcase7 fault
   recovery reproduced it nicely).

Please merge.  Lack of the first one might make trouble for
some people.

- Dave

--- 1.14/drivers/usb/host/ohci-pci.c    Thu Jul 31 14:36:49 2003
+++ edited/drivers/usb/host/ohci-pci.c  Mon Aug 25 18:03:05 2003
@@ -30,6 +30,15 @@
 
 /*-------------------------------------------------------------------------*/
 
+static int
+ohci_pci_reset (struct usb_hcd *hcd)
+{
+       struct ohci_hcd *ohci = hcd_to_ohci (hcd);
+
+       ohci->regs = hcd->regs;
+       return hc_reset (ohci);
+}
+
 static int __devinit
 ohci_pci_start (struct usb_hcd *hcd)
 {
@@ -89,12 +98,6 @@
                ohci_stop (hcd);
                return ret;
        }
-       ohci->regs = hcd->regs;
-
-       if (hc_reset (ohci) < 0) {
-               ohci_stop (hcd);
-               return -ENODEV;
-       }
 
        if (hc_start (ohci) < 0) {
                ohci_err (ohci, "can't start\n");
@@ -315,6 +318,7 @@
        /*
         * basic lifecycle operations
         */
+       .reset =                ohci_pci_reset,
        .start =                ohci_pci_start,
 #ifdef CONFIG_PM
        .suspend =              ohci_pci_suspend,
--- 1.42/drivers/usb/host/ohci-q.c      Mon Jul 14 11:27:33 2003
+++ edited/drivers/usb/host/ohci-q.c    Mon Aug 25 19:15:06 2003
@@ -1013,10 +1013,22 @@
                if (list_empty (&ed->td_list))
                        ed_deschedule (ohci, ed);
                /* ... reenabling halted EDs only after fault cleanup */
-               else if (!(ed->hwINFO & ED_DEQUEUE)) {
+               else if ((ed->hwINFO & (ED_SKIP | ED_DEQUEUE)) == ED_SKIP) {
                        td = list_entry (ed->td_list.next, struct td, td_list);
-                       if (!(td->hwINFO & TD_DONE))
+                       if (!(td->hwINFO & TD_DONE)) {
                                ed->hwINFO &= ~ED_SKIP;
+                               /* ... hc may need waking-up */
+                               switch (ed->type) {
+                               case PIPE_CONTROL:
+                                       writel (OHCI_CLF,
+                                               &ohci->regs->cmdstatus);   
+                                       break;
+                               case PIPE_BULK:
+                                       writel (OHCI_BLF,
+                                               &ohci->regs->cmdstatus);   
+                                       break;
+                               }
+                       }
                }
 
                td = td_next;

Reply via email to