aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb
diff options
context:
space:
mode:
authorSarah Sharp <sarah.a.sharp@linux.intel.com>2009-09-04 13:53:15 -0400
committerGreg Kroah-Hartman <gregkh@suse.de>2009-09-23 09:46:40 -0400
commita50c8aa953c65fd690eca03a2618ac445a3da05d (patch)
treeb3a6a20e681bd38df1e9f0885afa0a7b4ff78b43 /drivers/usb
parent913a8a344ffcaf0b4a586d6662a2c66a7106557d (diff)
USB: xhci: Fix command wait list handling.
In the xHCI driver, configure endpoint commands that are submitted to the hardware may involve one of two data structures. If the configure endpoint command is setting up a new configuration or modifying max packet sizes, the data structures and completions are statically allocated in the xhci_virt_device structure. If the command is being used to set up streams or add hub information, then the data structures are dynamically allocated, and placed on a device command waiting list. Break out the code to check whether a completed command is in the device command waiting list. Fix a subtle bug in the old code: continue processing the command if the command isn't in the wait list. In the old code, if there was a command in the wait list, but it didn't match the completed command, the completed command event would be dropped. Signed-off-by: Sarah Sharp <sarah.a.sharp@linux.intel.com> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers/usb')
-rw-r--r--drivers/usb/host/xhci-ring.c46
1 files changed, 29 insertions, 17 deletions
diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c
index a9379b3bebaf..2274604e863e 100644
--- a/drivers/usb/host/xhci-ring.c
+++ b/drivers/usb/host/xhci-ring.c
@@ -685,6 +685,34 @@ static void handle_reset_ep_completion(struct xhci_hcd *xhci,
685 } 685 }
686} 686}
687 687
688/* Check to see if a command in the device's command queue matches this one.
689 * Signal the completion or free the command, and return 1. Return 0 if the
690 * completed command isn't at the head of the command list.
691 */
692static int handle_cmd_in_cmd_wait_list(struct xhci_hcd *xhci,
693 struct xhci_virt_device *virt_dev,
694 struct xhci_event_cmd *event)
695{
696 struct xhci_command *command;
697
698 if (list_empty(&virt_dev->cmd_list))
699 return 0;
700
701 command = list_entry(virt_dev->cmd_list.next,
702 struct xhci_command, cmd_list);
703 if (xhci->cmd_ring->dequeue != command->command_trb)
704 return 0;
705
706 command->status =
707 GET_COMP_CODE(event->status);
708 list_del(&command->cmd_list);
709 if (command->completion)
710 complete(command->completion);
711 else
712 xhci_free_command(xhci, command);
713 return 1;
714}
715
688static void handle_cmd_completion(struct xhci_hcd *xhci, 716static void handle_cmd_completion(struct xhci_hcd *xhci,
689 struct xhci_event_cmd *event) 717 struct xhci_event_cmd *event)
690{ 718{
@@ -724,24 +752,8 @@ static void handle_cmd_completion(struct xhci_hcd *xhci,
724 break; 752 break;
725 case TRB_TYPE(TRB_CONFIG_EP): 753 case TRB_TYPE(TRB_CONFIG_EP):
726 virt_dev = xhci->devs[slot_id]; 754 virt_dev = xhci->devs[slot_id];
727 /* Check to see if a command in the device's command queue 755 if (handle_cmd_in_cmd_wait_list(xhci, virt_dev, event))
728 * matches this one. Signal the completion or free the command.
729 */
730 if (!list_empty(&virt_dev->cmd_list)) {
731 struct xhci_command *command;
732 command = list_entry(virt_dev->cmd_list.next,
733 struct xhci_command, cmd_list);
734 if (xhci->cmd_ring->dequeue == command->command_trb) {
735 command->status =
736 GET_COMP_CODE(event->status);
737 list_del(&command->cmd_list);
738 if (command->completion)
739 complete(command->completion);
740 else
741 xhci_free_command(xhci, command);
742 }
743 break; 756 break;
744 }
745 /* 757 /*
746 * Configure endpoint commands can come from the USB core 758 * Configure endpoint commands can come from the USB core
747 * configuration or alt setting changes, or because the HW 759 * configuration or alt setting changes, or because the HW