Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>

authored by

Sarah Sharp and committed by
Greg Kroah-Hartman
a50c8aa9 913a8a34

+29 -17
+29 -17
drivers/usb/host/xhci-ring.c
··· 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 + */ 692 + static 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 + 688 716 static void handle_cmd_completion(struct xhci_hcd *xhci, 689 717 struct xhci_event_cmd *event) 690 718 { ··· 752 724 break; 753 725 case TRB_TYPE(TRB_CONFIG_EP): 754 726 virt_dev = xhci->devs[slot_id]; 755 - /* Check to see if a command in the device's command queue 756 - * matches this one. Signal the completion or free the command. 757 - */ 758 - if (!list_empty(&virt_dev->cmd_list)) { 759 - struct xhci_command *command; 760 - command = list_entry(virt_dev->cmd_list.next, 761 - struct xhci_command, cmd_list); 762 - if (xhci->cmd_ring->dequeue == command->command_trb) { 763 - command->status = 764 - GET_COMP_CODE(event->status); 765 - list_del(&command->cmd_list); 766 - if (command->completion) 767 - complete(command->completion); 768 - else 769 - xhci_free_command(xhci, command); 770 - } 727 + if (handle_cmd_in_cmd_wait_list(xhci, virt_dev, event)) 771 728 break; 772 - } 773 729 /* 774 730 * Configure endpoint commands can come from the USB core 775 731 * configuration or alt setting changes, or because the HW