Dan Streetman wrote:
...
> diff -ur usb-2.5/drivers/usb/host/uhci-hcd.c linux/drivers/usb/host/uhci-hcd.c
> --- usb-2.5/drivers/usb/host/uhci-hcd.c Fri Oct 11 16:52:49 2002
> +++ linux/drivers/usb/host/uhci-hcd.c   Fri Oct 11 16:59:53 2002
...
> @@ -545,9 +529,16 @@
>         urbp->qh->link = eurbp->qh->link;
> 
>         mb();                   /* Make sure we flush everything */
> +
>         lltd->link = cpu_to_le32(urbp->qh->dma_handle) | UHCI_PTR_QH;
> 
> +       /* If the HC wrote lltd->link (which used to point to TERM) back into 
>lurb->qh->element
> +        * before we wrote lltd->link, fix lurb->qh->element
> +        */
> +       mb();
> +       if (lurbp->qh->element == UHCI_PTR_TERM)
> +         lurbp->qh->element = lltd->link;
> +
>         list_add_tail(&urbp->queue_list, &furbp->queue_list);
> 
>         urbp->queued = 1;

You are still racing with hardware. Consider:

1. HC reads lltd->link (still ==TERM)
2. HCD sets lltd->link
3. HCD checks lurbp->qh->element (still !=TERM)
4. HCD does not set lurbp->qh->element
5. HC sets lurbp->qh->element to TERM (from step 1)
=> dropped transfer 

or (unlikely, but not impossible)

1. HCD sets lltd->link
2. HC reads lltd->link
3. HC sets lurbp->qh->element
4. HC reads lurbp->qh->element
3. HC processes transfer
4. HC reads lltd->link->link (assumed ==TERM; second "->link" is, of
course, not correct C)
5. HC sets lurbp->qh->element
6. HCD checks lurbp->qh->element (==TERM)
7. HCD sets lltd->link
8. double transfer/toggle error

...
> @@ -623,6 +640,15 @@
>                         /* The next URB happens to be the beginning, so */
>                         /*  we're the last, end the chain */
>                         pltd->link = UHCI_PTR_TERM;
> +
> +               pqh = purbp->qh; /* set to previous QH in our endpoint's queue */
> +
> +               /* If the HC wrote pltd->link (which used to point to our QH) back 
>into pqh->element
> +                * before we wrote pltd->link, fix pqh->element
> +                */
> +               mb();
> +               if (pqh->element == (cpu_to_le32(urbp->qh->dma_handle) | 
>UHCI_PTR_QH))
> +                 pqh->element = pltd->link;
>         }
> 
>         list_del_init(&urbp->queue_list);

Same here, I guess.

Regards,
        Stephan


-------------------------------------------------------
This sf.net email is sponsored by:ThinkGeek
Welcome to geek heaven.
http://thinkgeek.com/sf
_______________________________________________
[EMAIL PROTECTED]
To unsubscribe, use the last form field at:
https://lists.sourceforge.net/lists/listinfo/linux-usb-devel

Reply via email to