From 18a860b26af73cb4afb86ab480a0cfa017e58925 Mon Sep 17 00:00:00 2001 From: David Brownell Date: Thu, 25 Mar 2004 22:26:00 -0800 Subject: [PATCH] [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 --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c index 24268e5e95409..e40346c7c105e 100644 --- a/drivers/usb/core/hcd.c +++ b/drivers/usb/core/hcd.c @@ -418,9 +418,14 @@ static int rh_call_control (struct usb_hcd *hcd, struct urb *urb) 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 --git a/drivers/usb/host/ohci-hcd.c b/drivers/usb/host/ohci-hcd.c index 02c7e3152dbe0..1d9a689b06bba 100644 --- a/drivers/usb/host/ohci-hcd.c +++ b/drivers/usb/host/ohci-hcd.c @@ -344,8 +344,11 @@ rescan: 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 --git a/drivers/usb/host/ohci-q.c b/drivers/usb/host/ohci-q.c index bb342d499c6db..b5f5f1f899b03 100644 --- a/drivers/usb/host/ohci-q.c +++ b/drivers/usb/host/ohci-q.c @@ -156,6 +156,7 @@ static void periodic_link (struct ohci_hcd *ohci, struct ed *ed) wmb (); *prev = ed; *prev_p = cpu_to_le32p (&ed->dma); + wmb(); } ohci->load [i] += ed->load; } @@ -195,6 +196,7 @@ static int ed_schedule (struct ohci_hcd *ohci, struct ed *ed) } 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 @@ static int ed_schedule (struct ohci_hcd *ohci, struct ed *ed) } 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 @@ static struct td *dl_reverse_done_list (struct ohci_hcd *ohci) 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. -- 2.53.0