]>
Commit | Line | Data |
---|---|---|
3d6a91bc GKH |
1 | From 7a3783efffc7bc2e702d774e47fad5b8e37e9ad1 Mon Sep 17 00:00:00 2001 |
2 | From: Paul Zimmerman <Paul.Zimmerman@synopsys.com> | |
3 | Date: Wed, 17 Nov 2010 16:26:50 -0800 | |
4 | Subject: xhci: Fix reset-device and configure-endpoint commands | |
5 | ||
6 | From: Paul Zimmerman <Paul.Zimmerman@synopsys.com> | |
7 | ||
8 | commit 7a3783efffc7bc2e702d774e47fad5b8e37e9ad1 upstream. | |
9 | ||
10 | We have been having problems with the USB-IF Gold Tree tests when plugging | |
11 | and unplugging devices from the tree. I have seen that the reset-device | |
12 | and configure-endpoint commands, which are invoked from | |
13 | xhci_discover_or_reset_device() and xhci_configure_endpoint(), will sometimes | |
14 | time out. | |
15 | ||
16 | After much debugging, I determined that the commands themselves do not actually | |
17 | time out, but rather their completion events do not get delivered to the right | |
18 | place. | |
19 | ||
20 | This happens when the command ring has just wrapped around, and it's enqueue | |
21 | pointer is left pointing to the link TRB. xhci_discover_or_reset_device() and | |
22 | xhci_configure_endpoint() use the enqueue pointer directly as their command | |
23 | TRB pointer, without checking whether it's pointing to the link TRB. | |
24 | ||
25 | When the completion event arrives, if the command TRB is pointing to the link | |
26 | TRB, the check against the command ring dequeue pointer in | |
27 | handle_cmd_in_cmd_wait_list() fails, so the completion inside the command does | |
28 | not get signaled. | |
29 | ||
30 | The patch below fixes the timeout problem for me. | |
31 | ||
32 | This should be queued for the 2.6.35 and 2.6.36 stable trees. | |
33 | ||
34 | Signed-off-by: Paul Zimmerman <paulz@synopsys.com> | |
35 | Signed-off-by: Sarah Sharp <sarah.a.sharp@linux.intel.com> | |
36 | Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> | |
37 | ||
38 | --- | |
39 | drivers/usb/host/xhci.c | 18 ++++++++++++++++++ | |
40 | 1 file changed, 18 insertions(+) | |
41 | ||
42 | --- a/drivers/usb/host/xhci.c | |
43 | +++ b/drivers/usb/host/xhci.c | |
44 | @@ -1284,6 +1284,15 @@ static int xhci_configure_endpoint(struc | |
45 | cmd_completion = command->completion; | |
46 | cmd_status = &command->status; | |
47 | command->command_trb = xhci->cmd_ring->enqueue; | |
48 | + | |
49 | + /* Enqueue pointer can be left pointing to the link TRB, | |
50 | + * we must handle that | |
51 | + */ | |
52 | + if ((command->command_trb->link.control & TRB_TYPE_BITMASK) | |
53 | + == TRB_TYPE(TRB_LINK)) | |
54 | + command->command_trb = | |
55 | + xhci->cmd_ring->enq_seg->next->trbs; | |
56 | + | |
57 | list_add_tail(&command->cmd_list, &virt_dev->cmd_list); | |
58 | } else { | |
59 | in_ctx = virt_dev->in_ctx; | |
60 | @@ -1993,6 +2002,15 @@ int xhci_reset_device(struct usb_hcd *hc | |
61 | /* Attempt to submit the Reset Device command to the command ring */ | |
62 | spin_lock_irqsave(&xhci->lock, flags); | |
63 | reset_device_cmd->command_trb = xhci->cmd_ring->enqueue; | |
64 | + | |
65 | + /* Enqueue pointer can be left pointing to the link TRB, | |
66 | + * we must handle that | |
67 | + */ | |
68 | + if ((reset_device_cmd->command_trb->link.control & TRB_TYPE_BITMASK) | |
69 | + == TRB_TYPE(TRB_LINK)) | |
70 | + reset_device_cmd->command_trb = | |
71 | + xhci->cmd_ring->enq_seg->next->trbs; | |
72 | + | |
73 | list_add_tail(&reset_device_cmd->cmd_list, &virt_dev->cmd_list); | |
74 | ret = xhci_queue_reset_device(xhci, slot_id); | |
75 | if (ret) { |