On Sat, 21 Nov 2009, Oliver Neukum wrote: > Am Dienstag, 17. November 2009 17:10:10 schrieb Alan Stern: > > > I'd like it if there was also some way to move the delay into > > disable_periodic(), before the handshake_on_error_set_halt(), and have > > it take effect only if the most recent enable_periodic() call occurred > > less than 400 us previously. Can you do it that way? > > Sure. > Does anybody have a list of affected PCI ids? There is a single ID in the lcpci output attached to the bug report at freedesktop.org. Most of the reporters seem to be using the same (or very similar) sort of netbook, so maybe there's only one ID to worry about. > diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c > index 9835e07..ebdfc93 100644 > --- a/drivers/usb/host/ehci-hcd.c > +++ b/drivers/usb/host/ehci-hcd.c > @@ -676,6 +676,7 @@ static int ehci_run (struct usb_hcd *hcd) > ehci_readl(ehci, &ehci->regs->command); /* unblock posted writes */ > msleep(5); > up_write(&ehci_cf_port_reset_rwsem); > + ehci->last_periodic_disable = jiffies; > > temp = HC_VERSION(ehci_readl(ehci, &ehci->caps->hc_capbase)); > ehci_info (ehci, > diff --git a/drivers/usb/host/ehci-sched.c b/drivers/usb/host/ehci-sched.c > index b25cdea..586e901 100644 > --- a/drivers/usb/host/ehci-sched.c > +++ b/drivers/usb/host/ehci-sched.c > @@ -459,6 +459,10 @@ static int enable_periodic (struct ehci_hcd *ehci) > if (ehci->periodic_sched++) > return 0; > > + if (ehci->broken_periodic) > + if (time_before(jiffies, ehci->last_periodic_disable + msecs_to_jiffies(2)) > + mdelay(500); > + > /* did clearing PSE did take effect yet? > * takes effect only at frame boundaries... > */ > @@ -499,6 +503,7 @@ static int disable_periodic (struct ehci_hcd *ehci) > /* posted write ... */ > > ehci->next_uframe = -1; > + ehci->last_periodic_disable = jiffies; > return 0; Ooh, no. The delay should be 500 _microseconds_, not _milliseconds_. The precision of a jiffies counter won't be good enough; you'll have to use something like do_gettimeofday(), as in mon_get_timestamp(). Also, what needs to be stored is not the time of the last periodic disable but rather the time of the last enable. The idea is that the periodic schedule must be allowed to run for at least 500 us before the driver tries to turn it off. A possible optimization would be to delay for (500 us - elapsed time) instead of the full 500 us. Or the whole thing could be simplified by doing the full delay always, without any regard to the elapsed time -- but this would be less efficient. Alan Stern -- To unsubscribe from this list: send the line "unsubscribe linux-usb" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html