EHCI: Update qTD next pointer in QH overlay region during unlink
There is a possibility of QH overlay region having reference to a stale qTD pointer during unlink. Consider an endpoint having two pending qTD before unlink process begins. The endpoint's QH queue looks like this. qTD1 --> qTD2 --> Dummy To unlink qTD2, QH is removed from asynchronous list and Asynchronous Advance Doorbell is programmed. The qTD1's next qTD pointer is set to qTD2'2 next qTD pointer and qTD2 is retired upon controller's doorbell interrupt. If QH's current qTD pointer points to qTD1, transfer overlay region still have reference to qTD2. But qtD2 is just unlinked and freed. This may cause EHCI system error. Fix this by updating qTD next pointer in QH overlay region with the qTD next pointer of the current qTD. Signed-off-by: Pavankumar Kondeti <pkondeti@codeaurora.org> Acked-by: Alan Stern <stern@rowland.harvard.edu> Cc: stable <stable@vger.kernel.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
parent
6a44886899
commit
3d037774b4
|
@ -128,9 +128,17 @@ qh_refresh (struct ehci_hcd *ehci, struct ehci_qh *qh)
|
||||||
else {
|
else {
|
||||||
qtd = list_entry (qh->qtd_list.next,
|
qtd = list_entry (qh->qtd_list.next,
|
||||||
struct ehci_qtd, qtd_list);
|
struct ehci_qtd, qtd_list);
|
||||||
/* first qtd may already be partially processed */
|
/*
|
||||||
if (cpu_to_hc32(ehci, qtd->qtd_dma) == qh->hw->hw_current)
|
* first qtd may already be partially processed.
|
||||||
|
* If we come here during unlink, the QH overlay region
|
||||||
|
* might have reference to the just unlinked qtd. The
|
||||||
|
* qtd is updated in qh_completions(). Update the QH
|
||||||
|
* overlay here.
|
||||||
|
*/
|
||||||
|
if (cpu_to_hc32(ehci, qtd->qtd_dma) == qh->hw->hw_current) {
|
||||||
|
qh->hw->hw_qtd_next = qtd->hw_next;
|
||||||
qtd = NULL;
|
qtd = NULL;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (qtd)
|
if (qtd)
|
||||||
|
|
Loading…
Reference in New Issue