Mostly from Benjamin Herrenschmidt:

 - prevent usbcore from asking the HCD root hub code
   to read registers on one more suspend path (some
   hardware gets upset in those cases);

- try handling a "device died" cleanup case better

 - add some wmb() calls in spots that could matter
   on some hardware

Please merge.

- Dave

--- 1.80/drivers/usb/core/hcd.c Sun Mar  7 11:29:08 2004
+++ edited/drivers/usb/core/hcd.c       Thu Mar 25 20:58:45 2004
@@ -416,9 +416,14 @@
 
        default:
                /* non-generic request */
-               urb->status = hcd->driver->hub_control (hcd,
-                       typeReq, wValue, wIndex,
-                       ubuf, wLength);
+               if (HCD_IS_SUSPENDED (hcd->state))
+                       urb->status = -EAGAIN;
+               else if (!HCD_IS_RUNNING (hcd->state))
+                       urb->status = -ENODEV;
+               else
+                       urb->status = hcd->driver->hub_control (hcd,
+                               typeReq, wValue, wIndex,
+                               ubuf, wLength);
                break;
 error:
                /* "protocol stall" on error */
--- 1.56/drivers/usb/host/ohci-hcd.c    Tue Mar  2 05:52:40 2004
+++ edited/drivers/usb/host/ohci-hcd.c  Thu Mar 25 20:48:40 2004
@@ -344,8 +344,11 @@
        if (!ed)
                goto done;
 
-       if (!HCD_IS_RUNNING (ohci->hcd.state))
+       if (!HCD_IS_RUNNING (ohci->hcd.state)) {
                ed->state = ED_IDLE;
+               finish_unlinks (ohci, 0, 0);
+       }
+
        switch (ed->state) {
        case ED_UNLINK:         /* wait for hw to finish? */
                /* major IRQ delivery trouble loses INTR_SF too... */
--- 1.50/drivers/usb/host/ohci-q.c      Wed Mar 10 08:17:32 2004
+++ edited/drivers/usb/host/ohci-q.c    Thu Mar 25 20:46:59 2004
@@ -156,6 +156,7 @@
                        wmb ();
                        *prev = ed;
                        *prev_p = cpu_to_le32p (&ed->dma);
+                       wmb();
                }
                ohci->load [i] += ed->load;
        }
@@ -195,6 +196,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);
@@ -212,6 +214,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);
@@ -868,6 +871,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.

Reply via email to