]>
Commit | Line | Data |
---|---|---|
34a069e8 GKH |
1 | From feca7746d5d9e84b105a613b7f3b6ad00d327372 Mon Sep 17 00:00:00 2001 |
2 | From: Alan Stern <stern@rowland.harvard.edu> | |
3 | Date: Fri, 1 Mar 2013 10:51:15 -0500 | |
4 | Subject: USB: EHCI: don't check DMA values in QH overlays | |
5 | ||
6 | From: Alan Stern <stern@rowland.harvard.edu> | |
7 | ||
8 | commit feca7746d5d9e84b105a613b7f3b6ad00d327372 upstream. | |
9 | ||
10 | This patch (as1661) fixes a rather obscure bug in ehci-hcd. In a | |
11 | couple of places, the driver compares the DMA address stored in a QH's | |
12 | overlay region with the address of a particular qTD, in order to see | |
13 | whether that qTD is the one currently being processed by the hardware. | |
14 | (If it is then the status in the QH's overlay region is more | |
15 | up-to-date than the status in the qTD, and if it isn't then the | |
16 | overlay's value needs to be adjusted when the QH is added back to the | |
17 | active schedule.) | |
18 | ||
19 | However, DMA address in the overlay region isn't always valid. It | |
20 | sometimes will contain a stale value, which may happen by coincidence | |
21 | to be equal to a qTD's DMA address. Instead of checking the DMA | |
22 | address, we should check whether the overlay region is active and | |
23 | valid. The patch tests the ACTIVE bit in the overlay, and clears this | |
24 | bit when the overlay becomes invalid (which happens when the | |
25 | currently-executing URB is unlinked). | |
26 | ||
27 | This is the second part of a fix for the regression reported at: | |
28 | ||
29 | https://bugs.launchpad.net/bugs/1088733 | |
30 | ||
31 | Signed-off-by: Alan Stern <stern@rowland.harvard.edu> | |
32 | Reported-by: Joseph Salisbury <joseph.salisbury@canonical.com> | |
33 | Reported-and-tested-by: Stephen Thirlwall <sdt@dr.com> | |
34 | Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> | |
35 | ||
36 | --- | |
37 | drivers/usb/host/ehci-q.c | 18 +++++++++++++----- | |
38 | 1 file changed, 13 insertions(+), 5 deletions(-) | |
39 | ||
40 | --- a/drivers/usb/host/ehci-q.c | |
41 | +++ b/drivers/usb/host/ehci-q.c | |
42 | @@ -135,7 +135,7 @@ qh_refresh (struct ehci_hcd *ehci, struc | |
43 | * qtd is updated in qh_completions(). Update the QH | |
44 | * overlay here. | |
45 | */ | |
46 | - if (cpu_to_hc32(ehci, qtd->qtd_dma) == qh->hw->hw_current) { | |
47 | + if (qh->hw->hw_token & ACTIVE_BIT(ehci)) { | |
48 | qh->hw->hw_qtd_next = qtd->hw_next; | |
49 | qtd = NULL; | |
50 | } | |
51 | @@ -449,11 +449,19 @@ qh_completions (struct ehci_hcd *ehci, s | |
52 | else if (last_status == -EINPROGRESS && !urb->unlinked) | |
53 | continue; | |
54 | ||
55 | - /* qh unlinked; token in overlay may be most current */ | |
56 | - if (state == QH_STATE_IDLE | |
57 | - && cpu_to_hc32(ehci, qtd->qtd_dma) | |
58 | - == hw->hw_current) { | |
59 | + /* | |
60 | + * If this was the active qtd when the qh was unlinked | |
61 | + * and the overlay's token is active, then the overlay | |
62 | + * hasn't been written back to the qtd yet so use its | |
63 | + * token instead of the qtd's. After the qtd is | |
64 | + * processed and removed, the overlay won't be valid | |
65 | + * any more. | |
66 | + */ | |
67 | + if (state == QH_STATE_IDLE && | |
68 | + qh->qtd_list.next == &qtd->qtd_list && | |
69 | + (hw->hw_token & ACTIVE_BIT(ehci))) { | |
70 | token = hc32_to_cpu(ehci, hw->hw_token); | |
71 | + hw->hw_token &= ~ACTIVE_BIT(ehci); | |
72 | ||
73 | /* An unlink may leave an incomplete | |
74 | * async transaction in the TT buffer. |