Re: BisonCam 5986:0203 kills USB

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



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

[Index of Archives]     [Linux Media]     [Linux Input]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]     [Old Linux USB Devel Archive]

  Powered by Linux