mirror of
https://github.com/torvalds/linux.git
synced 2024-11-06 03:51:48 +00:00
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>
This commit is contained in:
parent
913a8a344f
commit
a50c8aa953
@ -685,6 +685,34 @@ static void handle_reset_ep_completion(struct xhci_hcd *xhci,
|
||||
}
|
||||
}
|
||||
|
||||
/* Check to see if a command in the device's command queue matches this one.
|
||||
* Signal the completion or free the command, and return 1. Return 0 if the
|
||||
* completed command isn't at the head of the command list.
|
||||
*/
|
||||
static int handle_cmd_in_cmd_wait_list(struct xhci_hcd *xhci,
|
||||
struct xhci_virt_device *virt_dev,
|
||||
struct xhci_event_cmd *event)
|
||||
{
|
||||
struct xhci_command *command;
|
||||
|
||||
if (list_empty(&virt_dev->cmd_list))
|
||||
return 0;
|
||||
|
||||
command = list_entry(virt_dev->cmd_list.next,
|
||||
struct xhci_command, cmd_list);
|
||||
if (xhci->cmd_ring->dequeue != command->command_trb)
|
||||
return 0;
|
||||
|
||||
command->status =
|
||||
GET_COMP_CODE(event->status);
|
||||
list_del(&command->cmd_list);
|
||||
if (command->completion)
|
||||
complete(command->completion);
|
||||
else
|
||||
xhci_free_command(xhci, command);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void handle_cmd_completion(struct xhci_hcd *xhci,
|
||||
struct xhci_event_cmd *event)
|
||||
{
|
||||
@ -724,24 +752,8 @@ static void handle_cmd_completion(struct xhci_hcd *xhci,
|
||||
break;
|
||||
case TRB_TYPE(TRB_CONFIG_EP):
|
||||
virt_dev = xhci->devs[slot_id];
|
||||
/* Check to see if a command in the device's command queue
|
||||
* matches this one. Signal the completion or free the command.
|
||||
*/
|
||||
if (!list_empty(&virt_dev->cmd_list)) {
|
||||
struct xhci_command *command;
|
||||
command = list_entry(virt_dev->cmd_list.next,
|
||||
struct xhci_command, cmd_list);
|
||||
if (xhci->cmd_ring->dequeue == command->command_trb) {
|
||||
command->status =
|
||||
GET_COMP_CODE(event->status);
|
||||
list_del(&command->cmd_list);
|
||||
if (command->completion)
|
||||
complete(command->completion);
|
||||
else
|
||||
xhci_free_command(xhci, command);
|
||||
}
|
||||
if (handle_cmd_in_cmd_wait_list(xhci, virt_dev, event))
|
||||
break;
|
||||
}
|
||||
/*
|
||||
* Configure endpoint commands can come from the USB core
|
||||
* configuration or alt setting changes, or because the HW
|
||||
|
Loading…
Reference in New Issue
Block a user