On Thu, 6 Sep 2012, Pavan Kondeti wrote:

> Hi
> 
> I am debugging "EHCI host system error" (4.15.2.4) issue. The issue
> happens during unlinking of URB from an interface driver. In our system
> the device is always connected to the host. some interfaces are always
> active (I/O can happen). Other interface's I/O depends on the user
> space. if user opens the device node, we submit IN URB. This issue
> happens when unlinking URB upon file close. This issue happens very rarely.
> 
> I have a doubt in unlink path of EHCI driver. Say if an endpoint has two
> pending IN URB requests at the time of calling unlinking API.
> (usb_kill_anchored_urbs API).
> 
> The QH's queue of this endpoint looks like this.
> 
> Qtd1 --> Qtd2 --> Dummy
> 
> EHCI driver kicks in the Async Advance Doorbell handshake after
> manipulating the QH horizontal pointer in start_unlink_async() function.
> EHCI driver wait for IAAD interrupt from the controller.
> 
> Say controller is working on Qtd1. Which means transfer overlay of this
> QH has reference to Qtd2. controller generates IAAD interrupt (Qtd1 is
> not completely finished. QH active pointer points to Qtd1). EHCI driver
> finishes Qtd2 unlinking and points qtd1's next pointer to qtd'2 next
> pointer and puts this QH back to asynchronous schedule.
> 
> My doubt is that software updated only QTD1 memory to point it to Qtd'2
> next pointer i.e dummy. What about the QH's transfer overlay memory?
> Would not the controller try to access the Qtd2 when QH is put back into
> schedule.
> 
> To further clarify my question, I am copy pasting the qh_refresh() code
> here. In the below code, if we enter "first qtd may already be partially
> processed" case, should not we update qh->hw->hw_qtd_next and
> qh->hw->hw_alt_next to reflect the current Qtd memory.
> 
> static void
> qh_refresh (struct ehci_hcd *ehci, struct ehci_qh *qh)
> {
>         struct ehci_qtd *qtd;
> 
>         if (list_empty (&qh->qtd_list))
>                 qtd = qh->dummy;
>         else {
>                 qtd = list_entry (qh->qtd_list.next,
>                                 struct ehci_qtd, qtd_list);
>                 /* first qtd may already be partially processed */
>                 if (cpu_to_hc32(ehci, qtd->qtd_dma) == qh->hw->hw_current)
>                         qtd = NULL;
>         }
> 
>         if (qtd)
>                 qh_update (ehci, qh, qtd);
> }

You're absolutely right; this is a bug in the driver.  Would you like 
to submit a patch to fix it?

(It shouldn't be necessary to update the hw_alt_next field.  The 
hw_alt_next part of the qTD doesn't get changed when the following qTD 
is removed.)

Alan Stern

--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to