ChangeSet 1.1673.8.42, 2004/03/26 14:26:00-08:00, david-b@pacbell.net

[PATCH] USB: ohci misc updates

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


 drivers/usb/core/hcd.c      |   11 ++++++++---
 drivers/usb/host/ohci-hcd.c |    5 ++++-
 drivers/usb/host/ohci-q.c   |    4 ++++
 3 files changed, 16 insertions(+), 4 deletions(-)


diff -Nru a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c
--- a/drivers/usb/core/hcd.c	Wed Apr 14 14:36:41 2004
+++ b/drivers/usb/core/hcd.c	Wed Apr 14 14:36:41 2004
@@ -418,9 +418,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 */
diff -Nru a/drivers/usb/host/ohci-hcd.c b/drivers/usb/host/ohci-hcd.c
--- a/drivers/usb/host/ohci-hcd.c	Wed Apr 14 14:36:41 2004
+++ b/drivers/usb/host/ohci-hcd.c	Wed Apr 14 14:36:41 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... */
diff -Nru a/drivers/usb/host/ohci-q.c b/drivers/usb/host/ohci-q.c
--- a/drivers/usb/host/ohci-q.c	Wed Apr 14 14:36:41 2004
+++ b/drivers/usb/host/ohci-q.c	Wed Apr 14 14:36:41 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.