Commit 5a346fe4 authored by David Brownell's avatar David Brownell Committed by Greg Kroah-Hartman

[PATCH] Re: ohci-hcd and that NCR implementation ...

The attached patch makes the one SiS controller behave
like the other... the key fix being wmb() to make sure that
no writes are still in CPU caches before telling the HC it's
OK to fetch the data.  (And a minor tweak to access PCI
less often through the hub driver.)

But the OPTi problem seems to be different.  Could you
try this patch to see if it affects the problem your seeing
with that NCR implementation?  And in any case, please
integrate it to Linus' latest.  (Against 2.5.10, might be
some fuzz on the pci tweak due to that warning fix.)

Those missing wmb() statements have likely been the root
cause of various usb-ohci flakes reported over time, too.
The drivers are still almost identical in those areas.  (Though
something made ohci-hcd consistently lose that cache flush
race; maybe it's a bit faster.)
parent a333596b
...@@ -154,12 +154,10 @@ static int ohci_hub_control ( ...@@ -154,12 +154,10 @@ static int ohci_hub_control (
u16 wLength u16 wLength
) { ) {
struct ohci_hcd *ohci = hcd_to_ohci (hcd); struct ohci_hcd *ohci = hcd_to_ohci (hcd);
int ports; int ports = hcd->self.root_hub->maxchild;
u32 temp; u32 temp;
int retval = 0; int retval = 0;
// if (port request)
ports = roothub_a (ohci) & RH_A_NDP;
switch (typeReq) { switch (typeReq) {
case ClearHubFeature: case ClearHubFeature:
switch (wValue) { switch (wValue) {
......
...@@ -569,6 +569,9 @@ td_fill (struct ohci_hcd *ohci, unsigned int info, ...@@ -569,6 +569,9 @@ td_fill (struct ohci_hcd *ohci, unsigned int info,
td->hwNextTD = cpu_to_le32 (td_pt->td_dma); td->hwNextTD = cpu_to_le32 (td_pt->td_dma);
td->hwPSW [0] = cpu_to_le16 ((data & 0x0FFF) | 0xE000); td->hwPSW [0] = cpu_to_le16 ((data & 0x0FFF) | 0xE000);
/* HC might read the TD right after we link it ... */
wmb ();
/* append to queue */ /* append to queue */
td->ed->hwTailP = td->hwNextTD; td->ed->hwTailP = td->hwNextTD;
} }
...@@ -641,8 +644,10 @@ static void td_submit_urb (struct urb *urb) ...@@ -641,8 +644,10 @@ static void td_submit_urb (struct urb *urb)
cnt++; cnt++;
} }
/* start bulk list */ /* start bulk list */
if (!ohci->sleeping) if (!ohci->sleeping) {
wmb ();
writel (OHCI_BLF, &ohci->regs->cmdstatus); writel (OHCI_BLF, &ohci->regs->cmdstatus);
}
break; break;
case PIPE_INTERRUPT: case PIPE_INTERRUPT:
...@@ -654,6 +659,7 @@ static void td_submit_urb (struct urb *urb) ...@@ -654,6 +659,7 @@ static void td_submit_urb (struct urb *urb)
break; break;
case PIPE_CONTROL: case PIPE_CONTROL:
/* control requests don't use toggle state */
info = TD_CC | TD_DP_SETUP | TD_T_DATA0; info = TD_CC | TD_DP_SETUP | TD_T_DATA0;
td_fill (ohci, info, td_fill (ohci, info,
#ifdef CONFIG_PCI #ifdef CONFIG_PCI
...@@ -678,8 +684,10 @@ static void td_submit_urb (struct urb *urb) ...@@ -678,8 +684,10 @@ static void td_submit_urb (struct urb *urb)
: TD_CC | TD_DP_OUT | TD_T_DATA1; : TD_CC | TD_DP_OUT | TD_T_DATA1;
td_fill (ohci, info, data, 0, urb, cnt++); td_fill (ohci, info, data, 0, urb, cnt++);
/* start control list */ /* start control list */
if (!ohci->sleeping) if (!ohci->sleeping) {
wmb ();
writel (OHCI_CLF, &ohci->regs->cmdstatus); writel (OHCI_CLF, &ohci->regs->cmdstatus);
}
break; break;
case PIPE_ISOCHRONOUS: case PIPE_ISOCHRONOUS:
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment