[PATCH 5/9] xhci: Fix command wait list handling.

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



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@xxxxxxxxxxxxxxx>
---
 drivers/usb/host/xhci-ring.c |   46 ++++++++++++++++++++++++++---------------
 1 files changed, 29 insertions(+), 17 deletions(-)

diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c
index a9379b3..2274604 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,
 	}
 }
 
+/* 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
-- 
1.6.0.4

--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html

[Index of Archives]     [Linux Media]     [Linux Input]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]     [Old Linux USB Devel Archive]

  Powered by Linux