The Linux Kernel Mailing List
 help / color / mirror / Atom feed
* [RFCv3 0/4] xhci: re-work command queue management
@ 2014-02-26 19:38 Mathias Nyman
  2014-02-26 19:38 ` [RFCv3 1/4] xhci: Use command structures when queuing commands on the command ring Mathias Nyman
                   ` (3 more replies)
  0 siblings, 4 replies; 7+ messages in thread
From: Mathias Nyman @ 2014-02-26 19:38 UTC (permalink / raw)
  To: linux-usb; +Cc: sarah.a.sharp, dan.j.williams, linux-kernel, Mathias Nyman

changes since v2:

    squash first 7 patches together that all just created commands 
    and avoid some nasty mid-patch series memory leaking	  

changes since v1: 

    Fixing smatch warnings and errors.
    Check for null return from alloc_command, release lock in error path and
    don't dereference possible null pointer in error path.

    release lock in xhci_stop_dev() error path.
    
This is the third attempt to re-work and solve the issues in xhci command
queue management that Sarah has described earlier:

Right now, the command management in the xHCI driver is rather ad-hock.  
Different parts of the driver all submit commands, including interrupt 
handling routines, functions called from the USB core (with or without the
bus bandwidth mutex held).
Some times they need to wait for the command to complete, and sometimes 
they just issue the command and don't care about the result of the command.

The places that wait on a command all time the command for five seconds,
and then attempt to cancel the command.  
Unfortunately, that means if several commands are issued at once, and one of
them times out, all the commands timeout, even though the host hasn't gotten
a chance to service them yet.

This is apparent with some devices that take a long time to respond to the 
Set Address command during device enumeration (when the device is plugged in).
If a driver for a different device attempts to change alternate interface
settings at the same time (causing a Configure Endpoint command to be issued),
both commands timeout.

Instead of having each command timeout after five seconds, the driver should
wait indefinitely in an uninterruptible sleep on the command completion.  
A global command queue manager should time whatever command is currently
running, and cancel that command after five seconds.

If the commands were in a list, like TDs currently are, it may be easier to keep
track of where the command ring dequeue pointer is, and avoid racing with events.
We may need to have parts of the driver that issue commands without waiting on
them still put the commands in the command list.

The Implementation:
-------------------

First step is to create a list of the commands submitted to the command queue.
To accomplish this each command is required to be submitted with a properly
filled command structure containing completion, status variable and a pointer to
the command TRB that will be used.

The first patch is all about creating these command structures and
submitting them when we queue commands.
The command structures are allocated on the fly, the commands that are submitted
in interrupt context are allocated with GFP_ATOMIC.

Next, the global command queue is introduced. Commands structures are added to 
the queue when trb's are queued, and removed when the command completes. 
Also switch to use the status variable and completion in the command struct.

A new timer handles command timeout, the timer is kicked every time when a 
command finishes and there's a new command waiting in the queue, or when a new
command is submitted to an _empty_ command queue.
Timer is deleted when the the last command on the queue finishes (empty queue)

The old cancel_cmd_list is removed. 
When the timer expires we simply tag the current command as "ABORTED" and start
the ring abortion process. Functions waiting for an aborted command to finish are
called after the command abortion is completed.

Mathias Nyman (4):
  xhci: Use command structures when queuing commands on the command ring
  xhci: Add a global command queue
  xhci: Use completion and status in global command queue
  xhci: rework command timeout and cancellation,

 drivers/usb/host/xhci-hub.c  |  43 ++--
 drivers/usb/host/xhci-mem.c  |  22 +-
 drivers/usb/host/xhci-ring.c | 529 ++++++++++++++-----------------------------
 drivers/usb/host/xhci.c      | 264 +++++++++++----------
 drivers/usb/host/xhci.h      |  43 ++--
 5 files changed, 373 insertions(+), 528 deletions(-)

-- 
1.8.1.2


^ permalink raw reply	[flat|nested] 7+ messages in thread

* [RFCv3 1/4] xhci: Use command structures when queuing commands on the command ring
  2014-02-26 19:38 [RFCv3 0/4] xhci: re-work command queue management Mathias Nyman
@ 2014-02-26 19:38 ` Mathias Nyman
  2014-03-06 21:15   ` Sarah Sharp
  2014-02-26 19:38 ` [RFCv3 2/4] xhci: Add a global command queue Mathias Nyman
                   ` (2 subsequent siblings)
  3 siblings, 1 reply; 7+ messages in thread
From: Mathias Nyman @ 2014-02-26 19:38 UTC (permalink / raw)
  To: linux-usb; +Cc: sarah.a.sharp, dan.j.williams, linux-kernel, Mathias Nyman

To create a global command queue we require that each command put on the
command ring is submitted with a command structure.

Functions that queue commands and wait for completion need to allocate a command
before submitting it, and free it once completed. The following command queuing
functions need to be modified.

xhci_configure_endpoint()
xhci_address_device()
xhci_queue_slot_control()
xhci_queue_stop_endpoint()
xhci_queue_new_dequeue_state()
xhci_queue_reset_ep()
xhci_configure_endpoint()

xhci_configure_endpoint() could already be called with a command structure,
and only xhci_check_maxpacket and xhci_check_bandwidth did not do so. These
are changed and a command structure is now required. This change also simplifies
the configure endpoint command completion handling and the "goto bandwidth_change"
handling code can be removed.

In some cases the command queuing function is called in interrupt context.
These commands needs to be allocated atomically, and they can't wait for
completion. These commands will in this patch be freed directly after queuing,
but freeing will be moved to the command completion event handler in a later
patch once we get the global command queue up.(Just so that we won't leak
memory in the middle of the patch set)

Signed-off-by: Mathias Nyman <mathias.nyman@linux.intel.com>
---
 drivers/usb/host/xhci-hub.c  |  21 +++--
 drivers/usb/host/xhci-ring.c | 105 ++++++++++++-----------
 drivers/usb/host/xhci.c      | 194 ++++++++++++++++++++++++++++---------------
 drivers/usb/host/xhci.h      |  31 +++----
 4 files changed, 214 insertions(+), 137 deletions(-)

diff --git a/drivers/usb/host/xhci-hub.c b/drivers/usb/host/xhci-hub.c
index 9992fbf..fb0f936 100644
--- a/drivers/usb/host/xhci-hub.c
+++ b/drivers/usb/host/xhci-hub.c
@@ -20,7 +20,8 @@
  * Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  */
 
-#include <linux/gfp.h>
+
+#include <linux/slab.h>
 #include <asm/unaligned.h>
 
 #include "xhci.h"
@@ -284,12 +285,22 @@ static int xhci_stop_device(struct xhci_hcd *xhci, int slot_id, int suspend)
 
 	spin_lock_irqsave(&xhci->lock, flags);
 	for (i = LAST_EP_INDEX; i > 0; i--) {
-		if (virt_dev->eps[i].ring && virt_dev->eps[i].ring->dequeue)
-			xhci_queue_stop_endpoint(xhci, slot_id, i, suspend);
+		if (virt_dev->eps[i].ring && virt_dev->eps[i].ring->dequeue) {
+			struct xhci_command *command;
+			command = xhci_alloc_command(xhci, false, false,
+						     GFP_NOIO);
+			if (!command) {
+				spin_unlock_irqrestore(&xhci->lock, flags);
+				xhci_free_command(xhci, cmd);
+				return -ENOMEM;
+
+			}
+			xhci_queue_stop_endpoint(xhci, command, slot_id, i,
+						 suspend);
+		}
 	}
-	cmd->command_trb = xhci_find_next_enqueue(xhci->cmd_ring);
 	list_add_tail(&cmd->cmd_list, &virt_dev->cmd_list);
-	xhci_queue_stop_endpoint(xhci, slot_id, 0, suspend);
+	xhci_queue_stop_endpoint(xhci, cmd, slot_id, 0, suspend);
 	xhci_ring_cmd_db(xhci);
 	spin_unlock_irqrestore(&xhci->lock, flags);
 
diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c
index 0ed64eb..fa34c9b 100644
--- a/drivers/usb/host/xhci-ring.c
+++ b/drivers/usb/host/xhci-ring.c
@@ -123,16 +123,6 @@ static int enqueue_is_link_trb(struct xhci_ring *ring)
 	return TRB_TYPE_LINK_LE32(link->control);
 }
 
-union xhci_trb *xhci_find_next_enqueue(struct xhci_ring *ring)
-{
-	/* Enqueue pointer can be left pointing to the link TRB,
-	 * we must handle that
-	 */
-	if (TRB_TYPE_LINK_LE32(ring->enqueue->link.control))
-		return ring->enq_seg->next->trbs;
-	return ring->enqueue;
-}
-
 /* Updates trb to point to the next TRB in the ring, and updates seg if the next
  * TRB is in a new segment.  This does not skip over link TRBs, and it does not
  * effect the ring dequeue or enqueue pointers.
@@ -674,12 +664,14 @@ static void td_to_noop(struct xhci_hcd *xhci, struct xhci_ring *ep_ring,
 	}
 }
 
-static int queue_set_tr_deq(struct xhci_hcd *xhci, int slot_id,
+static int queue_set_tr_deq(struct xhci_hcd *xhci,
+		struct xhci_command *cmd, int slot_id,
 		unsigned int ep_index, unsigned int stream_id,
 		struct xhci_segment *deq_seg,
 		union xhci_trb *deq_ptr, u32 cycle_state);
 
 void xhci_queue_new_dequeue_state(struct xhci_hcd *xhci,
+		struct xhci_command *cmd,
 		unsigned int slot_id, unsigned int ep_index,
 		unsigned int stream_id,
 		struct xhci_dequeue_state *deq_state)
@@ -694,7 +686,7 @@ void xhci_queue_new_dequeue_state(struct xhci_hcd *xhci,
 			deq_state->new_deq_ptr,
 			(unsigned long long)xhci_trb_virt_to_dma(deq_state->new_deq_seg, deq_state->new_deq_ptr),
 			deq_state->new_cycle_state);
-	queue_set_tr_deq(xhci, slot_id, ep_index, stream_id,
+	queue_set_tr_deq(xhci, cmd, slot_id, ep_index, stream_id,
 			deq_state->new_deq_seg,
 			deq_state->new_deq_ptr,
 			(u32) deq_state->new_cycle_state);
@@ -849,7 +841,9 @@ remove_finished_td:
 
 	/* If necessary, queue a Set Transfer Ring Dequeue Pointer command */
 	if (deq_state.new_deq_ptr && deq_state.new_deq_seg) {
-		xhci_queue_new_dequeue_state(xhci,
+		struct xhci_command *command;
+		command = xhci_alloc_command(xhci, false, false, GFP_ATOMIC);
+		xhci_queue_new_dequeue_state(xhci, command,
 				slot_id, ep_index,
 				ep->stopped_td->urb->stream_id,
 				&deq_state);
@@ -1174,9 +1168,11 @@ static void xhci_handle_cmd_reset_ep(struct xhci_hcd *xhci, int slot_id,
 	 * because the HW can't handle two commands being queued in a row.
 	 */
 	if (xhci->quirks & XHCI_RESET_EP_QUIRK) {
+		struct xhci_command *command;
+		command = xhci_alloc_command(xhci, false, false, GFP_ATOMIC);
 		xhci_dbg_trace(xhci, trace_xhci_dbg_quirks,
 				"Queueing configure endpoint command");
-		xhci_queue_configure_endpoint(xhci,
+		xhci_queue_configure_endpoint(xhci, command,
 				xhci->devs[slot_id]->in_ctx->dma, slot_id,
 				false);
 		xhci_ring_cmd_db(xhci);
@@ -1433,7 +1429,7 @@ static void xhci_handle_cmd_config_ep(struct xhci_hcd *xhci, int slot_id,
 			add_flags - SLOT_FLAG == drop_flags) {
 		ep_state = virt_dev->eps[ep_index].ep_state;
 		if (!(ep_state & EP_HALTED))
-			goto bandwidth_change;
+			return;
 		xhci_dbg_trace(xhci, trace_xhci_dbg_quirks,
 				"Completed config ep cmd - "
 				"last ep index = %d, state = %d",
@@ -1443,11 +1439,6 @@ static void xhci_handle_cmd_config_ep(struct xhci_hcd *xhci, int slot_id,
 		ring_doorbell_for_active_rings(xhci, slot_id, ep_index);
 		return;
 	}
-bandwidth_change:
-	xhci_dbg_trace(xhci,  trace_xhci_dbg_context_change,
-			"Completed config ep cmd");
-	virt_dev->cmd_status = cmd_comp_code;
-	complete(&virt_dev->cmd_completion);
 	return;
 }
 
@@ -1906,12 +1897,16 @@ static void xhci_cleanup_halted_endpoint(struct xhci_hcd *xhci,
 		struct xhci_td *td, union xhci_trb *event_trb)
 {
 	struct xhci_virt_ep *ep = &xhci->devs[slot_id]->eps[ep_index];
+	struct xhci_command *command;
+	command = xhci_alloc_command(xhci, false, false, GFP_ATOMIC);
+	if (!command)
+		return;
 	ep->ep_state |= EP_HALTED;
 	ep->stopped_td = td;
 	ep->stopped_trb = event_trb;
 	ep->stopped_stream = stream_id;
 
-	xhci_queue_reset_ep(xhci, slot_id, ep_index);
+	xhci_queue_reset_ep(xhci, command, slot_id, ep_index);
 	xhci_cleanup_stalled_ring(xhci, td->urb->dev, ep_index);
 
 	ep->stopped_td = NULL;
@@ -2626,7 +2621,7 @@ static int handle_tx_event(struct xhci_hcd *xhci,
 				 * successful event after a short transfer.
 				 * Ignore it.
 				 */
-				if ((xhci->quirks & XHCI_SPURIOUS_SUCCESS) && 
+				if ((xhci->quirks & XHCI_SPURIOUS_SUCCESS) &&
 						ep_ring->last_td_was_short) {
 					ep_ring->last_td_was_short = false;
 					ret = 0;
@@ -3968,8 +3963,9 @@ int xhci_queue_isoc_tx_prepare(struct xhci_hcd *xhci, gfp_t mem_flags,
  * Don't decrement xhci->cmd_ring_reserved_trbs after we've queued the TRB
  * because the command event handler may want to resubmit a failed command.
  */
-static int queue_command(struct xhci_hcd *xhci, u32 field1, u32 field2,
-		u32 field3, u32 field4, bool command_must_succeed)
+static int queue_command(struct xhci_hcd *xhci, struct xhci_command *cmd,
+			 u32 field1, u32 field2,
+			 u32 field3, u32 field4, bool command_must_succeed)
 {
 	int reserved_trbs = xhci->cmd_ring_reserved_trbs;
 	int ret;
@@ -3986,57 +3982,65 @@ static int queue_command(struct xhci_hcd *xhci, u32 field1, u32 field2,
 					"unfailable commands failed.\n");
 		return ret;
 	}
+	if (cmd->completion)
+		cmd->command_trb = xhci->cmd_ring->enqueue;
+	else
+		kfree(cmd);
+
 	queue_trb(xhci, xhci->cmd_ring, false, field1, field2, field3,
 			field4 | xhci->cmd_ring->cycle_state);
 	return 0;
 }
 
 /* Queue a slot enable or disable request on the command ring */
-int xhci_queue_slot_control(struct xhci_hcd *xhci, u32 trb_type, u32 slot_id)
+int xhci_queue_slot_control(struct xhci_hcd *xhci, struct xhci_command *cmd,
+		u32 trb_type, u32 slot_id)
 {
-	return queue_command(xhci, 0, 0, 0,
+	return queue_command(xhci, cmd, 0, 0, 0,
 			TRB_TYPE(trb_type) | SLOT_ID_FOR_TRB(slot_id), false);
 }
 
 /* Queue an address device command TRB */
-int xhci_queue_address_device(struct xhci_hcd *xhci, dma_addr_t in_ctx_ptr,
-			      u32 slot_id, enum xhci_setup_dev setup)
+int xhci_queue_address_device(struct xhci_hcd *xhci, struct xhci_command *cmd,
+		dma_addr_t in_ctx_ptr, u32 slot_id, enum xhci_setup_dev setup)
 {
-	return queue_command(xhci, lower_32_bits(in_ctx_ptr),
+	return queue_command(xhci, cmd, lower_32_bits(in_ctx_ptr),
 			upper_32_bits(in_ctx_ptr), 0,
 			TRB_TYPE(TRB_ADDR_DEV) | SLOT_ID_FOR_TRB(slot_id)
 			| (setup == SETUP_CONTEXT_ONLY ? TRB_BSR : 0), false);
 }
 
-int xhci_queue_vendor_command(struct xhci_hcd *xhci,
+int xhci_queue_vendor_command(struct xhci_hcd *xhci, struct xhci_command *cmd,
 		u32 field1, u32 field2, u32 field3, u32 field4)
 {
-	return queue_command(xhci, field1, field2, field3, field4, false);
+	return queue_command(xhci, cmd, field1, field2, field3, field4, false);
 }
 
 /* Queue a reset device command TRB */
-int xhci_queue_reset_device(struct xhci_hcd *xhci, u32 slot_id)
+int xhci_queue_reset_device(struct xhci_hcd *xhci, struct xhci_command *cmd,
+		u32 slot_id)
 {
-	return queue_command(xhci, 0, 0, 0,
+	return queue_command(xhci, cmd, 0, 0, 0,
 			TRB_TYPE(TRB_RESET_DEV) | SLOT_ID_FOR_TRB(slot_id),
 			false);
 }
 
 /* Queue a configure endpoint command TRB */
-int xhci_queue_configure_endpoint(struct xhci_hcd *xhci, dma_addr_t in_ctx_ptr,
+int xhci_queue_configure_endpoint(struct xhci_hcd *xhci,
+		struct xhci_command *cmd, dma_addr_t in_ctx_ptr,
 		u32 slot_id, bool command_must_succeed)
 {
-	return queue_command(xhci, lower_32_bits(in_ctx_ptr),
+	return queue_command(xhci, cmd, lower_32_bits(in_ctx_ptr),
 			upper_32_bits(in_ctx_ptr), 0,
 			TRB_TYPE(TRB_CONFIG_EP) | SLOT_ID_FOR_TRB(slot_id),
 			command_must_succeed);
 }
 
 /* Queue an evaluate context command TRB */
-int xhci_queue_evaluate_context(struct xhci_hcd *xhci, dma_addr_t in_ctx_ptr,
-		u32 slot_id, bool command_must_succeed)
+int xhci_queue_evaluate_context(struct xhci_hcd *xhci, struct xhci_command *cmd,
+		dma_addr_t in_ctx_ptr, u32 slot_id, bool command_must_succeed)
 {
-	return queue_command(xhci, lower_32_bits(in_ctx_ptr),
+	return queue_command(xhci, cmd, lower_32_bits(in_ctx_ptr),
 			upper_32_bits(in_ctx_ptr), 0,
 			TRB_TYPE(TRB_EVAL_CONTEXT) | SLOT_ID_FOR_TRB(slot_id),
 			command_must_succeed);
@@ -4046,25 +4050,26 @@ int xhci_queue_evaluate_context(struct xhci_hcd *xhci, dma_addr_t in_ctx_ptr,
  * Suspend is set to indicate "Stop Endpoint Command" is being issued to stop
  * activity on an endpoint that is about to be suspended.
  */
-int xhci_queue_stop_endpoint(struct xhci_hcd *xhci, int slot_id,
-		unsigned int ep_index, int suspend)
+int xhci_queue_stop_endpoint(struct xhci_hcd *xhci, struct xhci_command *cmd,
+			     int slot_id, unsigned int ep_index, int suspend)
 {
 	u32 trb_slot_id = SLOT_ID_FOR_TRB(slot_id);
 	u32 trb_ep_index = EP_ID_FOR_TRB(ep_index);
 	u32 type = TRB_TYPE(TRB_STOP_RING);
 	u32 trb_suspend = SUSPEND_PORT_FOR_TRB(suspend);
 
-	return queue_command(xhci, 0, 0, 0,
+	return queue_command(xhci, cmd, 0, 0, 0,
 			trb_slot_id | trb_ep_index | type | trb_suspend, false);
 }
 
 /* Set Transfer Ring Dequeue Pointer command.
  * This should not be used for endpoints that have streams enabled.
  */
-static int queue_set_tr_deq(struct xhci_hcd *xhci, int slot_id,
-		unsigned int ep_index, unsigned int stream_id,
-		struct xhci_segment *deq_seg,
-		union xhci_trb *deq_ptr, u32 cycle_state)
+static int queue_set_tr_deq(struct xhci_hcd *xhci, struct xhci_command *cmd,
+			int slot_id,
+			unsigned int ep_index, unsigned int stream_id,
+			struct xhci_segment *deq_seg,
+			union xhci_trb *deq_ptr, u32 cycle_state)
 {
 	dma_addr_t addr;
 	u32 trb_slot_id = SLOT_ID_FOR_TRB(slot_id);
@@ -4088,18 +4093,18 @@ static int queue_set_tr_deq(struct xhci_hcd *xhci, int slot_id,
 	}
 	ep->queued_deq_seg = deq_seg;
 	ep->queued_deq_ptr = deq_ptr;
-	return queue_command(xhci, lower_32_bits(addr) | cycle_state,
+	return queue_command(xhci, cmd, lower_32_bits(addr) | cycle_state,
 			upper_32_bits(addr), trb_stream_id,
 			trb_slot_id | trb_ep_index | type, false);
 }
 
-int xhci_queue_reset_ep(struct xhci_hcd *xhci, int slot_id,
-		unsigned int ep_index)
+int xhci_queue_reset_ep(struct xhci_hcd *xhci, struct xhci_command *cmd,
+			int slot_id, unsigned int ep_index)
 {
 	u32 trb_slot_id = SLOT_ID_FOR_TRB(slot_id);
 	u32 trb_ep_index = EP_ID_FOR_TRB(ep_index);
 	u32 type = TRB_TYPE(TRB_RESET_EP);
 
-	return queue_command(xhci, 0, 0, 0, trb_slot_id | trb_ep_index | type,
-			false);
+	return queue_command(xhci, cmd, 0, 0, 0,
+			     trb_slot_id | trb_ep_index | type, false);
 }
diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c
index 6fe577d..8bf2aa3 100644
--- a/drivers/usb/host/xhci.c
+++ b/drivers/usb/host/xhci.c
@@ -637,10 +637,14 @@ int xhci_run(struct usb_hcd *hcd)
 	writel(ER_IRQ_ENABLE(temp), &xhci->ir_set->irq_pending);
 	xhci_print_ir_set(xhci, 0);
 
-	if (xhci->quirks & XHCI_NEC_HOST)
-		xhci_queue_vendor_command(xhci, 0, 0, 0,
+	if (xhci->quirks & XHCI_NEC_HOST) {
+		struct xhci_command *command;
+		command = xhci_alloc_command(xhci, false, false, GFP_KERNEL);
+		if (!command)
+			return -ENOMEM;
+		xhci_queue_vendor_command(xhci, command, 0, 0, 0,
 				TRB_TYPE(TRB_NEC_GET_FW));
-
+	}
 	xhci_dbg_trace(xhci, trace_xhci_dbg_init,
 			"Finished xhci_run for USB2 roothub");
 	return 0;
@@ -1183,10 +1187,10 @@ static int xhci_configure_endpoint(struct xhci_hcd *xhci,
 static int xhci_check_maxpacket(struct xhci_hcd *xhci, unsigned int slot_id,
 		unsigned int ep_index, struct urb *urb)
 {
-	struct xhci_container_ctx *in_ctx;
 	struct xhci_container_ctx *out_ctx;
 	struct xhci_input_control_ctx *ctrl_ctx;
 	struct xhci_ep_ctx *ep_ctx;
+	struct xhci_command *command;
 	int max_packet_size;
 	int hw_max_packet_size;
 	int ret = 0;
@@ -1211,18 +1215,24 @@ static int xhci_check_maxpacket(struct xhci_hcd *xhci, unsigned int slot_id,
 		/* FIXME: This won't work if a non-default control endpoint
 		 * changes max packet sizes.
 		 */
-		in_ctx = xhci->devs[slot_id]->in_ctx;
-		ctrl_ctx = xhci_get_input_control_ctx(xhci, in_ctx);
+
+		command = xhci_alloc_command(xhci, false, true, GFP_KERNEL);
+		if (!command)
+			return -ENOMEM;
+
+		command->in_ctx = xhci->devs[slot_id]->in_ctx;
+		ctrl_ctx = xhci_get_input_control_ctx(xhci, command->in_ctx);
 		if (!ctrl_ctx) {
 			xhci_warn(xhci, "%s: Could not get input context, bad type.\n",
 					__func__);
-			return -ENOMEM;
+			ret = -ENOMEM;
+			goto command_cleanup;
 		}
 		/* Set up the modified control endpoint 0 */
 		xhci_endpoint_copy(xhci, xhci->devs[slot_id]->in_ctx,
 				xhci->devs[slot_id]->out_ctx, ep_index);
 
-		ep_ctx = xhci_get_ep_ctx(xhci, in_ctx, ep_index);
+		ep_ctx = xhci_get_ep_ctx(xhci, command->in_ctx, ep_index);
 		ep_ctx->ep_info2 &= cpu_to_le32(~MAX_PACKET_MASK);
 		ep_ctx->ep_info2 |= cpu_to_le32(MAX_PACKET(max_packet_size));
 
@@ -1230,17 +1240,20 @@ static int xhci_check_maxpacket(struct xhci_hcd *xhci, unsigned int slot_id,
 		ctrl_ctx->drop_flags = 0;
 
 		xhci_dbg(xhci, "Slot %d input context\n", slot_id);
-		xhci_dbg_ctx(xhci, in_ctx, ep_index);
+		xhci_dbg_ctx(xhci, command->in_ctx, ep_index);
 		xhci_dbg(xhci, "Slot %d output context\n", slot_id);
 		xhci_dbg_ctx(xhci, out_ctx, ep_index);
 
-		ret = xhci_configure_endpoint(xhci, urb->dev, NULL,
+		ret = xhci_configure_endpoint(xhci, urb->dev, command,
 				true, false);
 
 		/* Clean up the input context for later use by bandwidth
 		 * functions.
 		 */
 		ctrl_ctx->add_flags = cpu_to_le32(SLOT_FLAG);
+command_cleanup:
+		kfree(command->completion);
+		kfree(command);
 	}
 	return ret;
 }
@@ -1461,6 +1474,7 @@ int xhci_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status)
 	unsigned int ep_index;
 	struct xhci_ring *ep_ring;
 	struct xhci_virt_ep *ep;
+	struct xhci_command *command;
 
 	xhci = hcd_to_xhci(hcd);
 	spin_lock_irqsave(&xhci->lock, flags);
@@ -1530,12 +1544,14 @@ int xhci_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status)
 	 * the first cancellation to be handled.
 	 */
 	if (!(ep->ep_state & EP_HALT_PENDING)) {
+		command = xhci_alloc_command(xhci, false, false, GFP_ATOMIC);
 		ep->ep_state |= EP_HALT_PENDING;
 		ep->stop_cmds_pending++;
 		ep->stop_cmd_timer.expires = jiffies +
 			XHCI_STOP_EP_CMD_TIMEOUT * HZ;
 		add_timer(&ep->stop_cmd_timer);
-		xhci_queue_stop_endpoint(xhci, urb->dev->slot_id, ep_index, 0);
+		xhci_queue_stop_endpoint(xhci, command, urb->dev->slot_id,
+					 ep_index, 0);
 		xhci_ring_cmd_db(xhci);
 	}
 done:
@@ -2572,21 +2588,16 @@ static int xhci_configure_endpoint(struct xhci_hcd *xhci,
 	int ret;
 	int timeleft;
 	unsigned long flags;
-	struct xhci_container_ctx *in_ctx;
 	struct xhci_input_control_ctx *ctrl_ctx;
-	struct completion *cmd_completion;
-	u32 *cmd_status;
 	struct xhci_virt_device *virt_dev;
-	union xhci_trb *cmd_trb;
+
+	if (!command)
+		return -EINVAL;
 
 	spin_lock_irqsave(&xhci->lock, flags);
 	virt_dev = xhci->devs[udev->slot_id];
 
-	if (command)
-		in_ctx = command->in_ctx;
-	else
-		in_ctx = virt_dev->in_ctx;
-	ctrl_ctx = xhci_get_input_control_ctx(xhci, in_ctx);
+	ctrl_ctx = xhci_get_input_control_ctx(xhci, command->in_ctx);
 	if (!ctrl_ctx) {
 		spin_unlock_irqrestore(&xhci->lock, flags);
 		xhci_warn(xhci, "%s: Could not get input context, bad type.\n",
@@ -2603,7 +2614,7 @@ static int xhci_configure_endpoint(struct xhci_hcd *xhci,
 		return -ENOMEM;
 	}
 	if ((xhci->quirks & XHCI_SW_BW_CHECKING) &&
-			xhci_reserve_bandwidth(xhci, virt_dev, in_ctx)) {
+	    xhci_reserve_bandwidth(xhci, virt_dev, command->in_ctx)) {
 		if ((xhci->quirks & XHCI_EP_LIMIT_QUIRK))
 			xhci_free_host_resources(xhci, ctrl_ctx);
 		spin_unlock_irqrestore(&xhci->lock, flags);
@@ -2611,27 +2622,18 @@ static int xhci_configure_endpoint(struct xhci_hcd *xhci,
 		return -ENOMEM;
 	}
 
-	if (command) {
-		cmd_completion = command->completion;
-		cmd_status = &command->status;
-		command->command_trb = xhci_find_next_enqueue(xhci->cmd_ring);
-		list_add_tail(&command->cmd_list, &virt_dev->cmd_list);
-	} else {
-		cmd_completion = &virt_dev->cmd_completion;
-		cmd_status = &virt_dev->cmd_status;
-	}
-	init_completion(cmd_completion);
+	list_add_tail(&command->cmd_list, &virt_dev->cmd_list);
 
-	cmd_trb = xhci_find_next_enqueue(xhci->cmd_ring);
 	if (!ctx_change)
-		ret = xhci_queue_configure_endpoint(xhci, in_ctx->dma,
+		ret = xhci_queue_configure_endpoint(xhci, command,
+				command->in_ctx->dma,
 				udev->slot_id, must_succeed);
 	else
-		ret = xhci_queue_evaluate_context(xhci, in_ctx->dma,
+		ret = xhci_queue_evaluate_context(xhci, command,
+				command->in_ctx->dma,
 				udev->slot_id, must_succeed);
 	if (ret < 0) {
-		if (command)
-			list_del(&command->cmd_list);
+		list_del(&command->cmd_list);
 		if ((xhci->quirks & XHCI_EP_LIMIT_QUIRK))
 			xhci_free_host_resources(xhci, ctrl_ctx);
 		spin_unlock_irqrestore(&xhci->lock, flags);
@@ -2644,7 +2646,7 @@ static int xhci_configure_endpoint(struct xhci_hcd *xhci,
 
 	/* Wait for the configure endpoint command to complete */
 	timeleft = wait_for_completion_interruptible_timeout(
-			cmd_completion,
+			command->completion,
 			XHCI_CMD_DEFAULT_TIMEOUT);
 	if (timeleft <= 0) {
 		xhci_warn(xhci, "%s while waiting for %s command\n",
@@ -2653,16 +2655,18 @@ static int xhci_configure_endpoint(struct xhci_hcd *xhci,
 					"configure endpoint" :
 					"evaluate context");
 		/* cancel the configure endpoint command */
-		ret = xhci_cancel_cmd(xhci, command, cmd_trb);
+		ret = xhci_cancel_cmd(xhci, command, command->command_trb);
 		if (ret < 0)
 			return ret;
 		return -ETIME;
 	}
 
 	if (!ctx_change)
-		ret = xhci_configure_endpoint_result(xhci, udev, cmd_status);
+		ret = xhci_configure_endpoint_result(xhci, udev,
+						     &command->status);
 	else
-		ret = xhci_evaluate_context_result(xhci, udev, cmd_status);
+		ret = xhci_evaluate_context_result(xhci, udev,
+						   &command->status);
 
 	if ((xhci->quirks & XHCI_EP_LIMIT_QUIRK)) {
 		spin_lock_irqsave(&xhci->lock, flags);
@@ -2696,6 +2700,7 @@ int xhci_check_bandwidth(struct usb_hcd *hcd, struct usb_device *udev)
 	struct xhci_virt_device	*virt_dev;
 	struct xhci_input_control_ctx *ctrl_ctx;
 	struct xhci_slot_ctx *slot_ctx;
+	struct xhci_command *command;
 
 	ret = xhci_check_args(hcd, udev, NULL, 0, true, __func__);
 	if (ret <= 0)
@@ -2707,12 +2712,19 @@ int xhci_check_bandwidth(struct usb_hcd *hcd, struct usb_device *udev)
 	xhci_dbg(xhci, "%s called for udev %p\n", __func__, udev);
 	virt_dev = xhci->devs[udev->slot_id];
 
+	command = xhci_alloc_command(xhci, false, true, GFP_KERNEL);
+	if (!command)
+		return -ENOMEM;
+
+	command->in_ctx = virt_dev->in_ctx;
+
 	/* See section 4.6.6 - A0 = 1; A1 = D0 = D1 = 0 */
-	ctrl_ctx = xhci_get_input_control_ctx(xhci, virt_dev->in_ctx);
+	ctrl_ctx = xhci_get_input_control_ctx(xhci, command->in_ctx);
 	if (!ctrl_ctx) {
 		xhci_warn(xhci, "%s: Could not get input context, bad type.\n",
 				__func__);
-		return -ENOMEM;
+		ret = -ENOMEM;
+		goto command_cleanup;
 	}
 	ctrl_ctx->add_flags |= cpu_to_le32(SLOT_FLAG);
 	ctrl_ctx->add_flags &= cpu_to_le32(~EP0_FLAG);
@@ -2720,20 +2732,20 @@ int xhci_check_bandwidth(struct usb_hcd *hcd, struct usb_device *udev)
 
 	/* Don't issue the command if there's no endpoints to update. */
 	if (ctrl_ctx->add_flags == cpu_to_le32(SLOT_FLAG) &&
-			ctrl_ctx->drop_flags == 0)
-		return 0;
-
+	    ctrl_ctx->drop_flags == 0) {
+		ret = 0;
+		goto command_cleanup;
+	}
 	xhci_dbg(xhci, "New Input Control Context:\n");
 	slot_ctx = xhci_get_slot_ctx(xhci, virt_dev->in_ctx);
 	xhci_dbg_ctx(xhci, virt_dev->in_ctx,
 		     LAST_CTX_TO_EP_NUM(le32_to_cpu(slot_ctx->dev_info)));
 
-	ret = xhci_configure_endpoint(xhci, udev, NULL,
+	ret = xhci_configure_endpoint(xhci, udev, command,
 			false, false);
-	if (ret) {
+	if (ret)
 		/* Callee should call reset_bandwidth() */
-		return ret;
-	}
+		goto command_cleanup;
 
 	xhci_dbg(xhci, "Output context after successful config ep cmd:\n");
 	xhci_dbg_ctx(xhci, virt_dev->out_ctx,
@@ -2762,6 +2774,9 @@ int xhci_check_bandwidth(struct usb_hcd *hcd, struct usb_device *udev)
 		virt_dev->eps[i].ring = virt_dev->eps[i].new_ring;
 		virt_dev->eps[i].new_ring = NULL;
 	}
+command_cleanup:
+	kfree(command->completion);
+	kfree(command);
 
 	return ret;
 }
@@ -2863,9 +2878,14 @@ void xhci_cleanup_stalled_ring(struct xhci_hcd *xhci,
 	 * issue a configure endpoint command later.
 	 */
 	if (!(xhci->quirks & XHCI_RESET_EP_QUIRK)) {
+		struct xhci_command *command;
+		/* Can't sleep if we're called from cleanup_halted_endpoint() */
+		command = xhci_alloc_command(xhci, false, false, GFP_ATOMIC);
+		if (!command)
+			return;
 		xhci_dbg_trace(xhci, trace_xhci_dbg_reset_ep,
 				"Queueing new dequeue state");
-		xhci_queue_new_dequeue_state(xhci, udev->slot_id,
+		xhci_queue_new_dequeue_state(xhci, command, udev->slot_id,
 				ep_index, ep->stopped_stream, &deq_state);
 	} else {
 		/* Better hope no one uses the input context between now and the
@@ -2896,6 +2916,7 @@ void xhci_endpoint_reset(struct usb_hcd *hcd,
 	unsigned long flags;
 	int ret;
 	struct xhci_virt_ep *virt_ep;
+	struct xhci_command *command;
 
 	xhci = hcd_to_xhci(hcd);
 	udev = (struct usb_device *) ep->hcpriv;
@@ -2918,10 +2939,14 @@ void xhci_endpoint_reset(struct usb_hcd *hcd,
 		return;
 	}
 
+	command = xhci_alloc_command(xhci, false, false, GFP_ATOMIC);
+	if (!command)
+		return;
+
 	xhci_dbg_trace(xhci, trace_xhci_dbg_reset_ep,
 			"Queueing reset endpoint command");
 	spin_lock_irqsave(&xhci->lock, flags);
-	ret = xhci_queue_reset_ep(xhci, udev->slot_id, ep_index);
+	ret = xhci_queue_reset_ep(xhci, command, udev->slot_id, ep_index);
 	/*
 	 * Can't change the ring dequeue pointer until it's transitioned to the
 	 * stopped state, which is only upon a successful reset endpoint
@@ -3447,10 +3472,9 @@ int xhci_discover_or_reset_device(struct usb_hcd *hcd, struct usb_device *udev)
 
 	/* Attempt to submit the Reset Device command to the command ring */
 	spin_lock_irqsave(&xhci->lock, flags);
-	reset_device_cmd->command_trb = xhci_find_next_enqueue(xhci->cmd_ring);
 
 	list_add_tail(&reset_device_cmd->cmd_list, &virt_dev->cmd_list);
-	ret = xhci_queue_reset_device(xhci, slot_id);
+	ret = xhci_queue_reset_device(xhci, reset_device_cmd, slot_id);
 	if (ret) {
 		xhci_dbg(xhci, "FIXME: allocate a command ring segment\n");
 		list_del(&reset_device_cmd->cmd_list);
@@ -3561,6 +3585,11 @@ void xhci_free_dev(struct usb_hcd *hcd, struct usb_device *udev)
 	unsigned long flags;
 	u32 state;
 	int i, ret;
+	struct xhci_command *command;
+
+	command = xhci_alloc_command(xhci, false, false, GFP_KERNEL);
+	if (!command)
+		return;
 
 #ifndef CONFIG_USB_DEFAULT_PERSIST
 	/*
@@ -3576,8 +3605,10 @@ void xhci_free_dev(struct usb_hcd *hcd, struct usb_device *udev)
 	/* If the host is halted due to driver unload, we still need to free the
 	 * device.
 	 */
-	if (ret <= 0 && ret != -ENODEV)
+	if (ret <= 0 && ret != -ENODEV) {
+		kfree(command);
 		return;
+	}
 
 	virt_dev = xhci->devs[udev->slot_id];
 
@@ -3594,16 +3625,19 @@ void xhci_free_dev(struct usb_hcd *hcd, struct usb_device *udev)
 			(xhci->xhc_state & XHCI_STATE_HALTED)) {
 		xhci_free_virt_device(xhci, udev->slot_id);
 		spin_unlock_irqrestore(&xhci->lock, flags);
+		kfree(command);
 		return;
 	}
 
-	if (xhci_queue_slot_control(xhci, TRB_DISABLE_SLOT, udev->slot_id)) {
+	if (xhci_queue_slot_control(xhci, command, TRB_DISABLE_SLOT,
+				    udev->slot_id)) {
 		spin_unlock_irqrestore(&xhci->lock, flags);
 		xhci_dbg(xhci, "FIXME: allocate a command ring segment\n");
 		return;
 	}
 	xhci_ring_cmd_db(xhci);
 	spin_unlock_irqrestore(&xhci->lock, flags);
+
 	/*
 	 * Event command completion handler will free any data structures
 	 * associated with the slot.  XXX Can free sleep?
@@ -3643,31 +3677,40 @@ int xhci_alloc_dev(struct usb_hcd *hcd, struct usb_device *udev)
 	unsigned long flags;
 	int timeleft;
 	int ret;
-	union xhci_trb *cmd_trb;
+	struct xhci_command *command;
+
+	command = xhci_alloc_command(xhci, false, false, GFP_KERNEL);
+	if (!command)
+		return 0;
 
 	spin_lock_irqsave(&xhci->lock, flags);
-	cmd_trb = xhci_find_next_enqueue(xhci->cmd_ring);
-	ret = xhci_queue_slot_control(xhci, TRB_ENABLE_SLOT, 0);
+	command->completion = &xhci->addr_dev;
+	ret = xhci_queue_slot_control(xhci, command, TRB_ENABLE_SLOT, 0);
 	if (ret) {
 		spin_unlock_irqrestore(&xhci->lock, flags);
 		xhci_dbg(xhci, "FIXME: allocate a command ring segment\n");
+		kfree(command);
 		return 0;
 	}
 	xhci_ring_cmd_db(xhci);
 	spin_unlock_irqrestore(&xhci->lock, flags);
 
 	/* XXX: how much time for xHC slot assignment? */
-	timeleft = wait_for_completion_interruptible_timeout(&xhci->addr_dev,
+	timeleft = wait_for_completion_interruptible_timeout(
+			command->completion,
 			XHCI_CMD_DEFAULT_TIMEOUT);
 	if (timeleft <= 0) {
 		xhci_warn(xhci, "%s while waiting for a slot\n",
 				timeleft == 0 ? "Timeout" : "Signal");
 		/* cancel the enable slot request */
-		return xhci_cancel_cmd(xhci, NULL, cmd_trb);
+		ret = xhci_cancel_cmd(xhci, NULL, command->command_trb);
+		kfree(command);
+		return ret;
 	}
 
 	if (!xhci->slot_id) {
 		xhci_err(xhci, "Error while assigning device slot ID\n");
+		kfree(command);
 		return 0;
 	}
 
@@ -3702,6 +3745,8 @@ int xhci_alloc_dev(struct usb_hcd *hcd, struct usb_device *udev)
 		pm_runtime_get_noresume(hcd->self.controller);
 #endif
 
+
+	kfree(command);
 	/* Is this a LS or FS device under a HS hub? */
 	/* Hub or peripherial? */
 	return 1;
@@ -3709,7 +3754,10 @@ int xhci_alloc_dev(struct usb_hcd *hcd, struct usb_device *udev)
 disable_slot:
 	/* Disable slot, if we can do it without mem alloc */
 	spin_lock_irqsave(&xhci->lock, flags);
-	if (!xhci_queue_slot_control(xhci, TRB_DISABLE_SLOT, udev->slot_id))
+	command->completion = NULL;
+	command->status = 0;
+	if (!xhci_queue_slot_control(xhci, command, TRB_DISABLE_SLOT,
+				     udev->slot_id))
 		xhci_ring_cmd_db(xhci);
 	spin_unlock_irqrestore(&xhci->lock, flags);
 	return 0;
@@ -3733,7 +3781,7 @@ static int xhci_setup_device(struct usb_hcd *hcd, struct usb_device *udev,
 	struct xhci_slot_ctx *slot_ctx;
 	struct xhci_input_control_ctx *ctrl_ctx;
 	u64 temp_64;
-	union xhci_trb *cmd_trb;
+	struct xhci_command *command;
 
 	if (!udev->slot_id) {
 		xhci_dbg_trace(xhci, trace_xhci_dbg_address,
@@ -3754,11 +3802,19 @@ static int xhci_setup_device(struct usb_hcd *hcd, struct usb_device *udev,
 		return -EINVAL;
 	}
 
+	command = xhci_alloc_command(xhci, false, false, GFP_KERNEL);
+	if (!command)
+		return -ENOMEM;
+
+	command->in_ctx = virt_dev->in_ctx;
+	command->completion = &xhci->addr_dev;
+
 	slot_ctx = xhci_get_slot_ctx(xhci, virt_dev->in_ctx);
 	ctrl_ctx = xhci_get_input_control_ctx(xhci, virt_dev->in_ctx);
 	if (!ctrl_ctx) {
 		xhci_warn(xhci, "%s: Could not get input context, bad type.\n",
 				__func__);
+		kfree(command);
 		return -EINVAL;
 	}
 	/*
@@ -3780,21 +3836,21 @@ static int xhci_setup_device(struct usb_hcd *hcd, struct usb_device *udev,
 				le32_to_cpu(slot_ctx->dev_info) >> 27);
 
 	spin_lock_irqsave(&xhci->lock, flags);
-	cmd_trb = xhci_find_next_enqueue(xhci->cmd_ring);
-	ret = xhci_queue_address_device(xhci, virt_dev->in_ctx->dma,
+	ret = xhci_queue_address_device(xhci, command, virt_dev->in_ctx->dma,
 					udev->slot_id, setup);
 	if (ret) {
 		spin_unlock_irqrestore(&xhci->lock, flags);
 		xhci_dbg_trace(xhci, trace_xhci_dbg_address,
 				"FIXME: allocate a command ring segment");
+		kfree(command);
 		return ret;
 	}
 	xhci_ring_cmd_db(xhci);
 	spin_unlock_irqrestore(&xhci->lock, flags);
 
 	/* ctrl tx can take up to 5 sec; XXX: need more time for xHC? */
-	timeleft = wait_for_completion_interruptible_timeout(&xhci->addr_dev,
-			XHCI_CMD_DEFAULT_TIMEOUT);
+	timeleft = wait_for_completion_interruptible_timeout(
+			command->completion, XHCI_CMD_DEFAULT_TIMEOUT);
 	/* FIXME: From section 4.3.4: "Software shall be responsible for timing
 	 * the SetAddress() "recovery interval" required by USB and aborting the
 	 * command on a timeout.
@@ -3803,7 +3859,8 @@ static int xhci_setup_device(struct usb_hcd *hcd, struct usb_device *udev,
 		xhci_warn(xhci, "%s while waiting for setup %s command\n",
 			  timeleft == 0 ? "Timeout" : "Signal", act);
 		/* cancel the address device command */
-		ret = xhci_cancel_cmd(xhci, NULL, cmd_trb);
+		ret = xhci_cancel_cmd(xhci, NULL, command->command_trb);
+		kfree(command);
 		if (ret < 0)
 			return ret;
 		return -ETIME;
@@ -3840,6 +3897,7 @@ static int xhci_setup_device(struct usb_hcd *hcd, struct usb_device *udev,
 		break;
 	}
 	if (ret) {
+		kfree(command);
 		return ret;
 	}
 	temp_64 = xhci_read_64(xhci, &xhci->op_regs->dcbaa_ptr);
@@ -3874,7 +3932,7 @@ static int xhci_setup_device(struct usb_hcd *hcd, struct usb_device *udev,
 	xhci_dbg_trace(xhci, trace_xhci_dbg_address,
 		       "Internal device address = %d",
 		       le32_to_cpu(slot_ctx->dev_state) & DEV_ADDR_MASK);
-
+	kfree(command);
 	return 0;
 }
 
diff --git a/drivers/usb/host/xhci.h b/drivers/usb/host/xhci.h
index 58ed9d0..083ff11 100644
--- a/drivers/usb/host/xhci.h
+++ b/drivers/usb/host/xhci.h
@@ -1807,13 +1807,14 @@ struct xhci_segment *trb_in_td(struct xhci_segment *start_seg,
 		dma_addr_t suspect_dma);
 int xhci_is_vendor_info_code(struct xhci_hcd *xhci, unsigned int trb_comp_code);
 void xhci_ring_cmd_db(struct xhci_hcd *xhci);
-int xhci_queue_slot_control(struct xhci_hcd *xhci, u32 trb_type, u32 slot_id);
-int xhci_queue_address_device(struct xhci_hcd *xhci, dma_addr_t in_ctx_ptr,
-		u32 slot_id, enum xhci_setup_dev);
-int xhci_queue_vendor_command(struct xhci_hcd *xhci,
+int xhci_queue_slot_control(struct xhci_hcd *xhci, struct xhci_command *cmd,
+		u32 trb_type, u32 slot_id);
+int xhci_queue_address_device(struct xhci_hcd *xhci, struct xhci_command *cmd,
+		dma_addr_t in_ctx_ptr, u32 slot_id, enum xhci_setup_dev);
+int xhci_queue_vendor_command(struct xhci_hcd *xhci, struct xhci_command *cmd,
 		u32 field1, u32 field2, u32 field3, u32 field4);
-int xhci_queue_stop_endpoint(struct xhci_hcd *xhci, int slot_id,
-		unsigned int ep_index, int suspend);
+int xhci_queue_stop_endpoint(struct xhci_hcd *xhci, struct xhci_command *cmd,
+		int slot_id, unsigned int ep_index, int suspend);
 int xhci_queue_ctrl_tx(struct xhci_hcd *xhci, gfp_t mem_flags, struct urb *urb,
 		int slot_id, unsigned int ep_index);
 int xhci_queue_bulk_tx(struct xhci_hcd *xhci, gfp_t mem_flags, struct urb *urb,
@@ -1822,18 +1823,21 @@ int xhci_queue_intr_tx(struct xhci_hcd *xhci, gfp_t mem_flags, struct urb *urb,
 		int slot_id, unsigned int ep_index);
 int xhci_queue_isoc_tx_prepare(struct xhci_hcd *xhci, gfp_t mem_flags,
 		struct urb *urb, int slot_id, unsigned int ep_index);
-int xhci_queue_configure_endpoint(struct xhci_hcd *xhci, dma_addr_t in_ctx_ptr,
-		u32 slot_id, bool command_must_succeed);
-int xhci_queue_evaluate_context(struct xhci_hcd *xhci, dma_addr_t in_ctx_ptr,
-		u32 slot_id, bool command_must_succeed);
-int xhci_queue_reset_ep(struct xhci_hcd *xhci, int slot_id,
-		unsigned int ep_index);
-int xhci_queue_reset_device(struct xhci_hcd *xhci, u32 slot_id);
+int xhci_queue_configure_endpoint(struct xhci_hcd *xhci,
+		struct xhci_command *cmd, dma_addr_t in_ctx_ptr, u32 slot_id,
+		bool command_must_succeed);
+int xhci_queue_evaluate_context(struct xhci_hcd *xhci, struct xhci_command *cmd,
+		dma_addr_t in_ctx_ptr, u32 slot_id, bool command_must_succeed);
+int xhci_queue_reset_ep(struct xhci_hcd *xhci, struct xhci_command *cmd,
+		int slot_id, unsigned int ep_index);
+int xhci_queue_reset_device(struct xhci_hcd *xhci, struct xhci_command *cmd,
+		u32 slot_id);
 void xhci_find_new_dequeue_state(struct xhci_hcd *xhci,
 		unsigned int slot_id, unsigned int ep_index,
 		unsigned int stream_id, struct xhci_td *cur_td,
 		struct xhci_dequeue_state *state);
 void xhci_queue_new_dequeue_state(struct xhci_hcd *xhci,
+		struct xhci_command *cmd,
 		unsigned int slot_id, unsigned int ep_index,
 		unsigned int stream_id,
 		struct xhci_dequeue_state *deq_state);
@@ -1847,7 +1851,6 @@ int xhci_cancel_cmd(struct xhci_hcd *xhci, struct xhci_command *command,
 		union xhci_trb *cmd_trb);
 void xhci_ring_ep_doorbell(struct xhci_hcd *xhci, unsigned int slot_id,
 		unsigned int ep_index, unsigned int stream_id);
-union xhci_trb *xhci_find_next_enqueue(struct xhci_ring *ring);
 
 /* xHCI roothub code */
 void xhci_set_link_state(struct xhci_hcd *xhci, __le32 __iomem **port_array,
-- 
1.8.1.2


^ permalink raw reply related	[flat|nested] 7+ messages in thread

* [RFCv3 2/4] xhci: Add a global command queue
  2014-02-26 19:38 [RFCv3 0/4] xhci: re-work command queue management Mathias Nyman
  2014-02-26 19:38 ` [RFCv3 1/4] xhci: Use command structures when queuing commands on the command ring Mathias Nyman
@ 2014-02-26 19:38 ` Mathias Nyman
  2014-02-26 19:38 ` [RFCv3 3/4] xhci: Use completion and status in " Mathias Nyman
  2014-02-26 19:38 ` [RFCv3 4/4] xhci: rework command timeout and cancellation, Mathias Nyman
  3 siblings, 0 replies; 7+ messages in thread
From: Mathias Nyman @ 2014-02-26 19:38 UTC (permalink / raw)
  To: linux-usb; +Cc: sarah.a.sharp, dan.j.williams, linux-kernel, Mathias Nyman

Create a list to store command structures, add a structure to it every time
a command is submitted, and remove it from the list once we get a
command completion event matching the command.

Callers that wait for completion will free their command structures themselves.
The other command structures are freed in the command completion event handler.

Signed-off-by: Mathias Nyman <mathias.nyman@linux.intel.com>
---
 drivers/usb/host/xhci-mem.c  |  8 ++++++++
 drivers/usb/host/xhci-ring.c | 21 +++++++++++++++++----
 drivers/usb/host/xhci.c      |  2 --
 drivers/usb/host/xhci.h      |  1 +
 4 files changed, 26 insertions(+), 6 deletions(-)

diff --git a/drivers/usb/host/xhci-mem.c b/drivers/usb/host/xhci-mem.c
index bce4391..9df2aa0 100644
--- a/drivers/usb/host/xhci-mem.c
+++ b/drivers/usb/host/xhci-mem.c
@@ -1694,6 +1694,7 @@ void xhci_mem_cleanup(struct xhci_hcd *xhci)
 {
 	struct device	*dev = xhci_to_hcd(xhci)->self.controller;
 	struct xhci_cd  *cur_cd, *next_cd;
+	struct xhci_command *cur_cmd, *next_cmd;
 	int size;
 	int i, j, num_ports;
 
@@ -1722,6 +1723,12 @@ void xhci_mem_cleanup(struct xhci_hcd *xhci)
 		kfree(cur_cd);
 	}
 
+	list_for_each_entry_safe(cur_cmd, next_cmd,
+			&xhci->cmd_list, cmd_list) {
+		list_del(&cur_cmd->cmd_list);
+		kfree(cur_cmd);
+	}
+
 	for (i = 1; i < MAX_HC_SLOTS; ++i)
 		xhci_free_virt_device(xhci, i);
 
@@ -2223,6 +2230,7 @@ int xhci_mem_init(struct xhci_hcd *xhci, gfp_t flags)
 	int i;
 
 	INIT_LIST_HEAD(&xhci->cancel_cmd_list);
+	INIT_LIST_HEAD(&xhci->cmd_list);
 
 	page_size = readl(&xhci->op_regs->page_size);
 	xhci_dbg_trace(xhci, trace_xhci_dbg_init,
diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c
index fa34c9b..39d3ff7 100644
--- a/drivers/usb/host/xhci-ring.c
+++ b/drivers/usb/host/xhci-ring.c
@@ -1496,6 +1496,7 @@ static void handle_cmd_completion(struct xhci_hcd *xhci,
 	dma_addr_t cmd_dequeue_dma;
 	u32 cmd_comp_code;
 	union xhci_trb *cmd_trb;
+	struct xhci_command *cmd;
 	u32 cmd_type;
 
 	cmd_dma = le64_to_cpu(event->cmd_trb);
@@ -1513,6 +1514,13 @@ static void handle_cmd_completion(struct xhci_hcd *xhci,
 		return;
 	}
 
+	cmd = list_entry(xhci->cmd_list.next, struct xhci_command, cmd_list);
+
+	if (cmd->command_trb != xhci->cmd_ring->dequeue) {
+		xhci_err(xhci,
+			 "Command completion event does not match command\n");
+		return;
+	}
 	trace_xhci_cmd_completion(cmd_trb, (struct xhci_generic_trb *) event);
 
 	cmd_comp_code = GET_COMP_CODE(le32_to_cpu(event->status));
@@ -1582,6 +1590,12 @@ static void handle_cmd_completion(struct xhci_hcd *xhci,
 		xhci->error_bitmask |= 1 << 6;
 		break;
 	}
+
+	list_del(&cmd->cmd_list);
+
+	if (!cmd->completion)
+		kfree(cmd);
+
 	inc_deq(xhci, xhci->cmd_ring);
 }
 
@@ -3982,10 +3996,9 @@ static int queue_command(struct xhci_hcd *xhci, struct xhci_command *cmd,
 					"unfailable commands failed.\n");
 		return ret;
 	}
-	if (cmd->completion)
-		cmd->command_trb = xhci->cmd_ring->enqueue;
-	else
-		kfree(cmd);
+
+	cmd->command_trb = xhci->cmd_ring->enqueue;
+	list_add_tail(&cmd->cmd_list, &xhci->cmd_list);
 
 	queue_trb(xhci, xhci->cmd_ring, false, field1, field2, field3,
 			field4 | xhci->cmd_ring->cycle_state);
diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c
index 8bf2aa3..97de328 100644
--- a/drivers/usb/host/xhci.c
+++ b/drivers/usb/host/xhci.c
@@ -3704,7 +3704,6 @@ int xhci_alloc_dev(struct usb_hcd *hcd, struct usb_device *udev)
 				timeleft == 0 ? "Timeout" : "Signal");
 		/* cancel the enable slot request */
 		ret = xhci_cancel_cmd(xhci, NULL, command->command_trb);
-		kfree(command);
 		return ret;
 	}
 
@@ -3860,7 +3859,6 @@ static int xhci_setup_device(struct usb_hcd *hcd, struct usb_device *udev,
 			  timeleft == 0 ? "Timeout" : "Signal", act);
 		/* cancel the address device command */
 		ret = xhci_cancel_cmd(xhci, NULL, command->command_trb);
-		kfree(command);
 		if (ret < 0)
 			return ret;
 		return -ETIME;
diff --git a/drivers/usb/host/xhci.h b/drivers/usb/host/xhci.h
index 083ff11..7052b8c 100644
--- a/drivers/usb/host/xhci.h
+++ b/drivers/usb/host/xhci.h
@@ -1483,6 +1483,7 @@ struct xhci_hcd {
 #define CMD_RING_STATE_ABORTED         (1 << 1)
 #define CMD_RING_STATE_STOPPED         (1 << 2)
 	struct list_head        cancel_cmd_list;
+	struct list_head        cmd_list;
 	unsigned int		cmd_ring_reserved_trbs;
 	struct xhci_ring	*event_ring;
 	struct xhci_erst	erst;
-- 
1.8.1.2


^ permalink raw reply related	[flat|nested] 7+ messages in thread

* [RFCv3 3/4] xhci: Use completion and status in global command queue
  2014-02-26 19:38 [RFCv3 0/4] xhci: re-work command queue management Mathias Nyman
  2014-02-26 19:38 ` [RFCv3 1/4] xhci: Use command structures when queuing commands on the command ring Mathias Nyman
  2014-02-26 19:38 ` [RFCv3 2/4] xhci: Add a global command queue Mathias Nyman
@ 2014-02-26 19:38 ` Mathias Nyman
  2014-02-26 19:38 ` [RFCv3 4/4] xhci: rework command timeout and cancellation, Mathias Nyman
  3 siblings, 0 replies; 7+ messages in thread
From: Mathias Nyman @ 2014-02-26 19:38 UTC (permalink / raw)
  To: linux-usb; +Cc: sarah.a.sharp, dan.j.williams, linux-kernel, Mathias Nyman

Remove the per-device command list and handle_cmd_in_cmd_wait_list()
and use the completion and status variables found in the
command structure in the global command list.

Signed-off-by: Mathias Nyman <mathias.nyman@linux.intel.com>
---
 drivers/usb/host/xhci-hub.c  | 11 -------
 drivers/usb/host/xhci-mem.c  |  1 -
 drivers/usb/host/xhci-ring.c | 78 +++++++-------------------------------------
 drivers/usb/host/xhci.c      | 16 ++-------
 drivers/usb/host/xhci.h      |  3 --
 5 files changed, 14 insertions(+), 95 deletions(-)

diff --git a/drivers/usb/host/xhci-hub.c b/drivers/usb/host/xhci-hub.c
index fb0f936..0a57d95 100644
--- a/drivers/usb/host/xhci-hub.c
+++ b/drivers/usb/host/xhci-hub.c
@@ -299,7 +299,6 @@ static int xhci_stop_device(struct xhci_hcd *xhci, int slot_id, int suspend)
 						 suspend);
 		}
 	}
-	list_add_tail(&cmd->cmd_list, &virt_dev->cmd_list);
 	xhci_queue_stop_endpoint(xhci, cmd, slot_id, 0, suspend);
 	xhci_ring_cmd_db(xhci);
 	spin_unlock_irqrestore(&xhci->lock, flags);
@@ -311,18 +310,8 @@ static int xhci_stop_device(struct xhci_hcd *xhci, int slot_id, int suspend)
 	if (timeleft <= 0) {
 		xhci_warn(xhci, "%s while waiting for stop endpoint command\n",
 				timeleft == 0 ? "Timeout" : "Signal");
-		spin_lock_irqsave(&xhci->lock, flags);
-		/* The timeout might have raced with the event ring handler, so
-		 * only delete from the list if the item isn't poisoned.
-		 */
-		if (cmd->cmd_list.next != LIST_POISON1)
-			list_del(&cmd->cmd_list);
-		spin_unlock_irqrestore(&xhci->lock, flags);
 		ret = -ETIME;
-		goto command_cleanup;
 	}
-
-command_cleanup:
 	xhci_free_command(xhci, cmd);
 	return ret;
 }
diff --git a/drivers/usb/host/xhci-mem.c b/drivers/usb/host/xhci-mem.c
index 9df2aa0..81c2469 100644
--- a/drivers/usb/host/xhci-mem.c
+++ b/drivers/usb/host/xhci-mem.c
@@ -919,7 +919,6 @@ int xhci_alloc_virt_device(struct xhci_hcd *xhci, int slot_id,
 	dev->num_rings_cached = 0;
 
 	init_completion(&dev->cmd_completion);
-	INIT_LIST_HEAD(&dev->cmd_list);
 	dev->udev = udev;
 
 	/* Point to output device context in dcbaa. */
diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c
index 39d3ff7..12bf467 100644
--- a/drivers/usb/host/xhci-ring.c
+++ b/drivers/usb/host/xhci-ring.c
@@ -69,10 +69,6 @@
 #include "xhci.h"
 #include "xhci-trace.h"
 
-static int handle_cmd_in_cmd_wait_list(struct xhci_hcd *xhci,
-		struct xhci_virt_device *virt_dev,
-		struct xhci_event_cmd *event);
-
 /*
  * Returns zero if the TRB isn't in this segment, otherwise it returns the DMA
  * address of the TRB.
@@ -755,7 +751,6 @@ static void xhci_handle_cmd_stop_ep(struct xhci_hcd *xhci, int slot_id,
 		union xhci_trb *trb, struct xhci_event_cmd *event)
 {
 	unsigned int ep_index;
-	struct xhci_virt_device *virt_dev;
 	struct xhci_ring *ep_ring;
 	struct xhci_virt_ep *ep;
 	struct list_head *entry;
@@ -765,11 +760,7 @@ static void xhci_handle_cmd_stop_ep(struct xhci_hcd *xhci, int slot_id,
 	struct xhci_dequeue_state deq_state;
 
 	if (unlikely(TRB_TO_SUSPEND_PORT(le32_to_cpu(trb->generic.field[3])))) {
-		virt_dev = xhci->devs[slot_id];
-		if (virt_dev)
-			handle_cmd_in_cmd_wait_list(xhci, virt_dev,
-				event);
-		else
+		if (!xhci->devs[slot_id])
 			xhci_warn(xhci, "Stop endpoint command "
 				"completion for disabled slot %u\n",
 				slot_id);
@@ -1197,29 +1188,6 @@ static void xhci_complete_cmd_in_cmd_wait_list(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;
-
-	xhci_complete_cmd_in_cmd_wait_list(xhci, command,
-			GET_COMP_CODE(le32_to_cpu(event->status)));
-	return 1;
-}
-
 /*
  * Finding the command trb need to be cancelled and modifying it to
  * NO OP command. And if the command is in device's command wait
@@ -1371,7 +1339,6 @@ static void xhci_handle_cmd_enable_slot(struct xhci_hcd *xhci, int slot_id,
 		xhci->slot_id = slot_id;
 	else
 		xhci->slot_id = 0;
-	complete(&xhci->addr_dev);
 }
 
 static void xhci_handle_cmd_disable_slot(struct xhci_hcd *xhci, int slot_id)
@@ -1396,9 +1363,6 @@ static void xhci_handle_cmd_config_ep(struct xhci_hcd *xhci, int slot_id,
 	unsigned int ep_state;
 	u32 add_flags, drop_flags;
 
-	virt_dev = xhci->devs[slot_id];
-	if (handle_cmd_in_cmd_wait_list(xhci, virt_dev, event))
-		return;
 	/*
 	 * Configure endpoint commands can come from the USB core
 	 * configuration or alt setting changes, or because the HW
@@ -1407,6 +1371,7 @@ static void xhci_handle_cmd_config_ep(struct xhci_hcd *xhci, int slot_id,
 	 * If the command was for a halted endpoint, the xHCI driver
 	 * is not waiting on the configure endpoint command.
 	 */
+	virt_dev = xhci->devs[slot_id];
 	ctrl_ctx = xhci_get_input_control_ctx(xhci, virt_dev->in_ctx);
 	if (!ctrl_ctx) {
 		xhci_warn(xhci, "Could not get input context, bad type.\n");
@@ -1442,35 +1407,11 @@ static void xhci_handle_cmd_config_ep(struct xhci_hcd *xhci, int slot_id,
 	return;
 }
 
-static void xhci_handle_cmd_eval_ctx(struct xhci_hcd *xhci, int slot_id,
-		struct xhci_event_cmd *event, u32 cmd_comp_code)
-{
-	struct xhci_virt_device *virt_dev;
-
-	virt_dev = xhci->devs[slot_id];
-	if (handle_cmd_in_cmd_wait_list(xhci, virt_dev, event))
-		return;
-	virt_dev->cmd_status = cmd_comp_code;
-	complete(&virt_dev->cmd_completion);
-}
-
-static void xhci_handle_cmd_addr_dev(struct xhci_hcd *xhci, int slot_id,
-		u32 cmd_comp_code)
-{
-	xhci->devs[slot_id]->cmd_status = cmd_comp_code;
-	complete(&xhci->addr_dev);
-}
-
 static void xhci_handle_cmd_reset_dev(struct xhci_hcd *xhci, int slot_id,
 		struct xhci_event_cmd *event)
 {
-	struct xhci_virt_device *virt_dev;
-
 	xhci_dbg(xhci, "Completed reset device command.\n");
-	virt_dev = xhci->devs[slot_id];
-	if (virt_dev)
-		handle_cmd_in_cmd_wait_list(xhci, virt_dev, event);
-	else
+	if (!xhci->devs[slot_id])
 		xhci_warn(xhci, "Reset device command completion "
 				"for disabled slot %u\n", slot_id);
 }
@@ -1552,13 +1493,13 @@ static void handle_cmd_completion(struct xhci_hcd *xhci,
 		xhci_handle_cmd_disable_slot(xhci, slot_id);
 		break;
 	case TRB_CONFIG_EP:
-		xhci_handle_cmd_config_ep(xhci, slot_id, event, cmd_comp_code);
+		if (!cmd->completion)
+			xhci_handle_cmd_config_ep(xhci, slot_id, event,
+						  cmd_comp_code);
 		break;
 	case TRB_EVAL_CONTEXT:
-		xhci_handle_cmd_eval_ctx(xhci, slot_id, event, cmd_comp_code);
 		break;
 	case TRB_ADDR_DEV:
-		xhci_handle_cmd_addr_dev(xhci, slot_id, cmd_comp_code);
 		break;
 	case TRB_STOP_RING:
 		WARN_ON(slot_id != TRB_TO_SLOT_ID(
@@ -1593,8 +1534,13 @@ static void handle_cmd_completion(struct xhci_hcd *xhci,
 
 	list_del(&cmd->cmd_list);
 
-	if (!cmd->completion)
+	if (cmd->completion) {
+		/* the caller waiting for completion should free the command */
+		cmd->status = cmd_comp_code;
+		complete(cmd->completion);
+	} else {
 		kfree(cmd);
+	}
 
 	inc_deq(xhci, xhci->cmd_ring);
 }
diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c
index 97de328..4dc88ae 100644
--- a/drivers/usb/host/xhci.c
+++ b/drivers/usb/host/xhci.c
@@ -2622,8 +2622,6 @@ static int xhci_configure_endpoint(struct xhci_hcd *xhci,
 		return -ENOMEM;
 	}
 
-	list_add_tail(&command->cmd_list, &virt_dev->cmd_list);
-
 	if (!ctx_change)
 		ret = xhci_queue_configure_endpoint(xhci, command,
 				command->in_ctx->dma,
@@ -2633,7 +2631,6 @@ static int xhci_configure_endpoint(struct xhci_hcd *xhci,
 				command->in_ctx->dma,
 				udev->slot_id, must_succeed);
 	if (ret < 0) {
-		list_del(&command->cmd_list);
 		if ((xhci->quirks & XHCI_EP_LIMIT_QUIRK))
 			xhci_free_host_resources(xhci, ctrl_ctx);
 		spin_unlock_irqrestore(&xhci->lock, flags);
@@ -3473,11 +3470,9 @@ int xhci_discover_or_reset_device(struct usb_hcd *hcd, struct usb_device *udev)
 	/* Attempt to submit the Reset Device command to the command ring */
 	spin_lock_irqsave(&xhci->lock, flags);
 
-	list_add_tail(&reset_device_cmd->cmd_list, &virt_dev->cmd_list);
 	ret = xhci_queue_reset_device(xhci, reset_device_cmd, slot_id);
 	if (ret) {
 		xhci_dbg(xhci, "FIXME: allocate a command ring segment\n");
-		list_del(&reset_device_cmd->cmd_list);
 		spin_unlock_irqrestore(&xhci->lock, flags);
 		goto command_cleanup;
 	}
@@ -3491,13 +3486,6 @@ int xhci_discover_or_reset_device(struct usb_hcd *hcd, struct usb_device *udev)
 	if (timeleft <= 0) {
 		xhci_warn(xhci, "%s while waiting for reset device command\n",
 				timeleft == 0 ? "Timeout" : "Signal");
-		spin_lock_irqsave(&xhci->lock, flags);
-		/* The timeout might have raced with the event ring handler, so
-		 * only delete from the list if the item isn't poisoned.
-		 */
-		if (reset_device_cmd->cmd_list.next != LIST_POISON1)
-			list_del(&reset_device_cmd->cmd_list);
-		spin_unlock_irqrestore(&xhci->lock, flags);
 		ret = -ETIME;
 		goto command_cleanup;
 	}
@@ -3864,7 +3852,7 @@ static int xhci_setup_device(struct usb_hcd *hcd, struct usb_device *udev,
 		return -ETIME;
 	}
 
-	switch (virt_dev->cmd_status) {
+	switch (command->status) {
 	case COMP_CTX_STATE:
 	case COMP_EBADSLT:
 		xhci_err(xhci, "Setup ERROR: setup %s command for slot %d.\n",
@@ -3887,7 +3875,7 @@ static int xhci_setup_device(struct usb_hcd *hcd, struct usb_device *udev,
 	default:
 		xhci_err(xhci,
 			 "ERROR: unexpected setup %s command completion code 0x%x.\n",
-			 act, virt_dev->cmd_status);
+			 act, command->status);
 		xhci_dbg(xhci, "Slot ID %d Output Context:\n", udev->slot_id);
 		xhci_dbg_ctx(xhci, virt_dev->out_ctx, 2);
 		trace_xhci_address_ctx(xhci, virt_dev->out_ctx, 1);
diff --git a/drivers/usb/host/xhci.h b/drivers/usb/host/xhci.h
index 7052b8c..217e5b0 100644
--- a/drivers/usb/host/xhci.h
+++ b/drivers/usb/host/xhci.h
@@ -938,9 +938,6 @@ struct xhci_virt_device {
 #define	XHCI_MAX_RINGS_CACHED	31
 	struct xhci_virt_ep		eps[31];
 	struct completion		cmd_completion;
-	/* Status of the last command issued for this device */
-	u32				cmd_status;
-	struct list_head		cmd_list;
 	u8				fake_port;
 	u8				real_port;
 	struct xhci_interval_bw_table	*bw_table;
-- 
1.8.1.2


^ permalink raw reply related	[flat|nested] 7+ messages in thread

* [RFCv3 4/4] xhci: rework command timeout and cancellation,
  2014-02-26 19:38 [RFCv3 0/4] xhci: re-work command queue management Mathias Nyman
                   ` (2 preceding siblings ...)
  2014-02-26 19:38 ` [RFCv3 3/4] xhci: Use completion and status in " Mathias Nyman
@ 2014-02-26 19:38 ` Mathias Nyman
  2014-03-06 21:44   ` Sarah Sharp
  3 siblings, 1 reply; 7+ messages in thread
From: Mathias Nyman @ 2014-02-26 19:38 UTC (permalink / raw)
  To: linux-usb; +Cc: sarah.a.sharp, dan.j.williams, linux-kernel, Mathias Nyman

Use one timer to control command timeout.

start/kick the timer every time a command is completed and a
new command is waiting, or a new command is added to a empty list.

If the timer runs out, then tag the current command as "aborted", and
start the xhci command abortion process.

Previously each function that submitted a command had its own timer.
If that command timed out, a new command structure for
the command was created and it was put on a cancel_cmd_list list,
then a pci write to abort the command ring was issued.

when the ring was aborted, it checked if the current command
was the one to be canceled, later when the ring was stopped the
driver got ownership of the TRBs in the command ring,
compared then to the TRBs in the cancel_cmd_list,
and turned them into No-ops.

Now, instead, at timeout we tag the status of the command in the
command queue to be aborted, and start the ring abortion.
Ring abortion stops the command ring and gives control of the commands to us.
All the aborted commands are now turned into No-ops.

This allows us to remove the entire cancel_cmd_list code.

The functions waiting for a command to finish no longer have their own timeouts.
They will wait either until the command completes normally,
or until the whole command abortion is done.

Signed-off-by: Mathias Nyman <mathias.nyman@linux.intel.com>
---
 drivers/usb/host/xhci-hub.c  |  11 +-
 drivers/usb/host/xhci-mem.c  |  15 +-
 drivers/usb/host/xhci-ring.c | 335 +++++++++++++------------------------------
 drivers/usb/host/xhci.c      |  78 ++++------
 drivers/usb/host/xhci.h      |   8 +-
 5 files changed, 138 insertions(+), 309 deletions(-)

diff --git a/drivers/usb/host/xhci-hub.c b/drivers/usb/host/xhci-hub.c
index 0a57d95..8350fd9 100644
--- a/drivers/usb/host/xhci-hub.c
+++ b/drivers/usb/host/xhci-hub.c
@@ -271,7 +271,6 @@ static int xhci_stop_device(struct xhci_hcd *xhci, int slot_id, int suspend)
 	struct xhci_virt_device *virt_dev;
 	struct xhci_command *cmd;
 	unsigned long flags;
-	int timeleft;
 	int ret;
 	int i;
 
@@ -304,12 +303,10 @@ static int xhci_stop_device(struct xhci_hcd *xhci, int slot_id, int suspend)
 	spin_unlock_irqrestore(&xhci->lock, flags);
 
 	/* Wait for last stop endpoint command to finish */
-	timeleft = wait_for_completion_interruptible_timeout(
-			cmd->completion,
-			XHCI_CMD_DEFAULT_TIMEOUT);
-	if (timeleft <= 0) {
-		xhci_warn(xhci, "%s while waiting for stop endpoint command\n",
-				timeleft == 0 ? "Timeout" : "Signal");
+	wait_for_completion(cmd->completion);
+
+	if (cmd->status == COMP_CMD_ABORT || cmd->status == COMP_CMD_STOP) {
+		xhci_warn(xhci, "Timeout while waiting for stop endpoint command\n");
 		ret = -ETIME;
 	}
 	xhci_free_command(xhci, cmd);
diff --git a/drivers/usb/host/xhci-mem.c b/drivers/usb/host/xhci-mem.c
index 81c2469..6baaaf5 100644
--- a/drivers/usb/host/xhci-mem.c
+++ b/drivers/usb/host/xhci-mem.c
@@ -1692,7 +1692,6 @@ void xhci_free_command(struct xhci_hcd *xhci,
 void xhci_mem_cleanup(struct xhci_hcd *xhci)
 {
 	struct device	*dev = xhci_to_hcd(xhci)->self.controller;
-	struct xhci_cd  *cur_cd, *next_cd;
 	struct xhci_command *cur_cmd, *next_cmd;
 	int size;
 	int i, j, num_ports;
@@ -1712,15 +1711,13 @@ void xhci_mem_cleanup(struct xhci_hcd *xhci)
 	if (xhci->lpm_command)
 		xhci_free_command(xhci, xhci->lpm_command);
 	xhci->cmd_ring_reserved_trbs = 0;
+
+	del_timer_sync(&xhci->cmd_timer);
+
 	if (xhci->cmd_ring)
 		xhci_ring_free(xhci, xhci->cmd_ring);
 	xhci->cmd_ring = NULL;
 	xhci_dbg_trace(xhci, trace_xhci_dbg_init, "Freed command ring");
-	list_for_each_entry_safe(cur_cd, next_cd,
-			&xhci->cancel_cmd_list, cancel_cmd_list) {
-		list_del(&cur_cd->cancel_cmd_list);
-		kfree(cur_cd);
-	}
 
 	list_for_each_entry_safe(cur_cmd, next_cmd,
 			&xhci->cmd_list, cmd_list) {
@@ -2228,7 +2225,6 @@ int xhci_mem_init(struct xhci_hcd *xhci, gfp_t flags)
 	u32 page_size, temp;
 	int i;
 
-	INIT_LIST_HEAD(&xhci->cancel_cmd_list);
 	INIT_LIST_HEAD(&xhci->cmd_list);
 
 	page_size = readl(&xhci->op_regs->page_size);
@@ -2414,6 +2410,11 @@ int xhci_mem_init(struct xhci_hcd *xhci, gfp_t flags)
 			"Wrote ERST address to ir_set 0.");
 	xhci_print_ir_set(xhci, 0);
 
+	/* init command timeout timer */
+	init_timer(&xhci->cmd_timer);
+	xhci->cmd_timer.data = (unsigned long) xhci;
+	xhci->cmd_timer.function = xhci_handle_command_timeout;
+
 	/*
 	 * XXX: Might need to set the Interrupter Moderation Register to
 	 * something other than the default (~1ms minimum between interrupts).
diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c
index 12bf467..b664a42 100644
--- a/drivers/usb/host/xhci-ring.c
+++ b/drivers/usb/host/xhci-ring.c
@@ -323,71 +323,6 @@ static int xhci_abort_cmd_ring(struct xhci_hcd *xhci)
 	return 0;
 }
 
-static int xhci_queue_cd(struct xhci_hcd *xhci,
-		struct xhci_command *command,
-		union xhci_trb *cmd_trb)
-{
-	struct xhci_cd *cd;
-	cd = kzalloc(sizeof(struct xhci_cd), GFP_ATOMIC);
-	if (!cd)
-		return -ENOMEM;
-	INIT_LIST_HEAD(&cd->cancel_cmd_list);
-
-	cd->command = command;
-	cd->cmd_trb = cmd_trb;
-	list_add_tail(&cd->cancel_cmd_list, &xhci->cancel_cmd_list);
-
-	return 0;
-}
-
-/*
- * Cancel the command which has issue.
- *
- * Some commands may hang due to waiting for acknowledgement from
- * usb device. It is outside of the xHC's ability to control and
- * will cause the command ring is blocked. When it occurs software
- * should intervene to recover the command ring.
- * See Section 4.6.1.1 and 4.6.1.2
- */
-int xhci_cancel_cmd(struct xhci_hcd *xhci, struct xhci_command *command,
-		union xhci_trb *cmd_trb)
-{
-	int retval = 0;
-	unsigned long flags;
-
-	spin_lock_irqsave(&xhci->lock, flags);
-
-	if (xhci->xhc_state & XHCI_STATE_DYING) {
-		xhci_warn(xhci, "Abort the command ring,"
-				" but the xHCI is dead.\n");
-		retval = -ESHUTDOWN;
-		goto fail;
-	}
-
-	/* queue the cmd desriptor to cancel_cmd_list */
-	retval = xhci_queue_cd(xhci, command, cmd_trb);
-	if (retval) {
-		xhci_warn(xhci, "Queuing command descriptor failed.\n");
-		goto fail;
-	}
-
-	/* abort command ring */
-	retval = xhci_abort_cmd_ring(xhci);
-	if (retval) {
-		xhci_err(xhci, "Abort command ring failed\n");
-		if (unlikely(retval == -ESHUTDOWN)) {
-			spin_unlock_irqrestore(&xhci->lock, flags);
-			usb_hc_died(xhci_to_hcd(xhci)->primary_hcd);
-			xhci_dbg(xhci, "xHCI host controller is dead.\n");
-			return retval;
-		}
-	}
-
-fail:
-	spin_unlock_irqrestore(&xhci->lock, flags);
-	return retval;
-}
-
 void xhci_ring_ep_doorbell(struct xhci_hcd *xhci,
 		unsigned int slot_id,
 		unsigned int ep_index,
@@ -1174,164 +1109,6 @@ static void xhci_handle_cmd_reset_ep(struct xhci_hcd *xhci, int slot_id,
 	}
 }
 
-/* Complete the command and detele it from the devcie's command queue.
- */
-static void xhci_complete_cmd_in_cmd_wait_list(struct xhci_hcd *xhci,
-		struct xhci_command *command, u32 status)
-{
-	command->status = status;
-	list_del(&command->cmd_list);
-	if (command->completion)
-		complete(command->completion);
-	else
-		xhci_free_command(xhci, command);
-}
-
-
-/*
- * Finding the command trb need to be cancelled and modifying it to
- * NO OP command. And if the command is in device's command wait
- * list, finishing and freeing it.
- *
- * If we can't find the command trb, we think it had already been
- * executed.
- */
-static void xhci_cmd_to_noop(struct xhci_hcd *xhci, struct xhci_cd *cur_cd)
-{
-	struct xhci_segment *cur_seg;
-	union xhci_trb *cmd_trb;
-	u32 cycle_state;
-
-	if (xhci->cmd_ring->dequeue == xhci->cmd_ring->enqueue)
-		return;
-
-	/* find the current segment of command ring */
-	cur_seg = find_trb_seg(xhci->cmd_ring->first_seg,
-			xhci->cmd_ring->dequeue, &cycle_state);
-
-	if (!cur_seg) {
-		xhci_warn(xhci, "Command ring mismatch, dequeue = %p %llx (dma)\n",
-				xhci->cmd_ring->dequeue,
-				(unsigned long long)
-				xhci_trb_virt_to_dma(xhci->cmd_ring->deq_seg,
-					xhci->cmd_ring->dequeue));
-		xhci_debug_ring(xhci, xhci->cmd_ring);
-		xhci_dbg_ring_ptrs(xhci, xhci->cmd_ring);
-		return;
-	}
-
-	/* find the command trb matched by cd from command ring */
-	for (cmd_trb = xhci->cmd_ring->dequeue;
-			cmd_trb != xhci->cmd_ring->enqueue;
-			next_trb(xhci, xhci->cmd_ring, &cur_seg, &cmd_trb)) {
-		/* If the trb is link trb, continue */
-		if (TRB_TYPE_LINK_LE32(cmd_trb->generic.field[3]))
-			continue;
-
-		if (cur_cd->cmd_trb == cmd_trb) {
-
-			/* If the command in device's command list, we should
-			 * finish it and free the command structure.
-			 */
-			if (cur_cd->command)
-				xhci_complete_cmd_in_cmd_wait_list(xhci,
-					cur_cd->command, COMP_CMD_STOP);
-
-			/* get cycle state from the origin command trb */
-			cycle_state = le32_to_cpu(cmd_trb->generic.field[3])
-				& TRB_CYCLE;
-
-			/* modify the command trb to NO OP command */
-			cmd_trb->generic.field[0] = 0;
-			cmd_trb->generic.field[1] = 0;
-			cmd_trb->generic.field[2] = 0;
-			cmd_trb->generic.field[3] = cpu_to_le32(
-					TRB_TYPE(TRB_CMD_NOOP) | cycle_state);
-			break;
-		}
-	}
-}
-
-static void xhci_cancel_cmd_in_cd_list(struct xhci_hcd *xhci)
-{
-	struct xhci_cd *cur_cd, *next_cd;
-
-	if (list_empty(&xhci->cancel_cmd_list))
-		return;
-
-	list_for_each_entry_safe(cur_cd, next_cd,
-			&xhci->cancel_cmd_list, cancel_cmd_list) {
-		xhci_cmd_to_noop(xhci, cur_cd);
-		list_del(&cur_cd->cancel_cmd_list);
-		kfree(cur_cd);
-	}
-}
-
-/*
- * traversing the cancel_cmd_list. If the command descriptor according
- * to cmd_trb is found, the function free it and return 1, otherwise
- * return 0.
- */
-static int xhci_search_cmd_trb_in_cd_list(struct xhci_hcd *xhci,
-		union xhci_trb *cmd_trb)
-{
-	struct xhci_cd *cur_cd, *next_cd;
-
-	if (list_empty(&xhci->cancel_cmd_list))
-		return 0;
-
-	list_for_each_entry_safe(cur_cd, next_cd,
-			&xhci->cancel_cmd_list, cancel_cmd_list) {
-		if (cur_cd->cmd_trb == cmd_trb) {
-			if (cur_cd->command)
-				xhci_complete_cmd_in_cmd_wait_list(xhci,
-					cur_cd->command, COMP_CMD_STOP);
-			list_del(&cur_cd->cancel_cmd_list);
-			kfree(cur_cd);
-			return 1;
-		}
-	}
-
-	return 0;
-}
-
-/*
- * If the cmd_trb_comp_code is COMP_CMD_ABORT, we just check whether the
- * trb pointed by the command ring dequeue pointer is the trb we want to
- * cancel or not. And if the cmd_trb_comp_code is COMP_CMD_STOP, we will
- * traverse the cancel_cmd_list to trun the all of the commands according
- * to command descriptor to NO-OP trb.
- */
-static int handle_stopped_cmd_ring(struct xhci_hcd *xhci,
-		int cmd_trb_comp_code)
-{
-	int cur_trb_is_good = 0;
-
-	/* Searching the cmd trb pointed by the command ring dequeue
-	 * pointer in command descriptor list. If it is found, free it.
-	 */
-	cur_trb_is_good = xhci_search_cmd_trb_in_cd_list(xhci,
-			xhci->cmd_ring->dequeue);
-
-	if (cmd_trb_comp_code == COMP_CMD_ABORT)
-		xhci->cmd_ring_state = CMD_RING_STATE_STOPPED;
-	else if (cmd_trb_comp_code == COMP_CMD_STOP) {
-		/* traversing the cancel_cmd_list and canceling
-		 * the command according to command descriptor
-		 */
-		xhci_cancel_cmd_in_cd_list(xhci);
-
-		xhci->cmd_ring_state = CMD_RING_STATE_RUNNING;
-		/*
-		 * ring command ring doorbell again to restart the
-		 * command ring
-		 */
-		if (xhci->cmd_ring->dequeue != xhci->cmd_ring->enqueue)
-			xhci_ring_cmd_db(xhci);
-	}
-	return cur_trb_is_good;
-}
-
 static void xhci_handle_cmd_enable_slot(struct xhci_hcd *xhci, int slot_id,
 		u32 cmd_comp_code)
 {
@@ -1429,6 +1206,30 @@ static void xhci_handle_cmd_nec_get_fw(struct xhci_hcd *xhci,
 			NEC_FW_MINOR(le32_to_cpu(event->status)));
 }
 
+void xhci_handle_command_timeout(unsigned long data)
+{
+	struct xhci_hcd *xhci;
+	int ret;
+	unsigned long flags;
+	xhci = (struct xhci_hcd *) data;
+	/* mark this command to be cancelled */
+	spin_lock_irqsave(&xhci->lock, flags);
+	if (xhci->current_cmd)
+		xhci->current_cmd->status = COMP_CMD_ABORT;
+	spin_unlock_irqrestore(&xhci->lock, flags);
+
+	ret = xhci_abort_cmd_ring(xhci);
+
+	if (ret) {
+		xhci_err(xhci, "Abort command ring failed\n");
+		if (unlikely(ret == -ESHUTDOWN)) {
+			usb_hc_died(xhci_to_hcd(xhci)->primary_hcd);
+			xhci_dbg(xhci, "xHCI host controller is dead.\n");
+		}
+	}
+	return;
+}
+
 static void handle_cmd_completion(struct xhci_hcd *xhci,
 		struct xhci_event_cmd *event)
 {
@@ -1462,26 +1263,64 @@ static void handle_cmd_completion(struct xhci_hcd *xhci,
 			 "Command completion event does not match command\n");
 		return;
 	}
+
+	del_timer(&xhci->cmd_timer);
+
 	trace_xhci_cmd_completion(cmd_trb, (struct xhci_generic_trb *) event);
 
 	cmd_comp_code = GET_COMP_CODE(le32_to_cpu(event->status));
-	if (cmd_comp_code == COMP_CMD_ABORT || cmd_comp_code == COMP_CMD_STOP) {
-		/* If the return value is 0, we think the trb pointed by
-		 * command ring dequeue pointer is a good trb. The good
-		 * trb means we don't want to cancel the trb, but it have
-		 * been stopped by host. So we should handle it normally.
-		 * Otherwise, driver should invoke inc_deq() and return.
-		 */
-		if (handle_stopped_cmd_ring(xhci, cmd_comp_code)) {
-			inc_deq(xhci, xhci->cmd_ring);
-			return;
+
+	/* If CMD ring stopped we own the trbs between enqueue and dequeue */
+	if (cmd_comp_code == COMP_CMD_STOP) {
+		struct xhci_command *cur_cmd, *tmp_cmd;
+		u32 cycle_state;
+
+		/* Turn all aborted commands in list to no-ops, then restart */
+		list_for_each_entry_safe(cur_cmd, tmp_cmd, &xhci->cmd_list,
+					 cmd_list) {
+
+			if (cur_cmd->status != COMP_CMD_ABORT)
+				continue;
+
+			cur_cmd->status = COMP_CMD_STOP;
+
+			/* get cycle state from the original cmd trb */
+			cycle_state = le32_to_cpu(
+				cur_cmd->command_trb->generic.field[3]) &
+				TRB_CYCLE;
+
+			/* modify the command trb to NO OP command */
+			cur_cmd->command_trb->generic.field[0] = 0;
+			cur_cmd->command_trb->generic.field[1] = 0;
+			cur_cmd->command_trb->generic.field[2] = 0;
+			cur_cmd->command_trb->generic.field[3] = cpu_to_le32(
+				TRB_TYPE(TRB_CMD_NOOP) | cycle_state);
+
+			/* completion is called when command completion
+			 * event is received for these no-op commands
+			 */
 		}
-		/* There is no command to handle if we get a stop event when the
-		 * command ring is empty, event->cmd_trb points to the next
-		 * unset command
-		 */
-		if (xhci->cmd_ring->dequeue == xhci->cmd_ring->enqueue)
-			return;
+		xhci->cmd_ring_state = CMD_RING_STATE_RUNNING;
+
+		/* ring command ring doorbell to restart the command ring */
+		if (xhci->cmd_ring->dequeue != xhci->cmd_ring->enqueue) {
+			xhci->current_cmd = cmd;
+			mod_timer(&xhci->cmd_timer,
+				  jiffies + XHCI_CMD_DEFAULT_TIMEOUT);
+			xhci_ring_cmd_db(xhci);
+		}
+		return;
+	}
+	/*
+	 * Host aborted the command ring, check if the current command was
+	 * supposed to be aborted, otherwise continue normally.
+	 * The command ring is stopped now, but the xHC will issue a Command
+	 * Ring Stopped event which will cause us to restart it.
+	 */
+	if (cmd_comp_code == COMP_CMD_ABORT) {
+		xhci->cmd_ring_state = CMD_RING_STATE_STOPPED;
+		if (cmd->status == COMP_CMD_ABORT)
+			goto event_handled;
 	}
 
 	cmd_type = TRB_FIELD_TO_TYPE(le32_to_cpu(cmd_trb->generic.field[3]));
@@ -1512,6 +1351,9 @@ static void handle_cmd_completion(struct xhci_hcd *xhci,
 		xhci_handle_cmd_set_deq(xhci, slot_id, cmd_trb, cmd_comp_code);
 		break;
 	case TRB_CMD_NOOP:
+		/* Is this an aborted command turned to NO-OP? */
+		if (cmd->status == COMP_CMD_STOP)
+			cmd_comp_code = COMP_CMD_STOP;
 		break;
 	case TRB_RESET_EP:
 		WARN_ON(slot_id != TRB_TO_SLOT_ID(
@@ -1532,6 +1374,14 @@ static void handle_cmd_completion(struct xhci_hcd *xhci,
 		break;
 	}
 
+	/* restart timer if this wasn't the last command */
+	if (cmd->cmd_list.next != &xhci->cmd_list) {
+		xhci->current_cmd = list_entry(cmd->cmd_list.next,
+					       struct xhci_command, cmd_list);
+		mod_timer(&xhci->cmd_timer, jiffies + XHCI_CMD_DEFAULT_TIMEOUT);
+	}
+
+event_handled:
 	list_del(&cmd->cmd_list);
 
 	if (cmd->completion) {
@@ -3946,6 +3796,13 @@ static int queue_command(struct xhci_hcd *xhci, struct xhci_command *cmd,
 	cmd->command_trb = xhci->cmd_ring->enqueue;
 	list_add_tail(&cmd->cmd_list, &xhci->cmd_list);
 
+	/* if there are no other commands queued we start the timeout timer */
+	if (xhci->cmd_list.next == &cmd->cmd_list &&
+	    !timer_pending(&xhci->cmd_timer)) {
+		xhci->current_cmd = cmd;
+		mod_timer(&xhci->cmd_timer, jiffies + XHCI_CMD_DEFAULT_TIMEOUT);
+	}
+
 	queue_trb(xhci, xhci->cmd_ring, false, field1, field2, field3,
 			field4 | xhci->cmd_ring->cycle_state);
 	return 0;
diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c
index 4dc88ae..d44eee7 100644
--- a/drivers/usb/host/xhci.c
+++ b/drivers/usb/host/xhci.c
@@ -1816,6 +1816,11 @@ static int xhci_configure_endpoint_result(struct xhci_hcd *xhci,
 	int ret;
 
 	switch (*cmd_status) {
+	case COMP_CMD_ABORT:
+	case COMP_CMD_STOP:
+		xhci_warn(xhci, "Timeout while waiting for configure endpoint command\n");
+		ret = -ETIME;
+		break;
 	case COMP_ENOMEM:
 		dev_warn(&udev->dev, "Not enough host controller resources "
 				"for new device state.\n");
@@ -1862,6 +1867,11 @@ static int xhci_evaluate_context_result(struct xhci_hcd *xhci,
 	struct xhci_virt_device *virt_dev = xhci->devs[udev->slot_id];
 
 	switch (*cmd_status) {
+	case COMP_CMD_ABORT:
+	case COMP_CMD_STOP:
+		xhci_warn(xhci, "Timeout while waiting for evaluate context command\n");
+		ret = -ETIME;
+		break;
 	case COMP_EINVAL:
 		dev_warn(&udev->dev, "WARN: xHCI driver setup invalid evaluate "
 				"context command.\n");
@@ -2586,7 +2596,6 @@ static int xhci_configure_endpoint(struct xhci_hcd *xhci,
 		bool ctx_change, bool must_succeed)
 {
 	int ret;
-	int timeleft;
 	unsigned long flags;
 	struct xhci_input_control_ctx *ctrl_ctx;
 	struct xhci_virt_device *virt_dev;
@@ -2642,21 +2651,7 @@ static int xhci_configure_endpoint(struct xhci_hcd *xhci,
 	spin_unlock_irqrestore(&xhci->lock, flags);
 
 	/* Wait for the configure endpoint command to complete */
-	timeleft = wait_for_completion_interruptible_timeout(
-			command->completion,
-			XHCI_CMD_DEFAULT_TIMEOUT);
-	if (timeleft <= 0) {
-		xhci_warn(xhci, "%s while waiting for %s command\n",
-				timeleft == 0 ? "Timeout" : "Signal",
-				ctx_change == 0 ?
-					"configure endpoint" :
-					"evaluate context");
-		/* cancel the configure endpoint command */
-		ret = xhci_cancel_cmd(xhci, command, command->command_trb);
-		if (ret < 0)
-			return ret;
-		return -ETIME;
-	}
+	wait_for_completion(command->completion);
 
 	if (!ctx_change)
 		ret = xhci_configure_endpoint_result(xhci, udev,
@@ -3412,7 +3407,6 @@ int xhci_discover_or_reset_device(struct usb_hcd *hcd, struct usb_device *udev)
 	unsigned int slot_id;
 	struct xhci_virt_device *virt_dev;
 	struct xhci_command *reset_device_cmd;
-	int timeleft;
 	int last_freed_endpoint;
 	struct xhci_slot_ctx *slot_ctx;
 	int old_active_eps = 0;
@@ -3480,15 +3474,7 @@ int xhci_discover_or_reset_device(struct usb_hcd *hcd, struct usb_device *udev)
 	spin_unlock_irqrestore(&xhci->lock, flags);
 
 	/* Wait for the Reset Device command to finish */
-	timeleft = wait_for_completion_interruptible_timeout(
-			reset_device_cmd->completion,
-			XHCI_CMD_DEFAULT_TIMEOUT);
-	if (timeleft <= 0) {
-		xhci_warn(xhci, "%s while waiting for reset device command\n",
-				timeleft == 0 ? "Timeout" : "Signal");
-		ret = -ETIME;
-		goto command_cleanup;
-	}
+	wait_for_completion(reset_device_cmd->completion);
 
 	/* The Reset Device command can't fail, according to the 0.95/0.96 spec,
 	 * unless we tried to reset a slot ID that wasn't enabled,
@@ -3496,6 +3482,11 @@ int xhci_discover_or_reset_device(struct usb_hcd *hcd, struct usb_device *udev)
 	 */
 	ret = reset_device_cmd->status;
 	switch (ret) {
+	case COMP_CMD_ABORT:
+	case COMP_CMD_STOP:
+		xhci_warn(xhci, "Timeout waiting for reset device command\n");
+		ret = -ETIME;
+		goto command_cleanup;
 	case COMP_EBADSLT: /* 0.95 completion code for bad slot ID */
 	case COMP_CTX_STATE: /* 0.96 completion code for same thing */
 		xhci_dbg(xhci, "Can't reset device (slot ID %u) in %s state\n",
@@ -3663,7 +3654,6 @@ int xhci_alloc_dev(struct usb_hcd *hcd, struct usb_device *udev)
 {
 	struct xhci_hcd *xhci = hcd_to_xhci(hcd);
 	unsigned long flags;
-	int timeleft;
 	int ret;
 	struct xhci_command *command;
 
@@ -3683,19 +3673,9 @@ int xhci_alloc_dev(struct usb_hcd *hcd, struct usb_device *udev)
 	xhci_ring_cmd_db(xhci);
 	spin_unlock_irqrestore(&xhci->lock, flags);
 
-	/* XXX: how much time for xHC slot assignment? */
-	timeleft = wait_for_completion_interruptible_timeout(
-			command->completion,
-			XHCI_CMD_DEFAULT_TIMEOUT);
-	if (timeleft <= 0) {
-		xhci_warn(xhci, "%s while waiting for a slot\n",
-				timeleft == 0 ? "Timeout" : "Signal");
-		/* cancel the enable slot request */
-		ret = xhci_cancel_cmd(xhci, NULL, command->command_trb);
-		return ret;
-	}
+	wait_for_completion(command->completion);
 
-	if (!xhci->slot_id) {
+	if (!xhci->slot_id || command->status != COMP_SUCCESS) {
 		xhci_err(xhci, "Error while assigning device slot ID\n");
 		kfree(command);
 		return 0;
@@ -3761,7 +3741,6 @@ static int xhci_setup_device(struct usb_hcd *hcd, struct usb_device *udev,
 {
 	const char *act = setup == SETUP_CONTEXT_ONLY ? "context" : "address";
 	unsigned long flags;
-	int timeleft;
 	struct xhci_virt_device *virt_dev;
 	int ret = 0;
 	struct xhci_hcd *xhci = hcd_to_xhci(hcd);
@@ -3836,23 +3815,18 @@ static int xhci_setup_device(struct usb_hcd *hcd, struct usb_device *udev,
 	spin_unlock_irqrestore(&xhci->lock, flags);
 
 	/* ctrl tx can take up to 5 sec; XXX: need more time for xHC? */
-	timeleft = wait_for_completion_interruptible_timeout(
-			command->completion, XHCI_CMD_DEFAULT_TIMEOUT);
+	wait_for_completion(command->completion);
+
 	/* FIXME: From section 4.3.4: "Software shall be responsible for timing
 	 * the SetAddress() "recovery interval" required by USB and aborting the
 	 * command on a timeout.
 	 */
-	if (timeleft <= 0) {
-		xhci_warn(xhci, "%s while waiting for setup %s command\n",
-			  timeleft == 0 ? "Timeout" : "Signal", act);
-		/* cancel the address device command */
-		ret = xhci_cancel_cmd(xhci, NULL, command->command_trb);
-		if (ret < 0)
-			return ret;
-		return -ETIME;
-	}
-
 	switch (command->status) {
+	case COMP_CMD_ABORT:
+	case COMP_CMD_STOP:
+		xhci_warn(xhci, "Timeout while waiting for setup device command\n");
+		ret = -ETIME;
+		break;
 	case COMP_CTX_STATE:
 	case COMP_EBADSLT:
 		xhci_err(xhci, "Setup ERROR: setup %s command for slot %d.\n",
diff --git a/drivers/usb/host/xhci.h b/drivers/usb/host/xhci.h
index 217e5b0..f1a1906 100644
--- a/drivers/usb/host/xhci.h
+++ b/drivers/usb/host/xhci.h
@@ -1295,7 +1295,6 @@ struct xhci_td {
 
 /* command descriptor */
 struct xhci_cd {
-	struct list_head	cancel_cmd_list;
 	struct xhci_command	*command;
 	union xhci_trb		*cmd_trb;
 };
@@ -1479,9 +1478,10 @@ struct xhci_hcd {
 #define CMD_RING_STATE_RUNNING         (1 << 0)
 #define CMD_RING_STATE_ABORTED         (1 << 1)
 #define CMD_RING_STATE_STOPPED         (1 << 2)
-	struct list_head        cancel_cmd_list;
 	struct list_head        cmd_list;
 	unsigned int		cmd_ring_reserved_trbs;
+	struct timer_list	cmd_timer;
+	struct xhci_command	*current_cmd;
 	struct xhci_ring	*event_ring;
 	struct xhci_erst	erst;
 	/* Scratchpad */
@@ -1845,8 +1845,8 @@ void xhci_queue_config_ep_quirk(struct xhci_hcd *xhci,
 		unsigned int slot_id, unsigned int ep_index,
 		struct xhci_dequeue_state *deq_state);
 void xhci_stop_endpoint_command_watchdog(unsigned long arg);
-int xhci_cancel_cmd(struct xhci_hcd *xhci, struct xhci_command *command,
-		union xhci_trb *cmd_trb);
+void xhci_handle_command_timeout(unsigned long data);
+
 void xhci_ring_ep_doorbell(struct xhci_hcd *xhci, unsigned int slot_id,
 		unsigned int ep_index, unsigned int stream_id);
 
-- 
1.8.1.2


^ permalink raw reply related	[flat|nested] 7+ messages in thread

* Re: [RFCv3 1/4] xhci: Use command structures when queuing commands on the command ring
  2014-02-26 19:38 ` [RFCv3 1/4] xhci: Use command structures when queuing commands on the command ring Mathias Nyman
@ 2014-03-06 21:15   ` Sarah Sharp
  0 siblings, 0 replies; 7+ messages in thread
From: Sarah Sharp @ 2014-03-06 21:15 UTC (permalink / raw)
  To: Mathias Nyman; +Cc: linux-usb, dan.j.williams, linux-kernel

On Wed, Feb 26, 2014 at 09:38:47PM +0200, Mathias Nyman wrote:
> To create a global command queue we require that each command put on the
> command ring is submitted with a command structure.
> 
> Functions that queue commands and wait for completion need to allocate a command
> before submitting it, and free it once completed. The following command queuing
> functions need to be modified.
> 
> xhci_configure_endpoint()
> xhci_address_device()
> xhci_queue_slot_control()
> xhci_queue_stop_endpoint()
> xhci_queue_new_dequeue_state()
> xhci_queue_reset_ep()
> xhci_configure_endpoint()
> 
> xhci_configure_endpoint() could already be called with a command structure,
> and only xhci_check_maxpacket and xhci_check_bandwidth did not do so. These
> are changed and a command structure is now required. This change also simplifies
> the configure endpoint command completion handling and the "goto bandwidth_change"
> handling code can be removed.
> 
> In some cases the command queuing function is called in interrupt context.
> These commands needs to be allocated atomically, and they can't wait for
> completion. These commands will in this patch be freed directly after queuing,
> but freeing will be moved to the command completion event handler in a later
> patch once we get the global command queue up.(Just so that we won't leak
> memory in the middle of the patch set)

Mathias, I got the following stack trace while testing this code (along
with Hans' streams changes, although I suspect your code is the issue):

Mar  6 12:03:21 xanatos kernel: [ 1450.106055] usb 2-2: new SuperSpeed USB device number 2 using xhci_hcd
Mar  6 12:03:22 xanatos kernel: [ 1450.799410] usb 2-2: New USB device found, idVendor=2109, idProduct=0810
Mar  6 12:03:22 xanatos kernel: [ 1450.799419] usb 2-2: New USB device strings: Mfr=1, Product=2, SerialNumber=0
Mar  6 12:03:22 xanatos kernel: [ 1450.799423] usb 2-2: Product: 4-Port USB 3.0 Hub
Mar  6 12:03:22 xanatos kernel: [ 1450.799427] usb 2-2: Manufacturer: VIA Labs, Inc.
Mar  6 12:03:22 xanatos kernel: [ 1450.803206] hub 2-2:1.0: USB hub found
Mar  6 12:03:22 xanatos kernel: [ 1450.855282] hub 2-2:1.0: 4 ports detected
Mar  6 12:03:22 xanatos kernel: [ 1450.881379] BUG: sleeping function called from invalid context at mm/slub.c:965
Mar  6 12:03:22 xanatos kernel: [ 1450.881388] in_atomic(): 1, irqs_disabled(): 1, pid: 12761, name: kworker/0:0
Mar  6 12:03:22 xanatos kernel: [ 1450.881392] INFO: lockdep is turned off.
Mar  6 12:03:22 xanatos kernel: [ 1450.881396] irq event stamp: 0
Mar  6 12:03:22 xanatos kernel: [ 1450.881400] hardirqs last  enabled at (0): [<          (null)>]           (null)
Mar  6 12:03:22 xanatos kernel: [ 1450.881404] hardirqs last disabled at (0): [<ffffffff8104885c>] copy_process.part.24+0x60c/0x1be0
Mar  6 12:03:22 xanatos kernel: [ 1450.881416] softirqs last  enabled at (0): [<ffffffff8104885c>] copy_process.part.24+0x60c/0x1be0
Mar  6 12:03:22 xanatos kernel: [ 1450.881425] softirqs last disabled at (0): [<          (null)>]           (null)
Mar  6 12:03:22 xanatos kernel: [ 1450.881433] CPU: 0 PID: 12761 Comm: kworker/0:0 Not tainted 3.14.0-rc5+ #200
Mar  6 12:03:22 xanatos kernel: [ 1450.881436] Hardware name: LENOVO 2325AP7/2325AP7, BIOS G2ET82WW (2.02 ) 09/11/2012
Mar  6 12:03:22 xanatos kernel: [ 1450.881444] Workqueue: pm pm_runtime_work
Mar  6 12:03:22 xanatos kernel: [ 1450.881449]  0000000000000000 ffff880017933770 ffffffff81655c0d 0000000000000010
Mar  6 12:03:22 xanatos kernel: [ 1450.881457]  ffff880017933780 ffffffff81079e0f ffff8800179337c0 ffffffff81195f9e
Mar  6 12:03:22 xanatos kernel: [ 1450.881465]  ffffffffa05aa044 0000000000008010 0000000000000000 0000000000000000
Mar  6 12:03:22 xanatos kernel: [ 1450.881474] Call Trace:
Mar  6 12:03:22 xanatos kernel: [ 1450.881485]  [<ffffffff81655c0d>] dump_stack+0x4d/0x66
Mar  6 12:03:22 xanatos kernel: [ 1450.881493]  [<ffffffff81079e0f>] __might_sleep+0xdf/0x110
Mar  6 12:03:22 xanatos kernel: [ 1450.881502]  [<ffffffff81195f9e>] kmem_cache_alloc_trace+0x4e/0x190
Mar  6 12:03:22 xanatos kernel: [ 1450.881518]  [<ffffffffa05aa044>] ? xhci_alloc_command+0x44/0x150 [xhci_hcd]
Mar  6 12:03:22 xanatos kernel: [ 1450.881530]  [<ffffffffa05aa044>] xhci_alloc_command+0x44/0x150 [xhci_hcd]
Mar  6 12:03:22 xanatos kernel: [ 1450.881543]  [<ffffffffa05b1e48>] xhci_stop_device.constprop.9+0x88/0x1b0 [xhci_hcd]
Mar  6 12:03:22 xanatos kernel: [ 1450.881556]  [<ffffffffa05b2b46>] xhci_hub_control+0xa76/0x1420 [xhci_hcd]
Mar  6 12:03:22 xanatos kernel: [ 1450.881585]  [<ffffffffa003400e>] ? usb_hcd_link_urb_to_ep+0x1e/0xa0 [usbcore]
Mar  6 12:03:22 xanatos kernel: [ 1450.881596]  [<ffffffff811967cd>] ? __kmalloc+0xfd/0x1e0
Mar  6 12:03:22 xanatos kernel: [ 1450.881622]  [<ffffffffa00363cd>] usb_hcd_submit_urb+0x38d/0xaf0 [usbcore]
Mar  6 12:03:22 xanatos kernel: [ 1450.881632]  [<ffffffff8116554b>] ? is_kernel_percpu_address+0x4b/0x90
Mar  6 12:03:22 xanatos kernel: [ 1450.881645]  [<ffffffff810d47c6>] ? is_module_address+0x16/0x30
Mar  6 12:03:22 xanatos kernel: [ 1450.881668]  [<ffffffffa0037d8c>] usb_submit_urb+0x31c/0x5c0 [usbcore]
Mar  6 12:03:22 xanatos kernel: [ 1450.881695]  [<ffffffffa00387c4>] usb_start_wait_urb+0x74/0x190 [usbcore]
Mar  6 12:03:22 xanatos kernel: [ 1450.881722]  [<ffffffffa00389a5>] usb_control_msg+0xc5/0x110 [usbcore]
Mar  6 12:03:22 xanatos kernel: [ 1450.881744]  [<ffffffffa002bac8>] set_port_feature+0x48/0x50 [usbcore]
Mar  6 12:03:22 xanatos kernel: [ 1450.881764]  [<ffffffffa002f28b>] usb_port_suspend+0x15b/0x440 [usbcore]
Mar  6 12:03:22 xanatos kernel: [ 1450.881790]  [<ffffffffa00456ca>] generic_suspend+0x2a/0x40 [usbcore]
Mar  6 12:03:22 xanatos kernel: [ 1450.881815]  [<ffffffffa003bd3f>] usb_suspend_both+0x1bf/0x1e0 [usbcore]
Mar  6 12:03:22 xanatos kernel: [ 1450.881838]  [<ffffffffa003d103>] usb_runtime_suspend+0x33/0x70 [usbcore]
Mar  6 12:03:22 xanatos kernel: [ 1450.881859]  [<ffffffffa003d0d0>] ? usb_probe_interface+0x300/0x300 [usbcore]
Mar  6 12:03:22 xanatos kernel: [ 1450.881867]  [<ffffffff81448b52>] __rpm_callback+0x32/0x70
Mar  6 12:03:22 xanatos kernel: [ 1450.881872]  [<ffffffff81448bb4>] rpm_callback+0x24/0x80
Mar  6 12:03:22 xanatos kernel: [ 1450.881878]  [<ffffffff814490c6>] rpm_suspend+0x126/0x6e0
Mar  6 12:03:22 xanatos kernel: [ 1450.881885]  [<ffffffff8144a8dd>] __pm_runtime_suspend+0x5d/0xa0
Mar  6 12:03:22 xanatos kernel: [ 1450.881906]  [<ffffffffa003d160>] ? usb_runtime_resume+0x20/0x20 [usbcore]
Mar  6 12:03:22 xanatos kernel: [ 1450.881928]  [<ffffffffa003d18a>] usb_runtime_idle+0x2a/0x40 [usbcore]
Mar  6 12:03:22 xanatos kernel: [ 1450.881935]  [<ffffffff81448b52>] __rpm_callback+0x32/0x70
Mar  6 12:03:22 xanatos kernel: [ 1450.881942]  [<ffffffff8144995d>] rpm_idle+0x1ed/0x300
Mar  6 12:03:22 xanatos kernel: [ 1450.881948]  [<ffffffff8144aa5f>] pm_runtime_work+0xbf/0xd0
Mar  6 12:03:22 xanatos kernel: [ 1450.881956]  [<ffffffff81069184>] process_one_work+0x1f4/0x550
Mar  6 12:03:22 xanatos kernel: [ 1450.881962]  [<ffffffff81069122>] ? process_one_work+0x192/0x550
Mar  6 12:03:22 xanatos kernel: [ 1450.881968]  [<ffffffff81069ec1>] worker_thread+0x121/0x3a0
Mar  6 12:03:22 xanatos kernel: [ 1450.881975]  [<ffffffff81069da0>] ? manage_workers.isra.22+0x2a0/0x2a0
Mar  6 12:03:22 xanatos kernel: [ 1450.881982]  [<ffffffff8107084c>] kthread+0xfc/0x120
Mar  6 12:03:22 xanatos kernel: [ 1450.881990]  [<ffffffff81070750>] ? kthread_create_on_node+0x230/0x230
Mar  6 12:03:22 xanatos kernel: [ 1450.881999]  [<ffffffff816677ec>] ret_from_fork+0x7c/0xb0
Mar  6 12:03:22 xanatos kernel: [ 1450.882005]  [<ffffffff81070750>] ? kthread_create_on_node+0x230/0x230

Can you fix this in a second revision?  (Note, this does not take
priority over reverting those two patches that are causing regressions.
Let me know if you need any help with that.)

Sarah Sharp


> Signed-off-by: Mathias Nyman <mathias.nyman@linux.intel.com>
> ---
>  drivers/usb/host/xhci-hub.c  |  21 +++--
>  drivers/usb/host/xhci-ring.c | 105 ++++++++++++-----------
>  drivers/usb/host/xhci.c      | 194 ++++++++++++++++++++++++++++---------------
>  drivers/usb/host/xhci.h      |  31 +++----
>  4 files changed, 214 insertions(+), 137 deletions(-)
> 
> diff --git a/drivers/usb/host/xhci-hub.c b/drivers/usb/host/xhci-hub.c
> index 9992fbf..fb0f936 100644
> --- a/drivers/usb/host/xhci-hub.c
> +++ b/drivers/usb/host/xhci-hub.c
> @@ -20,7 +20,8 @@
>   * Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
>   */
>  
> -#include <linux/gfp.h>
> +
> +#include <linux/slab.h>
>  #include <asm/unaligned.h>
>  
>  #include "xhci.h"
> @@ -284,12 +285,22 @@ static int xhci_stop_device(struct xhci_hcd *xhci, int slot_id, int suspend)
>  
>  	spin_lock_irqsave(&xhci->lock, flags);
>  	for (i = LAST_EP_INDEX; i > 0; i--) {
> -		if (virt_dev->eps[i].ring && virt_dev->eps[i].ring->dequeue)
> -			xhci_queue_stop_endpoint(xhci, slot_id, i, suspend);
> +		if (virt_dev->eps[i].ring && virt_dev->eps[i].ring->dequeue) {
> +			struct xhci_command *command;
> +			command = xhci_alloc_command(xhci, false, false,
> +						     GFP_NOIO);

This GFP_NOIO should be GFP_ATOMIC, since you're holding the spinlock.
I'll fix that in your patch, since the code seems to be working fine
otherwise.

(Note, fixing this does not take priority over sending those two reverts
to Greg.  Let me know if you need help figuring out how to send a revert
patch.)

Sarah Sharp

> +			if (!command) {
> +				spin_unlock_irqrestore(&xhci->lock, flags);
> +				xhci_free_command(xhci, cmd);
> +				return -ENOMEM;
> +
> +			}
> +			xhci_queue_stop_endpoint(xhci, command, slot_id, i,
> +						 suspend);
> +		}
>  	}
> -	cmd->command_trb = xhci_find_next_enqueue(xhci->cmd_ring);
>  	list_add_tail(&cmd->cmd_list, &virt_dev->cmd_list);
> -	xhci_queue_stop_endpoint(xhci, slot_id, 0, suspend);
> +	xhci_queue_stop_endpoint(xhci, cmd, slot_id, 0, suspend);
>  	xhci_ring_cmd_db(xhci);
>  	spin_unlock_irqrestore(&xhci->lock, flags);
>  
> diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c
> index 0ed64eb..fa34c9b 100644
> --- a/drivers/usb/host/xhci-ring.c
> +++ b/drivers/usb/host/xhci-ring.c
> @@ -123,16 +123,6 @@ static int enqueue_is_link_trb(struct xhci_ring *ring)
>  	return TRB_TYPE_LINK_LE32(link->control);
>  }
>  
> -union xhci_trb *xhci_find_next_enqueue(struct xhci_ring *ring)
> -{
> -	/* Enqueue pointer can be left pointing to the link TRB,
> -	 * we must handle that
> -	 */
> -	if (TRB_TYPE_LINK_LE32(ring->enqueue->link.control))
> -		return ring->enq_seg->next->trbs;
> -	return ring->enqueue;
> -}
> -
>  /* Updates trb to point to the next TRB in the ring, and updates seg if the next
>   * TRB is in a new segment.  This does not skip over link TRBs, and it does not
>   * effect the ring dequeue or enqueue pointers.
> @@ -674,12 +664,14 @@ static void td_to_noop(struct xhci_hcd *xhci, struct xhci_ring *ep_ring,
>  	}
>  }
>  
> -static int queue_set_tr_deq(struct xhci_hcd *xhci, int slot_id,
> +static int queue_set_tr_deq(struct xhci_hcd *xhci,
> +		struct xhci_command *cmd, int slot_id,
>  		unsigned int ep_index, unsigned int stream_id,
>  		struct xhci_segment *deq_seg,
>  		union xhci_trb *deq_ptr, u32 cycle_state);
>  
>  void xhci_queue_new_dequeue_state(struct xhci_hcd *xhci,
> +		struct xhci_command *cmd,
>  		unsigned int slot_id, unsigned int ep_index,
>  		unsigned int stream_id,
>  		struct xhci_dequeue_state *deq_state)
> @@ -694,7 +686,7 @@ void xhci_queue_new_dequeue_state(struct xhci_hcd *xhci,
>  			deq_state->new_deq_ptr,
>  			(unsigned long long)xhci_trb_virt_to_dma(deq_state->new_deq_seg, deq_state->new_deq_ptr),
>  			deq_state->new_cycle_state);
> -	queue_set_tr_deq(xhci, slot_id, ep_index, stream_id,
> +	queue_set_tr_deq(xhci, cmd, slot_id, ep_index, stream_id,
>  			deq_state->new_deq_seg,
>  			deq_state->new_deq_ptr,
>  			(u32) deq_state->new_cycle_state);
> @@ -849,7 +841,9 @@ remove_finished_td:
>  
>  	/* If necessary, queue a Set Transfer Ring Dequeue Pointer command */
>  	if (deq_state.new_deq_ptr && deq_state.new_deq_seg) {
> -		xhci_queue_new_dequeue_state(xhci,
> +		struct xhci_command *command;
> +		command = xhci_alloc_command(xhci, false, false, GFP_ATOMIC);
> +		xhci_queue_new_dequeue_state(xhci, command,
>  				slot_id, ep_index,
>  				ep->stopped_td->urb->stream_id,
>  				&deq_state);
> @@ -1174,9 +1168,11 @@ static void xhci_handle_cmd_reset_ep(struct xhci_hcd *xhci, int slot_id,
>  	 * because the HW can't handle two commands being queued in a row.
>  	 */
>  	if (xhci->quirks & XHCI_RESET_EP_QUIRK) {
> +		struct xhci_command *command;
> +		command = xhci_alloc_command(xhci, false, false, GFP_ATOMIC);
>  		xhci_dbg_trace(xhci, trace_xhci_dbg_quirks,
>  				"Queueing configure endpoint command");
> -		xhci_queue_configure_endpoint(xhci,
> +		xhci_queue_configure_endpoint(xhci, command,
>  				xhci->devs[slot_id]->in_ctx->dma, slot_id,
>  				false);
>  		xhci_ring_cmd_db(xhci);
> @@ -1433,7 +1429,7 @@ static void xhci_handle_cmd_config_ep(struct xhci_hcd *xhci, int slot_id,
>  			add_flags - SLOT_FLAG == drop_flags) {
>  		ep_state = virt_dev->eps[ep_index].ep_state;
>  		if (!(ep_state & EP_HALTED))
> -			goto bandwidth_change;
> +			return;
>  		xhci_dbg_trace(xhci, trace_xhci_dbg_quirks,
>  				"Completed config ep cmd - "
>  				"last ep index = %d, state = %d",
> @@ -1443,11 +1439,6 @@ static void xhci_handle_cmd_config_ep(struct xhci_hcd *xhci, int slot_id,
>  		ring_doorbell_for_active_rings(xhci, slot_id, ep_index);
>  		return;
>  	}
> -bandwidth_change:
> -	xhci_dbg_trace(xhci,  trace_xhci_dbg_context_change,
> -			"Completed config ep cmd");
> -	virt_dev->cmd_status = cmd_comp_code;
> -	complete(&virt_dev->cmd_completion);
>  	return;
>  }
>  
> @@ -1906,12 +1897,16 @@ static void xhci_cleanup_halted_endpoint(struct xhci_hcd *xhci,
>  		struct xhci_td *td, union xhci_trb *event_trb)
>  {
>  	struct xhci_virt_ep *ep = &xhci->devs[slot_id]->eps[ep_index];
> +	struct xhci_command *command;
> +	command = xhci_alloc_command(xhci, false, false, GFP_ATOMIC);
> +	if (!command)
> +		return;
>  	ep->ep_state |= EP_HALTED;
>  	ep->stopped_td = td;
>  	ep->stopped_trb = event_trb;
>  	ep->stopped_stream = stream_id;
>  
> -	xhci_queue_reset_ep(xhci, slot_id, ep_index);
> +	xhci_queue_reset_ep(xhci, command, slot_id, ep_index);
>  	xhci_cleanup_stalled_ring(xhci, td->urb->dev, ep_index);
>  
>  	ep->stopped_td = NULL;
> @@ -2626,7 +2621,7 @@ static int handle_tx_event(struct xhci_hcd *xhci,
>  				 * successful event after a short transfer.
>  				 * Ignore it.
>  				 */
> -				if ((xhci->quirks & XHCI_SPURIOUS_SUCCESS) && 
> +				if ((xhci->quirks & XHCI_SPURIOUS_SUCCESS) &&
>  						ep_ring->last_td_was_short) {
>  					ep_ring->last_td_was_short = false;
>  					ret = 0;
> @@ -3968,8 +3963,9 @@ int xhci_queue_isoc_tx_prepare(struct xhci_hcd *xhci, gfp_t mem_flags,
>   * Don't decrement xhci->cmd_ring_reserved_trbs after we've queued the TRB
>   * because the command event handler may want to resubmit a failed command.
>   */
> -static int queue_command(struct xhci_hcd *xhci, u32 field1, u32 field2,
> -		u32 field3, u32 field4, bool command_must_succeed)
> +static int queue_command(struct xhci_hcd *xhci, struct xhci_command *cmd,
> +			 u32 field1, u32 field2,
> +			 u32 field3, u32 field4, bool command_must_succeed)
>  {
>  	int reserved_trbs = xhci->cmd_ring_reserved_trbs;
>  	int ret;
> @@ -3986,57 +3982,65 @@ static int queue_command(struct xhci_hcd *xhci, u32 field1, u32 field2,
>  					"unfailable commands failed.\n");
>  		return ret;
>  	}
> +	if (cmd->completion)
> +		cmd->command_trb = xhci->cmd_ring->enqueue;
> +	else
> +		kfree(cmd);
> +
>  	queue_trb(xhci, xhci->cmd_ring, false, field1, field2, field3,
>  			field4 | xhci->cmd_ring->cycle_state);
>  	return 0;
>  }
>  
>  /* Queue a slot enable or disable request on the command ring */
> -int xhci_queue_slot_control(struct xhci_hcd *xhci, u32 trb_type, u32 slot_id)
> +int xhci_queue_slot_control(struct xhci_hcd *xhci, struct xhci_command *cmd,
> +		u32 trb_type, u32 slot_id)
>  {
> -	return queue_command(xhci, 0, 0, 0,
> +	return queue_command(xhci, cmd, 0, 0, 0,
>  			TRB_TYPE(trb_type) | SLOT_ID_FOR_TRB(slot_id), false);
>  }
>  
>  /* Queue an address device command TRB */
> -int xhci_queue_address_device(struct xhci_hcd *xhci, dma_addr_t in_ctx_ptr,
> -			      u32 slot_id, enum xhci_setup_dev setup)
> +int xhci_queue_address_device(struct xhci_hcd *xhci, struct xhci_command *cmd,
> +		dma_addr_t in_ctx_ptr, u32 slot_id, enum xhci_setup_dev setup)
>  {
> -	return queue_command(xhci, lower_32_bits(in_ctx_ptr),
> +	return queue_command(xhci, cmd, lower_32_bits(in_ctx_ptr),
>  			upper_32_bits(in_ctx_ptr), 0,
>  			TRB_TYPE(TRB_ADDR_DEV) | SLOT_ID_FOR_TRB(slot_id)
>  			| (setup == SETUP_CONTEXT_ONLY ? TRB_BSR : 0), false);
>  }
>  
> -int xhci_queue_vendor_command(struct xhci_hcd *xhci,
> +int xhci_queue_vendor_command(struct xhci_hcd *xhci, struct xhci_command *cmd,
>  		u32 field1, u32 field2, u32 field3, u32 field4)
>  {
> -	return queue_command(xhci, field1, field2, field3, field4, false);
> +	return queue_command(xhci, cmd, field1, field2, field3, field4, false);
>  }
>  
>  /* Queue a reset device command TRB */
> -int xhci_queue_reset_device(struct xhci_hcd *xhci, u32 slot_id)
> +int xhci_queue_reset_device(struct xhci_hcd *xhci, struct xhci_command *cmd,
> +		u32 slot_id)
>  {
> -	return queue_command(xhci, 0, 0, 0,
> +	return queue_command(xhci, cmd, 0, 0, 0,
>  			TRB_TYPE(TRB_RESET_DEV) | SLOT_ID_FOR_TRB(slot_id),
>  			false);
>  }
>  
>  /* Queue a configure endpoint command TRB */
> -int xhci_queue_configure_endpoint(struct xhci_hcd *xhci, dma_addr_t in_ctx_ptr,
> +int xhci_queue_configure_endpoint(struct xhci_hcd *xhci,
> +		struct xhci_command *cmd, dma_addr_t in_ctx_ptr,
>  		u32 slot_id, bool command_must_succeed)
>  {
> -	return queue_command(xhci, lower_32_bits(in_ctx_ptr),
> +	return queue_command(xhci, cmd, lower_32_bits(in_ctx_ptr),
>  			upper_32_bits(in_ctx_ptr), 0,
>  			TRB_TYPE(TRB_CONFIG_EP) | SLOT_ID_FOR_TRB(slot_id),
>  			command_must_succeed);
>  }
>  
>  /* Queue an evaluate context command TRB */
> -int xhci_queue_evaluate_context(struct xhci_hcd *xhci, dma_addr_t in_ctx_ptr,
> -		u32 slot_id, bool command_must_succeed)
> +int xhci_queue_evaluate_context(struct xhci_hcd *xhci, struct xhci_command *cmd,
> +		dma_addr_t in_ctx_ptr, u32 slot_id, bool command_must_succeed)
>  {
> -	return queue_command(xhci, lower_32_bits(in_ctx_ptr),
> +	return queue_command(xhci, cmd, lower_32_bits(in_ctx_ptr),
>  			upper_32_bits(in_ctx_ptr), 0,
>  			TRB_TYPE(TRB_EVAL_CONTEXT) | SLOT_ID_FOR_TRB(slot_id),
>  			command_must_succeed);
> @@ -4046,25 +4050,26 @@ int xhci_queue_evaluate_context(struct xhci_hcd *xhci, dma_addr_t in_ctx_ptr,
>   * Suspend is set to indicate "Stop Endpoint Command" is being issued to stop
>   * activity on an endpoint that is about to be suspended.
>   */
> -int xhci_queue_stop_endpoint(struct xhci_hcd *xhci, int slot_id,
> -		unsigned int ep_index, int suspend)
> +int xhci_queue_stop_endpoint(struct xhci_hcd *xhci, struct xhci_command *cmd,
> +			     int slot_id, unsigned int ep_index, int suspend)
>  {
>  	u32 trb_slot_id = SLOT_ID_FOR_TRB(slot_id);
>  	u32 trb_ep_index = EP_ID_FOR_TRB(ep_index);
>  	u32 type = TRB_TYPE(TRB_STOP_RING);
>  	u32 trb_suspend = SUSPEND_PORT_FOR_TRB(suspend);
>  
> -	return queue_command(xhci, 0, 0, 0,
> +	return queue_command(xhci, cmd, 0, 0, 0,
>  			trb_slot_id | trb_ep_index | type | trb_suspend, false);
>  }
>  
>  /* Set Transfer Ring Dequeue Pointer command.
>   * This should not be used for endpoints that have streams enabled.
>   */
> -static int queue_set_tr_deq(struct xhci_hcd *xhci, int slot_id,
> -		unsigned int ep_index, unsigned int stream_id,
> -		struct xhci_segment *deq_seg,
> -		union xhci_trb *deq_ptr, u32 cycle_state)
> +static int queue_set_tr_deq(struct xhci_hcd *xhci, struct xhci_command *cmd,
> +			int slot_id,
> +			unsigned int ep_index, unsigned int stream_id,
> +			struct xhci_segment *deq_seg,
> +			union xhci_trb *deq_ptr, u32 cycle_state)
>  {
>  	dma_addr_t addr;
>  	u32 trb_slot_id = SLOT_ID_FOR_TRB(slot_id);
> @@ -4088,18 +4093,18 @@ static int queue_set_tr_deq(struct xhci_hcd *xhci, int slot_id,
>  	}
>  	ep->queued_deq_seg = deq_seg;
>  	ep->queued_deq_ptr = deq_ptr;
> -	return queue_command(xhci, lower_32_bits(addr) | cycle_state,
> +	return queue_command(xhci, cmd, lower_32_bits(addr) | cycle_state,
>  			upper_32_bits(addr), trb_stream_id,
>  			trb_slot_id | trb_ep_index | type, false);
>  }
>  
> -int xhci_queue_reset_ep(struct xhci_hcd *xhci, int slot_id,
> -		unsigned int ep_index)
> +int xhci_queue_reset_ep(struct xhci_hcd *xhci, struct xhci_command *cmd,
> +			int slot_id, unsigned int ep_index)
>  {
>  	u32 trb_slot_id = SLOT_ID_FOR_TRB(slot_id);
>  	u32 trb_ep_index = EP_ID_FOR_TRB(ep_index);
>  	u32 type = TRB_TYPE(TRB_RESET_EP);
>  
> -	return queue_command(xhci, 0, 0, 0, trb_slot_id | trb_ep_index | type,
> -			false);
> +	return queue_command(xhci, cmd, 0, 0, 0,
> +			     trb_slot_id | trb_ep_index | type, false);
>  }
> diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c
> index 6fe577d..8bf2aa3 100644
> --- a/drivers/usb/host/xhci.c
> +++ b/drivers/usb/host/xhci.c
> @@ -637,10 +637,14 @@ int xhci_run(struct usb_hcd *hcd)
>  	writel(ER_IRQ_ENABLE(temp), &xhci->ir_set->irq_pending);
>  	xhci_print_ir_set(xhci, 0);
>  
> -	if (xhci->quirks & XHCI_NEC_HOST)
> -		xhci_queue_vendor_command(xhci, 0, 0, 0,
> +	if (xhci->quirks & XHCI_NEC_HOST) {
> +		struct xhci_command *command;
> +		command = xhci_alloc_command(xhci, false, false, GFP_KERNEL);
> +		if (!command)
> +			return -ENOMEM;
> +		xhci_queue_vendor_command(xhci, command, 0, 0, 0,
>  				TRB_TYPE(TRB_NEC_GET_FW));
> -
> +	}
>  	xhci_dbg_trace(xhci, trace_xhci_dbg_init,
>  			"Finished xhci_run for USB2 roothub");
>  	return 0;
> @@ -1183,10 +1187,10 @@ static int xhci_configure_endpoint(struct xhci_hcd *xhci,
>  static int xhci_check_maxpacket(struct xhci_hcd *xhci, unsigned int slot_id,
>  		unsigned int ep_index, struct urb *urb)
>  {
> -	struct xhci_container_ctx *in_ctx;
>  	struct xhci_container_ctx *out_ctx;
>  	struct xhci_input_control_ctx *ctrl_ctx;
>  	struct xhci_ep_ctx *ep_ctx;
> +	struct xhci_command *command;
>  	int max_packet_size;
>  	int hw_max_packet_size;
>  	int ret = 0;
> @@ -1211,18 +1215,24 @@ static int xhci_check_maxpacket(struct xhci_hcd *xhci, unsigned int slot_id,
>  		/* FIXME: This won't work if a non-default control endpoint
>  		 * changes max packet sizes.
>  		 */
> -		in_ctx = xhci->devs[slot_id]->in_ctx;
> -		ctrl_ctx = xhci_get_input_control_ctx(xhci, in_ctx);
> +
> +		command = xhci_alloc_command(xhci, false, true, GFP_KERNEL);
> +		if (!command)
> +			return -ENOMEM;
> +
> +		command->in_ctx = xhci->devs[slot_id]->in_ctx;
> +		ctrl_ctx = xhci_get_input_control_ctx(xhci, command->in_ctx);
>  		if (!ctrl_ctx) {
>  			xhci_warn(xhci, "%s: Could not get input context, bad type.\n",
>  					__func__);
> -			return -ENOMEM;
> +			ret = -ENOMEM;
> +			goto command_cleanup;
>  		}
>  		/* Set up the modified control endpoint 0 */
>  		xhci_endpoint_copy(xhci, xhci->devs[slot_id]->in_ctx,
>  				xhci->devs[slot_id]->out_ctx, ep_index);
>  
> -		ep_ctx = xhci_get_ep_ctx(xhci, in_ctx, ep_index);
> +		ep_ctx = xhci_get_ep_ctx(xhci, command->in_ctx, ep_index);
>  		ep_ctx->ep_info2 &= cpu_to_le32(~MAX_PACKET_MASK);
>  		ep_ctx->ep_info2 |= cpu_to_le32(MAX_PACKET(max_packet_size));
>  
> @@ -1230,17 +1240,20 @@ static int xhci_check_maxpacket(struct xhci_hcd *xhci, unsigned int slot_id,
>  		ctrl_ctx->drop_flags = 0;
>  
>  		xhci_dbg(xhci, "Slot %d input context\n", slot_id);
> -		xhci_dbg_ctx(xhci, in_ctx, ep_index);
> +		xhci_dbg_ctx(xhci, command->in_ctx, ep_index);
>  		xhci_dbg(xhci, "Slot %d output context\n", slot_id);
>  		xhci_dbg_ctx(xhci, out_ctx, ep_index);
>  
> -		ret = xhci_configure_endpoint(xhci, urb->dev, NULL,
> +		ret = xhci_configure_endpoint(xhci, urb->dev, command,
>  				true, false);
>  
>  		/* Clean up the input context for later use by bandwidth
>  		 * functions.
>  		 */
>  		ctrl_ctx->add_flags = cpu_to_le32(SLOT_FLAG);
> +command_cleanup:
> +		kfree(command->completion);
> +		kfree(command);
>  	}
>  	return ret;
>  }
> @@ -1461,6 +1474,7 @@ int xhci_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status)
>  	unsigned int ep_index;
>  	struct xhci_ring *ep_ring;
>  	struct xhci_virt_ep *ep;
> +	struct xhci_command *command;
>  
>  	xhci = hcd_to_xhci(hcd);
>  	spin_lock_irqsave(&xhci->lock, flags);
> @@ -1530,12 +1544,14 @@ int xhci_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status)
>  	 * the first cancellation to be handled.
>  	 */
>  	if (!(ep->ep_state & EP_HALT_PENDING)) {
> +		command = xhci_alloc_command(xhci, false, false, GFP_ATOMIC);
>  		ep->ep_state |= EP_HALT_PENDING;
>  		ep->stop_cmds_pending++;
>  		ep->stop_cmd_timer.expires = jiffies +
>  			XHCI_STOP_EP_CMD_TIMEOUT * HZ;
>  		add_timer(&ep->stop_cmd_timer);
> -		xhci_queue_stop_endpoint(xhci, urb->dev->slot_id, ep_index, 0);
> +		xhci_queue_stop_endpoint(xhci, command, urb->dev->slot_id,
> +					 ep_index, 0);
>  		xhci_ring_cmd_db(xhci);
>  	}
>  done:
> @@ -2572,21 +2588,16 @@ static int xhci_configure_endpoint(struct xhci_hcd *xhci,
>  	int ret;
>  	int timeleft;
>  	unsigned long flags;
> -	struct xhci_container_ctx *in_ctx;
>  	struct xhci_input_control_ctx *ctrl_ctx;
> -	struct completion *cmd_completion;
> -	u32 *cmd_status;
>  	struct xhci_virt_device *virt_dev;
> -	union xhci_trb *cmd_trb;
> +
> +	if (!command)
> +		return -EINVAL;
>  
>  	spin_lock_irqsave(&xhci->lock, flags);
>  	virt_dev = xhci->devs[udev->slot_id];
>  
> -	if (command)
> -		in_ctx = command->in_ctx;
> -	else
> -		in_ctx = virt_dev->in_ctx;
> -	ctrl_ctx = xhci_get_input_control_ctx(xhci, in_ctx);
> +	ctrl_ctx = xhci_get_input_control_ctx(xhci, command->in_ctx);
>  	if (!ctrl_ctx) {
>  		spin_unlock_irqrestore(&xhci->lock, flags);
>  		xhci_warn(xhci, "%s: Could not get input context, bad type.\n",
> @@ -2603,7 +2614,7 @@ static int xhci_configure_endpoint(struct xhci_hcd *xhci,
>  		return -ENOMEM;
>  	}
>  	if ((xhci->quirks & XHCI_SW_BW_CHECKING) &&
> -			xhci_reserve_bandwidth(xhci, virt_dev, in_ctx)) {
> +	    xhci_reserve_bandwidth(xhci, virt_dev, command->in_ctx)) {
>  		if ((xhci->quirks & XHCI_EP_LIMIT_QUIRK))
>  			xhci_free_host_resources(xhci, ctrl_ctx);
>  		spin_unlock_irqrestore(&xhci->lock, flags);
> @@ -2611,27 +2622,18 @@ static int xhci_configure_endpoint(struct xhci_hcd *xhci,
>  		return -ENOMEM;
>  	}
>  
> -	if (command) {
> -		cmd_completion = command->completion;
> -		cmd_status = &command->status;
> -		command->command_trb = xhci_find_next_enqueue(xhci->cmd_ring);
> -		list_add_tail(&command->cmd_list, &virt_dev->cmd_list);
> -	} else {
> -		cmd_completion = &virt_dev->cmd_completion;
> -		cmd_status = &virt_dev->cmd_status;
> -	}
> -	init_completion(cmd_completion);
> +	list_add_tail(&command->cmd_list, &virt_dev->cmd_list);
>  
> -	cmd_trb = xhci_find_next_enqueue(xhci->cmd_ring);
>  	if (!ctx_change)
> -		ret = xhci_queue_configure_endpoint(xhci, in_ctx->dma,
> +		ret = xhci_queue_configure_endpoint(xhci, command,
> +				command->in_ctx->dma,
>  				udev->slot_id, must_succeed);
>  	else
> -		ret = xhci_queue_evaluate_context(xhci, in_ctx->dma,
> +		ret = xhci_queue_evaluate_context(xhci, command,
> +				command->in_ctx->dma,
>  				udev->slot_id, must_succeed);
>  	if (ret < 0) {
> -		if (command)
> -			list_del(&command->cmd_list);
> +		list_del(&command->cmd_list);
>  		if ((xhci->quirks & XHCI_EP_LIMIT_QUIRK))
>  			xhci_free_host_resources(xhci, ctrl_ctx);
>  		spin_unlock_irqrestore(&xhci->lock, flags);
> @@ -2644,7 +2646,7 @@ static int xhci_configure_endpoint(struct xhci_hcd *xhci,
>  
>  	/* Wait for the configure endpoint command to complete */
>  	timeleft = wait_for_completion_interruptible_timeout(
> -			cmd_completion,
> +			command->completion,
>  			XHCI_CMD_DEFAULT_TIMEOUT);
>  	if (timeleft <= 0) {
>  		xhci_warn(xhci, "%s while waiting for %s command\n",
> @@ -2653,16 +2655,18 @@ static int xhci_configure_endpoint(struct xhci_hcd *xhci,
>  					"configure endpoint" :
>  					"evaluate context");
>  		/* cancel the configure endpoint command */
> -		ret = xhci_cancel_cmd(xhci, command, cmd_trb);
> +		ret = xhci_cancel_cmd(xhci, command, command->command_trb);
>  		if (ret < 0)
>  			return ret;
>  		return -ETIME;
>  	}
>  
>  	if (!ctx_change)
> -		ret = xhci_configure_endpoint_result(xhci, udev, cmd_status);
> +		ret = xhci_configure_endpoint_result(xhci, udev,
> +						     &command->status);
>  	else
> -		ret = xhci_evaluate_context_result(xhci, udev, cmd_status);
> +		ret = xhci_evaluate_context_result(xhci, udev,
> +						   &command->status);
>  
>  	if ((xhci->quirks & XHCI_EP_LIMIT_QUIRK)) {
>  		spin_lock_irqsave(&xhci->lock, flags);
> @@ -2696,6 +2700,7 @@ int xhci_check_bandwidth(struct usb_hcd *hcd, struct usb_device *udev)
>  	struct xhci_virt_device	*virt_dev;
>  	struct xhci_input_control_ctx *ctrl_ctx;
>  	struct xhci_slot_ctx *slot_ctx;
> +	struct xhci_command *command;
>  
>  	ret = xhci_check_args(hcd, udev, NULL, 0, true, __func__);
>  	if (ret <= 0)
> @@ -2707,12 +2712,19 @@ int xhci_check_bandwidth(struct usb_hcd *hcd, struct usb_device *udev)
>  	xhci_dbg(xhci, "%s called for udev %p\n", __func__, udev);
>  	virt_dev = xhci->devs[udev->slot_id];
>  
> +	command = xhci_alloc_command(xhci, false, true, GFP_KERNEL);
> +	if (!command)
> +		return -ENOMEM;
> +
> +	command->in_ctx = virt_dev->in_ctx;
> +
>  	/* See section 4.6.6 - A0 = 1; A1 = D0 = D1 = 0 */
> -	ctrl_ctx = xhci_get_input_control_ctx(xhci, virt_dev->in_ctx);
> +	ctrl_ctx = xhci_get_input_control_ctx(xhci, command->in_ctx);
>  	if (!ctrl_ctx) {
>  		xhci_warn(xhci, "%s: Could not get input context, bad type.\n",
>  				__func__);
> -		return -ENOMEM;
> +		ret = -ENOMEM;
> +		goto command_cleanup;
>  	}
>  	ctrl_ctx->add_flags |= cpu_to_le32(SLOT_FLAG);
>  	ctrl_ctx->add_flags &= cpu_to_le32(~EP0_FLAG);
> @@ -2720,20 +2732,20 @@ int xhci_check_bandwidth(struct usb_hcd *hcd, struct usb_device *udev)
>  
>  	/* Don't issue the command if there's no endpoints to update. */
>  	if (ctrl_ctx->add_flags == cpu_to_le32(SLOT_FLAG) &&
> -			ctrl_ctx->drop_flags == 0)
> -		return 0;
> -
> +	    ctrl_ctx->drop_flags == 0) {
> +		ret = 0;
> +		goto command_cleanup;
> +	}
>  	xhci_dbg(xhci, "New Input Control Context:\n");
>  	slot_ctx = xhci_get_slot_ctx(xhci, virt_dev->in_ctx);
>  	xhci_dbg_ctx(xhci, virt_dev->in_ctx,
>  		     LAST_CTX_TO_EP_NUM(le32_to_cpu(slot_ctx->dev_info)));
>  
> -	ret = xhci_configure_endpoint(xhci, udev, NULL,
> +	ret = xhci_configure_endpoint(xhci, udev, command,
>  			false, false);
> -	if (ret) {
> +	if (ret)
>  		/* Callee should call reset_bandwidth() */
> -		return ret;
> -	}
> +		goto command_cleanup;
>  
>  	xhci_dbg(xhci, "Output context after successful config ep cmd:\n");
>  	xhci_dbg_ctx(xhci, virt_dev->out_ctx,
> @@ -2762,6 +2774,9 @@ int xhci_check_bandwidth(struct usb_hcd *hcd, struct usb_device *udev)
>  		virt_dev->eps[i].ring = virt_dev->eps[i].new_ring;
>  		virt_dev->eps[i].new_ring = NULL;
>  	}
> +command_cleanup:
> +	kfree(command->completion);
> +	kfree(command);
>  
>  	return ret;
>  }
> @@ -2863,9 +2878,14 @@ void xhci_cleanup_stalled_ring(struct xhci_hcd *xhci,
>  	 * issue a configure endpoint command later.
>  	 */
>  	if (!(xhci->quirks & XHCI_RESET_EP_QUIRK)) {
> +		struct xhci_command *command;
> +		/* Can't sleep if we're called from cleanup_halted_endpoint() */
> +		command = xhci_alloc_command(xhci, false, false, GFP_ATOMIC);
> +		if (!command)
> +			return;
>  		xhci_dbg_trace(xhci, trace_xhci_dbg_reset_ep,
>  				"Queueing new dequeue state");
> -		xhci_queue_new_dequeue_state(xhci, udev->slot_id,
> +		xhci_queue_new_dequeue_state(xhci, command, udev->slot_id,
>  				ep_index, ep->stopped_stream, &deq_state);
>  	} else {
>  		/* Better hope no one uses the input context between now and the
> @@ -2896,6 +2916,7 @@ void xhci_endpoint_reset(struct usb_hcd *hcd,
>  	unsigned long flags;
>  	int ret;
>  	struct xhci_virt_ep *virt_ep;
> +	struct xhci_command *command;
>  
>  	xhci = hcd_to_xhci(hcd);
>  	udev = (struct usb_device *) ep->hcpriv;
> @@ -2918,10 +2939,14 @@ void xhci_endpoint_reset(struct usb_hcd *hcd,
>  		return;
>  	}
>  
> +	command = xhci_alloc_command(xhci, false, false, GFP_ATOMIC);
> +	if (!command)
> +		return;
> +
>  	xhci_dbg_trace(xhci, trace_xhci_dbg_reset_ep,
>  			"Queueing reset endpoint command");
>  	spin_lock_irqsave(&xhci->lock, flags);
> -	ret = xhci_queue_reset_ep(xhci, udev->slot_id, ep_index);
> +	ret = xhci_queue_reset_ep(xhci, command, udev->slot_id, ep_index);
>  	/*
>  	 * Can't change the ring dequeue pointer until it's transitioned to the
>  	 * stopped state, which is only upon a successful reset endpoint
> @@ -3447,10 +3472,9 @@ int xhci_discover_or_reset_device(struct usb_hcd *hcd, struct usb_device *udev)
>  
>  	/* Attempt to submit the Reset Device command to the command ring */
>  	spin_lock_irqsave(&xhci->lock, flags);
> -	reset_device_cmd->command_trb = xhci_find_next_enqueue(xhci->cmd_ring);
>  
>  	list_add_tail(&reset_device_cmd->cmd_list, &virt_dev->cmd_list);
> -	ret = xhci_queue_reset_device(xhci, slot_id);
> +	ret = xhci_queue_reset_device(xhci, reset_device_cmd, slot_id);
>  	if (ret) {
>  		xhci_dbg(xhci, "FIXME: allocate a command ring segment\n");
>  		list_del(&reset_device_cmd->cmd_list);
> @@ -3561,6 +3585,11 @@ void xhci_free_dev(struct usb_hcd *hcd, struct usb_device *udev)
>  	unsigned long flags;
>  	u32 state;
>  	int i, ret;
> +	struct xhci_command *command;
> +
> +	command = xhci_alloc_command(xhci, false, false, GFP_KERNEL);
> +	if (!command)
> +		return;
>  
>  #ifndef CONFIG_USB_DEFAULT_PERSIST
>  	/*
> @@ -3576,8 +3605,10 @@ void xhci_free_dev(struct usb_hcd *hcd, struct usb_device *udev)
>  	/* If the host is halted due to driver unload, we still need to free the
>  	 * device.
>  	 */
> -	if (ret <= 0 && ret != -ENODEV)
> +	if (ret <= 0 && ret != -ENODEV) {
> +		kfree(command);
>  		return;
> +	}
>  
>  	virt_dev = xhci->devs[udev->slot_id];
>  
> @@ -3594,16 +3625,19 @@ void xhci_free_dev(struct usb_hcd *hcd, struct usb_device *udev)
>  			(xhci->xhc_state & XHCI_STATE_HALTED)) {
>  		xhci_free_virt_device(xhci, udev->slot_id);
>  		spin_unlock_irqrestore(&xhci->lock, flags);
> +		kfree(command);
>  		return;
>  	}
>  
> -	if (xhci_queue_slot_control(xhci, TRB_DISABLE_SLOT, udev->slot_id)) {
> +	if (xhci_queue_slot_control(xhci, command, TRB_DISABLE_SLOT,
> +				    udev->slot_id)) {
>  		spin_unlock_irqrestore(&xhci->lock, flags);
>  		xhci_dbg(xhci, "FIXME: allocate a command ring segment\n");
>  		return;
>  	}
>  	xhci_ring_cmd_db(xhci);
>  	spin_unlock_irqrestore(&xhci->lock, flags);
> +
>  	/*
>  	 * Event command completion handler will free any data structures
>  	 * associated with the slot.  XXX Can free sleep?
> @@ -3643,31 +3677,40 @@ int xhci_alloc_dev(struct usb_hcd *hcd, struct usb_device *udev)
>  	unsigned long flags;
>  	int timeleft;
>  	int ret;
> -	union xhci_trb *cmd_trb;
> +	struct xhci_command *command;
> +
> +	command = xhci_alloc_command(xhci, false, false, GFP_KERNEL);
> +	if (!command)
> +		return 0;
>  
>  	spin_lock_irqsave(&xhci->lock, flags);
> -	cmd_trb = xhci_find_next_enqueue(xhci->cmd_ring);
> -	ret = xhci_queue_slot_control(xhci, TRB_ENABLE_SLOT, 0);
> +	command->completion = &xhci->addr_dev;
> +	ret = xhci_queue_slot_control(xhci, command, TRB_ENABLE_SLOT, 0);
>  	if (ret) {
>  		spin_unlock_irqrestore(&xhci->lock, flags);
>  		xhci_dbg(xhci, "FIXME: allocate a command ring segment\n");
> +		kfree(command);
>  		return 0;
>  	}
>  	xhci_ring_cmd_db(xhci);
>  	spin_unlock_irqrestore(&xhci->lock, flags);
>  
>  	/* XXX: how much time for xHC slot assignment? */
> -	timeleft = wait_for_completion_interruptible_timeout(&xhci->addr_dev,
> +	timeleft = wait_for_completion_interruptible_timeout(
> +			command->completion,
>  			XHCI_CMD_DEFAULT_TIMEOUT);
>  	if (timeleft <= 0) {
>  		xhci_warn(xhci, "%s while waiting for a slot\n",
>  				timeleft == 0 ? "Timeout" : "Signal");
>  		/* cancel the enable slot request */
> -		return xhci_cancel_cmd(xhci, NULL, cmd_trb);
> +		ret = xhci_cancel_cmd(xhci, NULL, command->command_trb);
> +		kfree(command);
> +		return ret;
>  	}
>  
>  	if (!xhci->slot_id) {
>  		xhci_err(xhci, "Error while assigning device slot ID\n");
> +		kfree(command);
>  		return 0;
>  	}
>  
> @@ -3702,6 +3745,8 @@ int xhci_alloc_dev(struct usb_hcd *hcd, struct usb_device *udev)
>  		pm_runtime_get_noresume(hcd->self.controller);
>  #endif
>  
> +
> +	kfree(command);
>  	/* Is this a LS or FS device under a HS hub? */
>  	/* Hub or peripherial? */
>  	return 1;
> @@ -3709,7 +3754,10 @@ int xhci_alloc_dev(struct usb_hcd *hcd, struct usb_device *udev)
>  disable_slot:
>  	/* Disable slot, if we can do it without mem alloc */
>  	spin_lock_irqsave(&xhci->lock, flags);
> -	if (!xhci_queue_slot_control(xhci, TRB_DISABLE_SLOT, udev->slot_id))
> +	command->completion = NULL;
> +	command->status = 0;
> +	if (!xhci_queue_slot_control(xhci, command, TRB_DISABLE_SLOT,
> +				     udev->slot_id))
>  		xhci_ring_cmd_db(xhci);
>  	spin_unlock_irqrestore(&xhci->lock, flags);
>  	return 0;
> @@ -3733,7 +3781,7 @@ static int xhci_setup_device(struct usb_hcd *hcd, struct usb_device *udev,
>  	struct xhci_slot_ctx *slot_ctx;
>  	struct xhci_input_control_ctx *ctrl_ctx;
>  	u64 temp_64;
> -	union xhci_trb *cmd_trb;
> +	struct xhci_command *command;
>  
>  	if (!udev->slot_id) {
>  		xhci_dbg_trace(xhci, trace_xhci_dbg_address,
> @@ -3754,11 +3802,19 @@ static int xhci_setup_device(struct usb_hcd *hcd, struct usb_device *udev,
>  		return -EINVAL;
>  	}
>  
> +	command = xhci_alloc_command(xhci, false, false, GFP_KERNEL);
> +	if (!command)
> +		return -ENOMEM;
> +
> +	command->in_ctx = virt_dev->in_ctx;
> +	command->completion = &xhci->addr_dev;
> +
>  	slot_ctx = xhci_get_slot_ctx(xhci, virt_dev->in_ctx);
>  	ctrl_ctx = xhci_get_input_control_ctx(xhci, virt_dev->in_ctx);
>  	if (!ctrl_ctx) {
>  		xhci_warn(xhci, "%s: Could not get input context, bad type.\n",
>  				__func__);
> +		kfree(command);
>  		return -EINVAL;
>  	}
>  	/*
> @@ -3780,21 +3836,21 @@ static int xhci_setup_device(struct usb_hcd *hcd, struct usb_device *udev,
>  				le32_to_cpu(slot_ctx->dev_info) >> 27);
>  
>  	spin_lock_irqsave(&xhci->lock, flags);
> -	cmd_trb = xhci_find_next_enqueue(xhci->cmd_ring);
> -	ret = xhci_queue_address_device(xhci, virt_dev->in_ctx->dma,
> +	ret = xhci_queue_address_device(xhci, command, virt_dev->in_ctx->dma,
>  					udev->slot_id, setup);
>  	if (ret) {
>  		spin_unlock_irqrestore(&xhci->lock, flags);
>  		xhci_dbg_trace(xhci, trace_xhci_dbg_address,
>  				"FIXME: allocate a command ring segment");
> +		kfree(command);
>  		return ret;
>  	}
>  	xhci_ring_cmd_db(xhci);
>  	spin_unlock_irqrestore(&xhci->lock, flags);
>  
>  	/* ctrl tx can take up to 5 sec; XXX: need more time for xHC? */
> -	timeleft = wait_for_completion_interruptible_timeout(&xhci->addr_dev,
> -			XHCI_CMD_DEFAULT_TIMEOUT);
> +	timeleft = wait_for_completion_interruptible_timeout(
> +			command->completion, XHCI_CMD_DEFAULT_TIMEOUT);
>  	/* FIXME: From section 4.3.4: "Software shall be responsible for timing
>  	 * the SetAddress() "recovery interval" required by USB and aborting the
>  	 * command on a timeout.
> @@ -3803,7 +3859,8 @@ static int xhci_setup_device(struct usb_hcd *hcd, struct usb_device *udev,
>  		xhci_warn(xhci, "%s while waiting for setup %s command\n",
>  			  timeleft == 0 ? "Timeout" : "Signal", act);
>  		/* cancel the address device command */
> -		ret = xhci_cancel_cmd(xhci, NULL, cmd_trb);
> +		ret = xhci_cancel_cmd(xhci, NULL, command->command_trb);
> +		kfree(command);
>  		if (ret < 0)
>  			return ret;
>  		return -ETIME;
> @@ -3840,6 +3897,7 @@ static int xhci_setup_device(struct usb_hcd *hcd, struct usb_device *udev,
>  		break;
>  	}
>  	if (ret) {
> +		kfree(command);
>  		return ret;
>  	}
>  	temp_64 = xhci_read_64(xhci, &xhci->op_regs->dcbaa_ptr);
> @@ -3874,7 +3932,7 @@ static int xhci_setup_device(struct usb_hcd *hcd, struct usb_device *udev,
>  	xhci_dbg_trace(xhci, trace_xhci_dbg_address,
>  		       "Internal device address = %d",
>  		       le32_to_cpu(slot_ctx->dev_state) & DEV_ADDR_MASK);
> -
> +	kfree(command);
>  	return 0;
>  }
>  
> diff --git a/drivers/usb/host/xhci.h b/drivers/usb/host/xhci.h
> index 58ed9d0..083ff11 100644
> --- a/drivers/usb/host/xhci.h
> +++ b/drivers/usb/host/xhci.h
> @@ -1807,13 +1807,14 @@ struct xhci_segment *trb_in_td(struct xhci_segment *start_seg,
>  		dma_addr_t suspect_dma);
>  int xhci_is_vendor_info_code(struct xhci_hcd *xhci, unsigned int trb_comp_code);
>  void xhci_ring_cmd_db(struct xhci_hcd *xhci);
> -int xhci_queue_slot_control(struct xhci_hcd *xhci, u32 trb_type, u32 slot_id);
> -int xhci_queue_address_device(struct xhci_hcd *xhci, dma_addr_t in_ctx_ptr,
> -		u32 slot_id, enum xhci_setup_dev);
> -int xhci_queue_vendor_command(struct xhci_hcd *xhci,
> +int xhci_queue_slot_control(struct xhci_hcd *xhci, struct xhci_command *cmd,
> +		u32 trb_type, u32 slot_id);
> +int xhci_queue_address_device(struct xhci_hcd *xhci, struct xhci_command *cmd,
> +		dma_addr_t in_ctx_ptr, u32 slot_id, enum xhci_setup_dev);
> +int xhci_queue_vendor_command(struct xhci_hcd *xhci, struct xhci_command *cmd,
>  		u32 field1, u32 field2, u32 field3, u32 field4);
> -int xhci_queue_stop_endpoint(struct xhci_hcd *xhci, int slot_id,
> -		unsigned int ep_index, int suspend);
> +int xhci_queue_stop_endpoint(struct xhci_hcd *xhci, struct xhci_command *cmd,
> +		int slot_id, unsigned int ep_index, int suspend);
>  int xhci_queue_ctrl_tx(struct xhci_hcd *xhci, gfp_t mem_flags, struct urb *urb,
>  		int slot_id, unsigned int ep_index);
>  int xhci_queue_bulk_tx(struct xhci_hcd *xhci, gfp_t mem_flags, struct urb *urb,
> @@ -1822,18 +1823,21 @@ int xhci_queue_intr_tx(struct xhci_hcd *xhci, gfp_t mem_flags, struct urb *urb,
>  		int slot_id, unsigned int ep_index);
>  int xhci_queue_isoc_tx_prepare(struct xhci_hcd *xhci, gfp_t mem_flags,
>  		struct urb *urb, int slot_id, unsigned int ep_index);
> -int xhci_queue_configure_endpoint(struct xhci_hcd *xhci, dma_addr_t in_ctx_ptr,
> -		u32 slot_id, bool command_must_succeed);
> -int xhci_queue_evaluate_context(struct xhci_hcd *xhci, dma_addr_t in_ctx_ptr,
> -		u32 slot_id, bool command_must_succeed);
> -int xhci_queue_reset_ep(struct xhci_hcd *xhci, int slot_id,
> -		unsigned int ep_index);
> -int xhci_queue_reset_device(struct xhci_hcd *xhci, u32 slot_id);
> +int xhci_queue_configure_endpoint(struct xhci_hcd *xhci,
> +		struct xhci_command *cmd, dma_addr_t in_ctx_ptr, u32 slot_id,
> +		bool command_must_succeed);
> +int xhci_queue_evaluate_context(struct xhci_hcd *xhci, struct xhci_command *cmd,
> +		dma_addr_t in_ctx_ptr, u32 slot_id, bool command_must_succeed);
> +int xhci_queue_reset_ep(struct xhci_hcd *xhci, struct xhci_command *cmd,
> +		int slot_id, unsigned int ep_index);
> +int xhci_queue_reset_device(struct xhci_hcd *xhci, struct xhci_command *cmd,
> +		u32 slot_id);
>  void xhci_find_new_dequeue_state(struct xhci_hcd *xhci,
>  		unsigned int slot_id, unsigned int ep_index,
>  		unsigned int stream_id, struct xhci_td *cur_td,
>  		struct xhci_dequeue_state *state);
>  void xhci_queue_new_dequeue_state(struct xhci_hcd *xhci,
> +		struct xhci_command *cmd,
>  		unsigned int slot_id, unsigned int ep_index,
>  		unsigned int stream_id,
>  		struct xhci_dequeue_state *deq_state);
> @@ -1847,7 +1851,6 @@ int xhci_cancel_cmd(struct xhci_hcd *xhci, struct xhci_command *command,
>  		union xhci_trb *cmd_trb);
>  void xhci_ring_ep_doorbell(struct xhci_hcd *xhci, unsigned int slot_id,
>  		unsigned int ep_index, unsigned int stream_id);
> -union xhci_trb *xhci_find_next_enqueue(struct xhci_ring *ring);
>  
>  /* xHCI roothub code */
>  void xhci_set_link_state(struct xhci_hcd *xhci, __le32 __iomem **port_array,
> -- 
> 1.8.1.2
> 

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [RFCv3 4/4] xhci: rework command timeout and cancellation,
  2014-02-26 19:38 ` [RFCv3 4/4] xhci: rework command timeout and cancellation, Mathias Nyman
@ 2014-03-06 21:44   ` Sarah Sharp
  0 siblings, 0 replies; 7+ messages in thread
From: Sarah Sharp @ 2014-03-06 21:44 UTC (permalink / raw)
  To: Mathias Nyman; +Cc: linux-usb, dan.j.williams, linux-kernel

On Wed, Feb 26, 2014 at 09:38:50PM +0200, Mathias Nyman wrote:
> Use one timer to control command timeout.
> 
> start/kick the timer every time a command is completed and a
> new command is waiting, or a new command is added to a empty list.
> 
> If the timer runs out, then tag the current command as "aborted", and
> start the xhci command abortion process.
> 
> Previously each function that submitted a command had its own timer.
> If that command timed out, a new command structure for
> the command was created and it was put on a cancel_cmd_list list,
> then a pci write to abort the command ring was issued.
> 
> when the ring was aborted, it checked if the current command
> was the one to be canceled, later when the ring was stopped the
> driver got ownership of the TRBs in the command ring,
> compared then to the TRBs in the cancel_cmd_list,
> and turned them into No-ops.
> 
> Now, instead, at timeout we tag the status of the command in the
> command queue to be aborted, and start the ring abortion.
> Ring abortion stops the command ring and gives control of the commands to us.
> All the aborted commands are now turned into No-ops.
> 
> This allows us to remove the entire cancel_cmd_list code.
> 
> The functions waiting for a command to finish no longer have their own timeouts.
> They will wait either until the command completes normally,
> or until the whole command abortion is done.

Hmm, I thought this patchset was pretty much done, but I seem to have run
into a nasty corner case.

I thought it would be good to test these patches by adding a bit of code
to stall all commands when the fifth USB device was addressed:

diff --git a/drivers/usb/host/xhci-mem.c b/drivers/usb/host/xhci-mem.c
index 4522c3218005..55f45cfc2830 100644
--- a/drivers/usb/host/xhci-mem.c
+++ b/drivers/usb/host/xhci-mem.c
@@ -2328,6 +2328,7 @@ int xhci_mem_init(struct xhci_hcd *xhci, gfp_t flags)
 
 	INIT_LIST_HEAD(&xhci->cmd_list);
 
+	xhci->stall_commands = false;
 	page_size = readl(&xhci->op_regs->page_size);
 	xhci_dbg_trace(xhci, trace_xhci_dbg_init,
 			"Supported page size register = 0x%x", page_size);
diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c
index 1ffed0ad5f96..a04f39dde22f 100644
--- a/drivers/usb/host/xhci-ring.c
+++ b/drivers/usb/host/xhci-ring.c
@@ -271,7 +271,8 @@ static inline int room_on_ring(struct xhci_hcd *xhci, struct xhci_ring *ring,
 /* Ring the host controller doorbell after placing a command on the ring */
 void xhci_ring_cmd_db(struct xhci_hcd *xhci)
 {
-	if (!(xhci->cmd_ring_state & CMD_RING_STATE_RUNNING))
+	if (!(xhci->cmd_ring_state & CMD_RING_STATE_RUNNING) ||
+			xhci->stall_commands)
 		return;
 
 	xhci_dbg(xhci, "// Ding dong!\n");
diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c
index 9c522df277e1..ffe9a4ba2c3c 100644
--- a/drivers/usb/host/xhci.c
+++ b/drivers/usb/host/xhci.c
@@ -3840,6 +3840,10 @@ static int xhci_setup_device(struct usb_hcd *hcd, struct usb_device *udev,
 		kfree(command);
 		return ret;
 	}
+	if ((++xhci->num_addressed_devices % 5) == 0) {
+		xhci->stall_commands = true;
+		xhci_warn(xhci, "Stall all new commands.\n");
+	}
 	xhci_ring_cmd_db(xhci);
 	spin_unlock_irqrestore(&xhci->lock, flags);
 
@@ -3889,6 +3893,10 @@ static int xhci_setup_device(struct usb_hcd *hcd, struct usb_device *udev,
 		kfree(command);
 		return ret;
 	}
+	if (xhci->stall_commands) {
+		xhci_dbg(xhci, "Stop stalling commands. Command doorbell can now be rung.\n");
+		xhci->stall_commands = false;
+	}
 	temp_64 = xhci_read_64(xhci, &xhci->op_regs->dcbaa_ptr);
 	xhci_dbg_trace(xhci, trace_xhci_dbg_address,
 			"Op regs DCBAA ptr = %#016llx", temp_64);
diff --git a/drivers/usb/host/xhci.h b/drivers/usb/host/xhci.h
index 68f0e6893dc2..3be5126ab01f 100644
--- a/drivers/usb/host/xhci.h
+++ b/drivers/usb/host/xhci.h
@@ -1582,6 +1582,8 @@ struct xhci_hcd {
 	u32			port_status_u0;
 /* Compliance Mode Timer Triggered every 2 seconds */
 #define COMP_MODE_RCVRY_MSECS 2000
+	int			num_addressed_devices;
+	bool			stall_commands;
 };
 
 /* convert between an HCD pointer and the corresponding EHCI_HCD */


My goal was to have an address command stall while I submitted other
commands (like a Configure Endpoint command by changing the video
resolution on a webcam).  However, the effect that patch had was to
cause the USB core to mark the host as dying:

Mar  6 13:06:19 xanatos kernel: [ 5230.420138] usb 1-1.2: new high-speed USB device number 4 using xhci_hcd
Mar  6 13:06:19 xanatos kernel: [ 5230.420146] xhci_hcd 0000:00:14.0: Slot ID 3 Input Context:
Mar  6 13:06:19 xanatos kernel: [ 5230.420151] xhci_hcd 0000:00:14.0: Stall all new commands.
Mar  6 13:06:24 xanatos kernel: [ 5235.435382] xhci_hcd 0000:00:14.0: Abort command ring
Mar  6 13:06:29 xanatos kernel: [ 5240.430719] xhci_hcd 0000:00:14.0: xHCI host not responding to stop endpoint command.
Mar  6 13:06:29 xanatos kernel: [ 5240.430730] xhci_hcd 0000:00:14.0: Assuming host is dying, halting host.
Mar  6 13:06:29 xanatos kernel: [ 5240.430783] xhci_hcd 0000:00:14.0: HC died; cleaning up
Mar  6 13:06:29 xanatos kernel: [ 5240.446698] xhci_hcd 0000:00:14.0: Abort command ring
Mar  6 13:06:29 xanatos kernel: [ 5240.446710] xhci_hcd 0000:00:14.0: The command ring isn't running, Have the command ring been stopped?
Mar  6 13:08:10 xanatos kernel: [ 5341.096873] waiting module removal not supported: please upgrade
Mar  6 13:08:10 xanatos kernel: [ 5341.096916] xhci_hcd 0000:00:14.0: remove, state 4
Mar  6 13:08:10 xanatos kernel: [ 5341.096926] usb usb2: USB disconnect, device number 1
Mar  6 13:09:14 xanatos kernel: [ 5405.363489] INFO: task khubd:127 blocked for more than 120 seconds.
Mar  6 13:09:14 xanatos kernel: [ 5405.363498]       Not tainted 3.14.0-rc5+ #200
Mar  6 13:09:14 xanatos kernel: [ 5405.363501] "echo 0 > /proc/sys/kernel/hung_task_timeout_secs" disables this message.
Mar  6 13:09:14 xanatos kernel: [ 5405.363504] khubd           D ffff88003202c300     0   127      2 0x00000000
Mar  6 13:09:14 xanatos kernel: [ 5405.363512]  ffff880115455b10 0000000000000046 ffff88003202c300 ffffffff81c114c0
Mar  6 13:09:14 xanatos kernel: [ 5405.363519]  ffff880115455fd8 0000000000013b80 0000000000013b80 ffff88003202c300
Mar  6 13:09:14 xanatos kernel: [ 5405.363525]  7fffffffffffffff ffff8800c7360198 ffff8800c7360190 ffff88003202c300
Mar  6 13:09:14 xanatos kernel: [ 5405.363531] Call Trace:
Mar  6 13:09:14 xanatos kernel: [ 5405.363544]  [<ffffffff81659519>] schedule+0x29/0x70
Mar  6 13:09:14 xanatos kernel: [ 5405.363550]  [<ffffffff81658711>] schedule_timeout+0x281/0x310
Mar  6 13:09:14 xanatos kernel: [ 5405.363557]  [<ffffffff8165a88b>] ? wait_for_completion+0x3b/0x120
Mar  6 13:09:14 xanatos kernel: [ 5405.363563]  [<ffffffff8165a904>] wait_for_completion+0xb4/0x120
Mar  6 13:09:14 xanatos kernel: [ 5405.363571]  [<ffffffff81082480>] ? wake_up_state+0x20/0x20
Mar  6 13:09:14 xanatos kernel: [ 5405.363583]  [<ffffffffa0158096>] xhci_setup_device+0x196/0x760 [xhci_hcd]
Mar  6 13:09:14 xanatos kernel: [ 5405.363593]  [<ffffffffa015d920>] xhci_enable_device+0x10/0x20 [xhci_hcd]
Mar  6 13:09:14 xanatos kernel: [ 5405.363625]  [<ffffffffa002fcbd>] hub_port_init+0x49d/0xbe0 [usbcore]
Mar  6 13:09:14 xanatos kernel: [ 5405.363644]  [<ffffffffa0031ac6>] hub_thread+0x7a6/0x1730 [usbcore]
Mar  6 13:09:14 xanatos kernel: [ 5405.363651]  [<ffffffff8109f31d>] ? trace_hardirqs_on_caller+0xfd/0x1c0
Mar  6 13:09:14 xanatos kernel: [ 5405.363659]  [<ffffffff810954d0>] ? prepare_to_wait_event+0x100/0x100
Mar  6 13:09:14 xanatos kernel: [ 5405.363674]  [<ffffffffa0031320>] ? usb_reset_device+0x1d0/0x1d0 [usbcore]
Mar  6 13:09:14 xanatos kernel: [ 5405.363680]  [<ffffffff8107084c>] kthread+0xfc/0x120
Mar  6 13:09:14 xanatos kernel: [ 5405.363686]  [<ffffffff81070750>] ? kthread_create_on_node+0x230/0x230
Mar  6 13:09:14 xanatos kernel: [ 5405.363693]  [<ffffffff816677ec>] ret_from_fork+0x7c/0xb0
Mar  6 13:09:14 xanatos kernel: [ 5405.363698]  [<ffffffff81070750>] ? kthread_create_on_node+0x230/0x230
Mar  6 13:09:14 xanatos kernel: [ 5405.363701] INFO: lockdep is turned off.
Mar  6 13:09:14 xanatos kernel: [ 5405.363721] INFO: task upowerd:1356 blocked for more than 120 seconds.
Mar  6 13:09:14 xanatos kernel: [ 5405.363724]       Not tainted 3.14.0-rc5+ #200
Mar  6 13:09:14 xanatos kernel: [ 5405.363726] "echo 0 > /proc/sys/kernel/hung_task_timeout_secs" disables this message.
Mar  6 13:09:14 xanatos kernel: [ 5405.363728] upowerd         D ffff8800b986a180     0  1356      1 0x00000000
Mar  6 13:09:14 xanatos kernel: [ 5405.363734]  ffff8800b9861de0 0000000000000046 ffff8800b986a180 ffff8800c566c300
Mar  6 13:09:14 xanatos kernel: [ 5405.363740]  ffff8800b9861fd8 0000000000013b80 0000000000013b80 ffff8800b986a180
Mar  6 13:09:14 xanatos kernel: [ 5405.363745]  ffff8800b9ab38f0 ffff8800b9ab38f8 0000000000000246 ffff8800b986a180
Mar  6 13:09:14 xanatos kernel: [ 5405.363751] Call Trace:
Mar  6 13:09:14 xanatos kernel: [ 5405.363758]  [<ffffffff816599f1>] schedule_preempt_disabled+0x31/0x80
Mar  6 13:09:14 xanatos kernel: [ 5405.363763]  [<ffffffff8165aacc>] mutex_lock_nested+0x15c/0x390
Mar  6 13:09:14 xanatos kernel: [ 5405.363783]  [<ffffffffa004043b>] ? read_descriptors+0x3b/0x110 [usbcore]
Mar  6 13:09:14 xanatos kernel: [ 5405.363800]  [<ffffffffa004043b>] read_descriptors+0x3b/0x110 [usbcore]
Mar  6 13:09:14 xanatos kernel: [ 5405.363809]  [<ffffffff8122c1fd>] sysfs_kf_bin_read+0x4d/0x70
Mar  6 13:09:14 xanatos kernel: [ 5405.363814]  [<ffffffff81230363>] kernfs_fop_read+0xa3/0x170
Mar  6 13:09:14 xanatos kernel: [ 5405.363821]  [<ffffffff811b1d6b>] vfs_read+0x9b/0x160
Mar  6 13:09:14 xanatos kernel: [ 5405.363827]  [<ffffffff811b2829>] SyS_read+0x49/0xa0
Mar  6 13:09:14 xanatos kernel: [ 5405.363834]  [<ffffffff81667896>] system_call_fastpath+0x1a/0x1f
Mar  6 13:09:14 xanatos kernel: [ 5405.363836] INFO: lockdep is turned off.
Mar  6 13:09:14 xanatos kernel: [ 5405.363860] INFO: task alsa-sink-USB A:14271 blocked for more than 120 seconds.
Mar  6 13:09:14 xanatos kernel: [ 5405.363862]       Not tainted 3.14.0-rc5+ #200
Mar  6 13:09:14 xanatos kernel: [ 5405.363864] "echo 0 > /proc/sys/kernel/hung_task_timeout_secs" disables this message.
Mar  6 13:09:14 xanatos kernel: [ 5405.363866] alsa-sink-USB A D ffff8800c7168000     0 14271   1801 0x00000000
Mar  6 13:09:14 xanatos kernel: [ 5405.363871]  ffff8800c5657b90 0000000000000046 ffff8800c7168000 ffff880118672180
Mar  6 13:09:14 xanatos kernel: [ 5405.363877]  ffff8800c5657fd8 0000000000013b80 0000000000013b80 ffff8800c7168000
Mar  6 13:09:14 xanatos kernel: [ 5405.363882]  7fffffffffffffff ffff880032314f68 ffff880032314f60 ffff8800c7168000
Mar  6 13:09:14 xanatos kernel: [ 5405.363888] Call Trace:
Mar  6 13:09:14 xanatos kernel: [ 5405.363894]  [<ffffffff81659519>] schedule+0x29/0x70
Mar  6 13:09:14 xanatos kernel: [ 5405.363899]  [<ffffffff81658711>] schedule_timeout+0x281/0x310
Mar  6 13:09:14 xanatos kernel: [ 5405.363905]  [<ffffffff8165a88b>] ? wait_for_completion+0x3b/0x120
Mar  6 13:09:14 xanatos kernel: [ 5405.363911]  [<ffffffff8165a904>] wait_for_completion+0xb4/0x120
Mar  6 13:09:14 xanatos kernel: [ 5405.363917]  [<ffffffff81082480>] ? wake_up_state+0x20/0x20
Mar  6 13:09:14 xanatos kernel: [ 5405.363927]  [<ffffffffa015b0df>] xhci_configure_endpoint+0xcf/0x550 [xhci_hcd]
Mar  6 13:09:14 xanatos kernel: [ 5405.363936]  [<ffffffffa015bead>] xhci_check_bandwidth+0x10d/0x2e0 [xhci_hcd]
Mar  6 13:09:14 xanatos kernel: [ 5405.363954]  [<ffffffffa0037043>] usb_hcd_alloc_bandwidth+0x2a3/0x340 [usbcore]
Mar  6 13:09:14 xanatos kernel: [ 5405.363972]  [<ffffffffa003a33a>] usb_set_interface+0xca/0x390 [usbcore]
Mar  6 13:09:14 xanatos kernel: [ 5405.363986]  [<ffffffffa055f3e1>] snd_usb_pcm_close.isra.9+0x51/0x80 [snd_usb_audio]
Mar  6 13:09:14 xanatos kernel: [ 5405.363996]  [<ffffffffa055f444>] snd_usb_playback_close+0x14/0x20 [snd_usb_audio]
Mar  6 13:09:14 xanatos kernel: [ 5405.364008]  [<ffffffffa043654f>] snd_pcm_release_substream.part.29+0x3f/0x90 [snd_pcm]
Mar  6 13:09:14 xanatos kernel: [ 5405.364018]  [<ffffffffa0436680>] snd_pcm_release+0xb0/0xc0 [snd_pcm]
Mar  6 13:09:14 xanatos kernel: [ 5405.364025]  [<ffffffff811b3a3f>] __fput+0xef/0x240
Mar  6 13:09:14 xanatos kernel: [ 5405.364031]  [<ffffffff811b3bde>] ____fput+0xe/0x10
Mar  6 13:09:14 xanatos kernel: [ 5405.364037]  [<ffffffff8106d4fc>] task_work_run+0xac/0xe0
Mar  6 13:09:14 xanatos kernel: [ 5405.364045]  [<ffffffff81002d69>] do_notify_resume+0x59/0x90
Mar  6 13:09:14 xanatos kernel: [ 5405.364049]  [<ffffffff81667ba2>] int_signal+0x12/0x17

And now khubd is hung, I can't unload the xHCI module, and the sound
layer is probably hung as well.

I think the issue is that when the xHCI host was marked as dying, we
halted the host, and the command ring will be marked as not running.
But there are still processes waiting on pending commands.  When the
timer fires because the first command times out, xhci_abort_cmd_ring
notices the command ring is not running, and assumes we'll get a command
event with the completion code set to COMP_CMD_STOP.  However, the host
is dead, so we'll never see that event.

I think the easiest way to fix this would be to have a new function that
handles when the host dies, that's called from both
xhci_stop_endpoint_command_watchdog and xhci_abort_cmd_ring (when
stopping the command ring fails).  That function should call
xhci_quiesce, xhci_halt, and flush out the entire command queue.

Also, what will happen if the xhci-hcd module is unloaded when a command
is still pending?  I think the code in xhci_mem_cleanup will leave those
processes hanging, waiting for their commands to complete:

        list_for_each_entry_safe(cur_cmd, next_cmd,
                        &xhci->cmd_list, cmd_list) {
                list_del(&cur_cmd->cmd_list);
                kfree(cur_cmd);
        }

You should probably also audit all xHCI functions that submit commands,
and make them not submit if the host is dying.  I don't see anything
stopping the USB core from causing command submission to a dead xHCI
host.

This needs to get fixed before the code can be merged.  (And again,
reverting those patches that were causing xHCI regressions takes
priority to fixing this.)

Sarah Sharp

> 
> Signed-off-by: Mathias Nyman <mathias.nyman@linux.intel.com>
> ---
>  drivers/usb/host/xhci-hub.c  |  11 +-
>  drivers/usb/host/xhci-mem.c  |  15 +-
>  drivers/usb/host/xhci-ring.c | 335 +++++++++++++------------------------------
>  drivers/usb/host/xhci.c      |  78 ++++------
>  drivers/usb/host/xhci.h      |   8 +-
>  5 files changed, 138 insertions(+), 309 deletions(-)
> 
> diff --git a/drivers/usb/host/xhci-hub.c b/drivers/usb/host/xhci-hub.c
> index 0a57d95..8350fd9 100644
> --- a/drivers/usb/host/xhci-hub.c
> +++ b/drivers/usb/host/xhci-hub.c
> @@ -271,7 +271,6 @@ static int xhci_stop_device(struct xhci_hcd *xhci, int slot_id, int suspend)
>  	struct xhci_virt_device *virt_dev;
>  	struct xhci_command *cmd;
>  	unsigned long flags;
> -	int timeleft;
>  	int ret;
>  	int i;
>  
> @@ -304,12 +303,10 @@ static int xhci_stop_device(struct xhci_hcd *xhci, int slot_id, int suspend)
>  	spin_unlock_irqrestore(&xhci->lock, flags);
>  
>  	/* Wait for last stop endpoint command to finish */
> -	timeleft = wait_for_completion_interruptible_timeout(
> -			cmd->completion,
> -			XHCI_CMD_DEFAULT_TIMEOUT);
> -	if (timeleft <= 0) {
> -		xhci_warn(xhci, "%s while waiting for stop endpoint command\n",
> -				timeleft == 0 ? "Timeout" : "Signal");
> +	wait_for_completion(cmd->completion);
> +
> +	if (cmd->status == COMP_CMD_ABORT || cmd->status == COMP_CMD_STOP) {
> +		xhci_warn(xhci, "Timeout while waiting for stop endpoint command\n");
>  		ret = -ETIME;
>  	}
>  	xhci_free_command(xhci, cmd);
> diff --git a/drivers/usb/host/xhci-mem.c b/drivers/usb/host/xhci-mem.c
> index 81c2469..6baaaf5 100644
> --- a/drivers/usb/host/xhci-mem.c
> +++ b/drivers/usb/host/xhci-mem.c
> @@ -1692,7 +1692,6 @@ void xhci_free_command(struct xhci_hcd *xhci,
>  void xhci_mem_cleanup(struct xhci_hcd *xhci)
>  {
>  	struct device	*dev = xhci_to_hcd(xhci)->self.controller;
> -	struct xhci_cd  *cur_cd, *next_cd;
>  	struct xhci_command *cur_cmd, *next_cmd;
>  	int size;
>  	int i, j, num_ports;
> @@ -1712,15 +1711,13 @@ void xhci_mem_cleanup(struct xhci_hcd *xhci)
>  	if (xhci->lpm_command)
>  		xhci_free_command(xhci, xhci->lpm_command);
>  	xhci->cmd_ring_reserved_trbs = 0;
> +
> +	del_timer_sync(&xhci->cmd_timer);
> +
>  	if (xhci->cmd_ring)
>  		xhci_ring_free(xhci, xhci->cmd_ring);
>  	xhci->cmd_ring = NULL;
>  	xhci_dbg_trace(xhci, trace_xhci_dbg_init, "Freed command ring");
> -	list_for_each_entry_safe(cur_cd, next_cd,
> -			&xhci->cancel_cmd_list, cancel_cmd_list) {
> -		list_del(&cur_cd->cancel_cmd_list);
> -		kfree(cur_cd);
> -	}
>  
>  	list_for_each_entry_safe(cur_cmd, next_cmd,
>  			&xhci->cmd_list, cmd_list) {
> @@ -2228,7 +2225,6 @@ int xhci_mem_init(struct xhci_hcd *xhci, gfp_t flags)
>  	u32 page_size, temp;
>  	int i;
>  
> -	INIT_LIST_HEAD(&xhci->cancel_cmd_list);
>  	INIT_LIST_HEAD(&xhci->cmd_list);
>  
>  	page_size = readl(&xhci->op_regs->page_size);
> @@ -2414,6 +2410,11 @@ int xhci_mem_init(struct xhci_hcd *xhci, gfp_t flags)
>  			"Wrote ERST address to ir_set 0.");
>  	xhci_print_ir_set(xhci, 0);
>  
> +	/* init command timeout timer */
> +	init_timer(&xhci->cmd_timer);
> +	xhci->cmd_timer.data = (unsigned long) xhci;
> +	xhci->cmd_timer.function = xhci_handle_command_timeout;
> +
>  	/*
>  	 * XXX: Might need to set the Interrupter Moderation Register to
>  	 * something other than the default (~1ms minimum between interrupts).
> diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c
> index 12bf467..b664a42 100644
> --- a/drivers/usb/host/xhci-ring.c
> +++ b/drivers/usb/host/xhci-ring.c
> @@ -323,71 +323,6 @@ static int xhci_abort_cmd_ring(struct xhci_hcd *xhci)
>  	return 0;
>  }
>  
> -static int xhci_queue_cd(struct xhci_hcd *xhci,
> -		struct xhci_command *command,
> -		union xhci_trb *cmd_trb)
> -{
> -	struct xhci_cd *cd;
> -	cd = kzalloc(sizeof(struct xhci_cd), GFP_ATOMIC);
> -	if (!cd)
> -		return -ENOMEM;
> -	INIT_LIST_HEAD(&cd->cancel_cmd_list);
> -
> -	cd->command = command;
> -	cd->cmd_trb = cmd_trb;
> -	list_add_tail(&cd->cancel_cmd_list, &xhci->cancel_cmd_list);
> -
> -	return 0;
> -}
> -
> -/*
> - * Cancel the command which has issue.
> - *
> - * Some commands may hang due to waiting for acknowledgement from
> - * usb device. It is outside of the xHC's ability to control and
> - * will cause the command ring is blocked. When it occurs software
> - * should intervene to recover the command ring.
> - * See Section 4.6.1.1 and 4.6.1.2
> - */
> -int xhci_cancel_cmd(struct xhci_hcd *xhci, struct xhci_command *command,
> -		union xhci_trb *cmd_trb)
> -{
> -	int retval = 0;
> -	unsigned long flags;
> -
> -	spin_lock_irqsave(&xhci->lock, flags);
> -
> -	if (xhci->xhc_state & XHCI_STATE_DYING) {
> -		xhci_warn(xhci, "Abort the command ring,"
> -				" but the xHCI is dead.\n");
> -		retval = -ESHUTDOWN;
> -		goto fail;
> -	}
> -
> -	/* queue the cmd desriptor to cancel_cmd_list */
> -	retval = xhci_queue_cd(xhci, command, cmd_trb);
> -	if (retval) {
> -		xhci_warn(xhci, "Queuing command descriptor failed.\n");
> -		goto fail;
> -	}
> -
> -	/* abort command ring */
> -	retval = xhci_abort_cmd_ring(xhci);
> -	if (retval) {
> -		xhci_err(xhci, "Abort command ring failed\n");
> -		if (unlikely(retval == -ESHUTDOWN)) {
> -			spin_unlock_irqrestore(&xhci->lock, flags);
> -			usb_hc_died(xhci_to_hcd(xhci)->primary_hcd);
> -			xhci_dbg(xhci, "xHCI host controller is dead.\n");
> -			return retval;
> -		}
> -	}
> -
> -fail:
> -	spin_unlock_irqrestore(&xhci->lock, flags);
> -	return retval;
> -}
> -
>  void xhci_ring_ep_doorbell(struct xhci_hcd *xhci,
>  		unsigned int slot_id,
>  		unsigned int ep_index,
> @@ -1174,164 +1109,6 @@ static void xhci_handle_cmd_reset_ep(struct xhci_hcd *xhci, int slot_id,
>  	}
>  }
>  
> -/* Complete the command and detele it from the devcie's command queue.
> - */
> -static void xhci_complete_cmd_in_cmd_wait_list(struct xhci_hcd *xhci,
> -		struct xhci_command *command, u32 status)
> -{
> -	command->status = status;
> -	list_del(&command->cmd_list);
> -	if (command->completion)
> -		complete(command->completion);
> -	else
> -		xhci_free_command(xhci, command);
> -}
> -
> -
> -/*
> - * Finding the command trb need to be cancelled and modifying it to
> - * NO OP command. And if the command is in device's command wait
> - * list, finishing and freeing it.
> - *
> - * If we can't find the command trb, we think it had already been
> - * executed.
> - */
> -static void xhci_cmd_to_noop(struct xhci_hcd *xhci, struct xhci_cd *cur_cd)
> -{
> -	struct xhci_segment *cur_seg;
> -	union xhci_trb *cmd_trb;
> -	u32 cycle_state;
> -
> -	if (xhci->cmd_ring->dequeue == xhci->cmd_ring->enqueue)
> -		return;
> -
> -	/* find the current segment of command ring */
> -	cur_seg = find_trb_seg(xhci->cmd_ring->first_seg,
> -			xhci->cmd_ring->dequeue, &cycle_state);
> -
> -	if (!cur_seg) {
> -		xhci_warn(xhci, "Command ring mismatch, dequeue = %p %llx (dma)\n",
> -				xhci->cmd_ring->dequeue,
> -				(unsigned long long)
> -				xhci_trb_virt_to_dma(xhci->cmd_ring->deq_seg,
> -					xhci->cmd_ring->dequeue));
> -		xhci_debug_ring(xhci, xhci->cmd_ring);
> -		xhci_dbg_ring_ptrs(xhci, xhci->cmd_ring);
> -		return;
> -	}
> -
> -	/* find the command trb matched by cd from command ring */
> -	for (cmd_trb = xhci->cmd_ring->dequeue;
> -			cmd_trb != xhci->cmd_ring->enqueue;
> -			next_trb(xhci, xhci->cmd_ring, &cur_seg, &cmd_trb)) {
> -		/* If the trb is link trb, continue */
> -		if (TRB_TYPE_LINK_LE32(cmd_trb->generic.field[3]))
> -			continue;
> -
> -		if (cur_cd->cmd_trb == cmd_trb) {
> -
> -			/* If the command in device's command list, we should
> -			 * finish it and free the command structure.
> -			 */
> -			if (cur_cd->command)
> -				xhci_complete_cmd_in_cmd_wait_list(xhci,
> -					cur_cd->command, COMP_CMD_STOP);
> -
> -			/* get cycle state from the origin command trb */
> -			cycle_state = le32_to_cpu(cmd_trb->generic.field[3])
> -				& TRB_CYCLE;
> -
> -			/* modify the command trb to NO OP command */
> -			cmd_trb->generic.field[0] = 0;
> -			cmd_trb->generic.field[1] = 0;
> -			cmd_trb->generic.field[2] = 0;
> -			cmd_trb->generic.field[3] = cpu_to_le32(
> -					TRB_TYPE(TRB_CMD_NOOP) | cycle_state);
> -			break;
> -		}
> -	}
> -}
> -
> -static void xhci_cancel_cmd_in_cd_list(struct xhci_hcd *xhci)
> -{
> -	struct xhci_cd *cur_cd, *next_cd;
> -
> -	if (list_empty(&xhci->cancel_cmd_list))
> -		return;
> -
> -	list_for_each_entry_safe(cur_cd, next_cd,
> -			&xhci->cancel_cmd_list, cancel_cmd_list) {
> -		xhci_cmd_to_noop(xhci, cur_cd);
> -		list_del(&cur_cd->cancel_cmd_list);
> -		kfree(cur_cd);
> -	}
> -}
> -
> -/*
> - * traversing the cancel_cmd_list. If the command descriptor according
> - * to cmd_trb is found, the function free it and return 1, otherwise
> - * return 0.
> - */
> -static int xhci_search_cmd_trb_in_cd_list(struct xhci_hcd *xhci,
> -		union xhci_trb *cmd_trb)
> -{
> -	struct xhci_cd *cur_cd, *next_cd;
> -
> -	if (list_empty(&xhci->cancel_cmd_list))
> -		return 0;
> -
> -	list_for_each_entry_safe(cur_cd, next_cd,
> -			&xhci->cancel_cmd_list, cancel_cmd_list) {
> -		if (cur_cd->cmd_trb == cmd_trb) {
> -			if (cur_cd->command)
> -				xhci_complete_cmd_in_cmd_wait_list(xhci,
> -					cur_cd->command, COMP_CMD_STOP);
> -			list_del(&cur_cd->cancel_cmd_list);
> -			kfree(cur_cd);
> -			return 1;
> -		}
> -	}
> -
> -	return 0;
> -}
> -
> -/*
> - * If the cmd_trb_comp_code is COMP_CMD_ABORT, we just check whether the
> - * trb pointed by the command ring dequeue pointer is the trb we want to
> - * cancel or not. And if the cmd_trb_comp_code is COMP_CMD_STOP, we will
> - * traverse the cancel_cmd_list to trun the all of the commands according
> - * to command descriptor to NO-OP trb.
> - */
> -static int handle_stopped_cmd_ring(struct xhci_hcd *xhci,
> -		int cmd_trb_comp_code)
> -{
> -	int cur_trb_is_good = 0;
> -
> -	/* Searching the cmd trb pointed by the command ring dequeue
> -	 * pointer in command descriptor list. If it is found, free it.
> -	 */
> -	cur_trb_is_good = xhci_search_cmd_trb_in_cd_list(xhci,
> -			xhci->cmd_ring->dequeue);
> -
> -	if (cmd_trb_comp_code == COMP_CMD_ABORT)
> -		xhci->cmd_ring_state = CMD_RING_STATE_STOPPED;
> -	else if (cmd_trb_comp_code == COMP_CMD_STOP) {
> -		/* traversing the cancel_cmd_list and canceling
> -		 * the command according to command descriptor
> -		 */
> -		xhci_cancel_cmd_in_cd_list(xhci);
> -
> -		xhci->cmd_ring_state = CMD_RING_STATE_RUNNING;
> -		/*
> -		 * ring command ring doorbell again to restart the
> -		 * command ring
> -		 */
> -		if (xhci->cmd_ring->dequeue != xhci->cmd_ring->enqueue)
> -			xhci_ring_cmd_db(xhci);
> -	}
> -	return cur_trb_is_good;
> -}
> -
>  static void xhci_handle_cmd_enable_slot(struct xhci_hcd *xhci, int slot_id,
>  		u32 cmd_comp_code)
>  {
> @@ -1429,6 +1206,30 @@ static void xhci_handle_cmd_nec_get_fw(struct xhci_hcd *xhci,
>  			NEC_FW_MINOR(le32_to_cpu(event->status)));
>  }
>  
> +void xhci_handle_command_timeout(unsigned long data)
> +{
> +	struct xhci_hcd *xhci;
> +	int ret;
> +	unsigned long flags;
> +	xhci = (struct xhci_hcd *) data;
> +	/* mark this command to be cancelled */
> +	spin_lock_irqsave(&xhci->lock, flags);
> +	if (xhci->current_cmd)
> +		xhci->current_cmd->status = COMP_CMD_ABORT;
> +	spin_unlock_irqrestore(&xhci->lock, flags);
> +
> +	ret = xhci_abort_cmd_ring(xhci);
> +
> +	if (ret) {
> +		xhci_err(xhci, "Abort command ring failed\n");
> +		if (unlikely(ret == -ESHUTDOWN)) {
> +			usb_hc_died(xhci_to_hcd(xhci)->primary_hcd);
> +			xhci_dbg(xhci, "xHCI host controller is dead.\n");
> +		}
> +	}
> +	return;
> +}
> +
>  static void handle_cmd_completion(struct xhci_hcd *xhci,
>  		struct xhci_event_cmd *event)
>  {
> @@ -1462,26 +1263,64 @@ static void handle_cmd_completion(struct xhci_hcd *xhci,
>  			 "Command completion event does not match command\n");
>  		return;
>  	}
> +
> +	del_timer(&xhci->cmd_timer);
> +
>  	trace_xhci_cmd_completion(cmd_trb, (struct xhci_generic_trb *) event);
>  
>  	cmd_comp_code = GET_COMP_CODE(le32_to_cpu(event->status));
> -	if (cmd_comp_code == COMP_CMD_ABORT || cmd_comp_code == COMP_CMD_STOP) {
> -		/* If the return value is 0, we think the trb pointed by
> -		 * command ring dequeue pointer is a good trb. The good
> -		 * trb means we don't want to cancel the trb, but it have
> -		 * been stopped by host. So we should handle it normally.
> -		 * Otherwise, driver should invoke inc_deq() and return.
> -		 */
> -		if (handle_stopped_cmd_ring(xhci, cmd_comp_code)) {
> -			inc_deq(xhci, xhci->cmd_ring);
> -			return;
> +
> +	/* If CMD ring stopped we own the trbs between enqueue and dequeue */
> +	if (cmd_comp_code == COMP_CMD_STOP) {
> +		struct xhci_command *cur_cmd, *tmp_cmd;
> +		u32 cycle_state;
> +
> +		/* Turn all aborted commands in list to no-ops, then restart */
> +		list_for_each_entry_safe(cur_cmd, tmp_cmd, &xhci->cmd_list,
> +					 cmd_list) {
> +
> +			if (cur_cmd->status != COMP_CMD_ABORT)
> +				continue;
> +
> +			cur_cmd->status = COMP_CMD_STOP;
> +
> +			/* get cycle state from the original cmd trb */
> +			cycle_state = le32_to_cpu(
> +				cur_cmd->command_trb->generic.field[3]) &
> +				TRB_CYCLE;
> +
> +			/* modify the command trb to NO OP command */
> +			cur_cmd->command_trb->generic.field[0] = 0;
> +			cur_cmd->command_trb->generic.field[1] = 0;
> +			cur_cmd->command_trb->generic.field[2] = 0;
> +			cur_cmd->command_trb->generic.field[3] = cpu_to_le32(
> +				TRB_TYPE(TRB_CMD_NOOP) | cycle_state);
> +
> +			/* completion is called when command completion
> +			 * event is received for these no-op commands
> +			 */
>  		}
> -		/* There is no command to handle if we get a stop event when the
> -		 * command ring is empty, event->cmd_trb points to the next
> -		 * unset command
> -		 */
> -		if (xhci->cmd_ring->dequeue == xhci->cmd_ring->enqueue)
> -			return;
> +		xhci->cmd_ring_state = CMD_RING_STATE_RUNNING;
> +
> +		/* ring command ring doorbell to restart the command ring */
> +		if (xhci->cmd_ring->dequeue != xhci->cmd_ring->enqueue) {
> +			xhci->current_cmd = cmd;
> +			mod_timer(&xhci->cmd_timer,
> +				  jiffies + XHCI_CMD_DEFAULT_TIMEOUT);
> +			xhci_ring_cmd_db(xhci);
> +		}
> +		return;
> +	}
> +	/*
> +	 * Host aborted the command ring, check if the current command was
> +	 * supposed to be aborted, otherwise continue normally.
> +	 * The command ring is stopped now, but the xHC will issue a Command
> +	 * Ring Stopped event which will cause us to restart it.
> +	 */
> +	if (cmd_comp_code == COMP_CMD_ABORT) {
> +		xhci->cmd_ring_state = CMD_RING_STATE_STOPPED;
> +		if (cmd->status == COMP_CMD_ABORT)
> +			goto event_handled;
>  	}
>  
>  	cmd_type = TRB_FIELD_TO_TYPE(le32_to_cpu(cmd_trb->generic.field[3]));
> @@ -1512,6 +1351,9 @@ static void handle_cmd_completion(struct xhci_hcd *xhci,
>  		xhci_handle_cmd_set_deq(xhci, slot_id, cmd_trb, cmd_comp_code);
>  		break;
>  	case TRB_CMD_NOOP:
> +		/* Is this an aborted command turned to NO-OP? */
> +		if (cmd->status == COMP_CMD_STOP)
> +			cmd_comp_code = COMP_CMD_STOP;
>  		break;
>  	case TRB_RESET_EP:
>  		WARN_ON(slot_id != TRB_TO_SLOT_ID(
> @@ -1532,6 +1374,14 @@ static void handle_cmd_completion(struct xhci_hcd *xhci,
>  		break;
>  	}
>  
> +	/* restart timer if this wasn't the last command */
> +	if (cmd->cmd_list.next != &xhci->cmd_list) {
> +		xhci->current_cmd = list_entry(cmd->cmd_list.next,
> +					       struct xhci_command, cmd_list);
> +		mod_timer(&xhci->cmd_timer, jiffies + XHCI_CMD_DEFAULT_TIMEOUT);
> +	}
> +
> +event_handled:
>  	list_del(&cmd->cmd_list);
>  
>  	if (cmd->completion) {
> @@ -3946,6 +3796,13 @@ static int queue_command(struct xhci_hcd *xhci, struct xhci_command *cmd,
>  	cmd->command_trb = xhci->cmd_ring->enqueue;
>  	list_add_tail(&cmd->cmd_list, &xhci->cmd_list);
>  
> +	/* if there are no other commands queued we start the timeout timer */
> +	if (xhci->cmd_list.next == &cmd->cmd_list &&
> +	    !timer_pending(&xhci->cmd_timer)) {
> +		xhci->current_cmd = cmd;
> +		mod_timer(&xhci->cmd_timer, jiffies + XHCI_CMD_DEFAULT_TIMEOUT);
> +	}
> +
>  	queue_trb(xhci, xhci->cmd_ring, false, field1, field2, field3,
>  			field4 | xhci->cmd_ring->cycle_state);
>  	return 0;
> diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c
> index 4dc88ae..d44eee7 100644
> --- a/drivers/usb/host/xhci.c
> +++ b/drivers/usb/host/xhci.c
> @@ -1816,6 +1816,11 @@ static int xhci_configure_endpoint_result(struct xhci_hcd *xhci,
>  	int ret;
>  
>  	switch (*cmd_status) {
> +	case COMP_CMD_ABORT:
> +	case COMP_CMD_STOP:
> +		xhci_warn(xhci, "Timeout while waiting for configure endpoint command\n");
> +		ret = -ETIME;
> +		break;
>  	case COMP_ENOMEM:
>  		dev_warn(&udev->dev, "Not enough host controller resources "
>  				"for new device state.\n");
> @@ -1862,6 +1867,11 @@ static int xhci_evaluate_context_result(struct xhci_hcd *xhci,
>  	struct xhci_virt_device *virt_dev = xhci->devs[udev->slot_id];
>  
>  	switch (*cmd_status) {
> +	case COMP_CMD_ABORT:
> +	case COMP_CMD_STOP:
> +		xhci_warn(xhci, "Timeout while waiting for evaluate context command\n");
> +		ret = -ETIME;
> +		break;
>  	case COMP_EINVAL:
>  		dev_warn(&udev->dev, "WARN: xHCI driver setup invalid evaluate "
>  				"context command.\n");
> @@ -2586,7 +2596,6 @@ static int xhci_configure_endpoint(struct xhci_hcd *xhci,
>  		bool ctx_change, bool must_succeed)
>  {
>  	int ret;
> -	int timeleft;
>  	unsigned long flags;
>  	struct xhci_input_control_ctx *ctrl_ctx;
>  	struct xhci_virt_device *virt_dev;
> @@ -2642,21 +2651,7 @@ static int xhci_configure_endpoint(struct xhci_hcd *xhci,
>  	spin_unlock_irqrestore(&xhci->lock, flags);
>  
>  	/* Wait for the configure endpoint command to complete */
> -	timeleft = wait_for_completion_interruptible_timeout(
> -			command->completion,
> -			XHCI_CMD_DEFAULT_TIMEOUT);
> -	if (timeleft <= 0) {
> -		xhci_warn(xhci, "%s while waiting for %s command\n",
> -				timeleft == 0 ? "Timeout" : "Signal",
> -				ctx_change == 0 ?
> -					"configure endpoint" :
> -					"evaluate context");
> -		/* cancel the configure endpoint command */
> -		ret = xhci_cancel_cmd(xhci, command, command->command_trb);
> -		if (ret < 0)
> -			return ret;
> -		return -ETIME;
> -	}
> +	wait_for_completion(command->completion);
>  
>  	if (!ctx_change)
>  		ret = xhci_configure_endpoint_result(xhci, udev,
> @@ -3412,7 +3407,6 @@ int xhci_discover_or_reset_device(struct usb_hcd *hcd, struct usb_device *udev)
>  	unsigned int slot_id;
>  	struct xhci_virt_device *virt_dev;
>  	struct xhci_command *reset_device_cmd;
> -	int timeleft;
>  	int last_freed_endpoint;
>  	struct xhci_slot_ctx *slot_ctx;
>  	int old_active_eps = 0;
> @@ -3480,15 +3474,7 @@ int xhci_discover_or_reset_device(struct usb_hcd *hcd, struct usb_device *udev)
>  	spin_unlock_irqrestore(&xhci->lock, flags);
>  
>  	/* Wait for the Reset Device command to finish */
> -	timeleft = wait_for_completion_interruptible_timeout(
> -			reset_device_cmd->completion,
> -			XHCI_CMD_DEFAULT_TIMEOUT);
> -	if (timeleft <= 0) {
> -		xhci_warn(xhci, "%s while waiting for reset device command\n",
> -				timeleft == 0 ? "Timeout" : "Signal");
> -		ret = -ETIME;
> -		goto command_cleanup;
> -	}
> +	wait_for_completion(reset_device_cmd->completion);
>  
>  	/* The Reset Device command can't fail, according to the 0.95/0.96 spec,
>  	 * unless we tried to reset a slot ID that wasn't enabled,
> @@ -3496,6 +3482,11 @@ int xhci_discover_or_reset_device(struct usb_hcd *hcd, struct usb_device *udev)
>  	 */
>  	ret = reset_device_cmd->status;
>  	switch (ret) {
> +	case COMP_CMD_ABORT:
> +	case COMP_CMD_STOP:
> +		xhci_warn(xhci, "Timeout waiting for reset device command\n");
> +		ret = -ETIME;
> +		goto command_cleanup;
>  	case COMP_EBADSLT: /* 0.95 completion code for bad slot ID */
>  	case COMP_CTX_STATE: /* 0.96 completion code for same thing */
>  		xhci_dbg(xhci, "Can't reset device (slot ID %u) in %s state\n",
> @@ -3663,7 +3654,6 @@ int xhci_alloc_dev(struct usb_hcd *hcd, struct usb_device *udev)
>  {
>  	struct xhci_hcd *xhci = hcd_to_xhci(hcd);
>  	unsigned long flags;
> -	int timeleft;
>  	int ret;
>  	struct xhci_command *command;
>  
> @@ -3683,19 +3673,9 @@ int xhci_alloc_dev(struct usb_hcd *hcd, struct usb_device *udev)
>  	xhci_ring_cmd_db(xhci);
>  	spin_unlock_irqrestore(&xhci->lock, flags);
>  
> -	/* XXX: how much time for xHC slot assignment? */
> -	timeleft = wait_for_completion_interruptible_timeout(
> -			command->completion,
> -			XHCI_CMD_DEFAULT_TIMEOUT);
> -	if (timeleft <= 0) {
> -		xhci_warn(xhci, "%s while waiting for a slot\n",
> -				timeleft == 0 ? "Timeout" : "Signal");
> -		/* cancel the enable slot request */
> -		ret = xhci_cancel_cmd(xhci, NULL, command->command_trb);
> -		return ret;
> -	}
> +	wait_for_completion(command->completion);
>  
> -	if (!xhci->slot_id) {
> +	if (!xhci->slot_id || command->status != COMP_SUCCESS) {
>  		xhci_err(xhci, "Error while assigning device slot ID\n");
>  		kfree(command);
>  		return 0;
> @@ -3761,7 +3741,6 @@ static int xhci_setup_device(struct usb_hcd *hcd, struct usb_device *udev,
>  {
>  	const char *act = setup == SETUP_CONTEXT_ONLY ? "context" : "address";
>  	unsigned long flags;
> -	int timeleft;
>  	struct xhci_virt_device *virt_dev;
>  	int ret = 0;
>  	struct xhci_hcd *xhci = hcd_to_xhci(hcd);
> @@ -3836,23 +3815,18 @@ static int xhci_setup_device(struct usb_hcd *hcd, struct usb_device *udev,
>  	spin_unlock_irqrestore(&xhci->lock, flags);
>  
>  	/* ctrl tx can take up to 5 sec; XXX: need more time for xHC? */
> -	timeleft = wait_for_completion_interruptible_timeout(
> -			command->completion, XHCI_CMD_DEFAULT_TIMEOUT);
> +	wait_for_completion(command->completion);
> +
>  	/* FIXME: From section 4.3.4: "Software shall be responsible for timing
>  	 * the SetAddress() "recovery interval" required by USB and aborting the
>  	 * command on a timeout.
>  	 */
> -	if (timeleft <= 0) {
> -		xhci_warn(xhci, "%s while waiting for setup %s command\n",
> -			  timeleft == 0 ? "Timeout" : "Signal", act);
> -		/* cancel the address device command */
> -		ret = xhci_cancel_cmd(xhci, NULL, command->command_trb);
> -		if (ret < 0)
> -			return ret;
> -		return -ETIME;
> -	}
> -
>  	switch (command->status) {
> +	case COMP_CMD_ABORT:
> +	case COMP_CMD_STOP:
> +		xhci_warn(xhci, "Timeout while waiting for setup device command\n");
> +		ret = -ETIME;
> +		break;
>  	case COMP_CTX_STATE:
>  	case COMP_EBADSLT:
>  		xhci_err(xhci, "Setup ERROR: setup %s command for slot %d.\n",
> diff --git a/drivers/usb/host/xhci.h b/drivers/usb/host/xhci.h
> index 217e5b0..f1a1906 100644
> --- a/drivers/usb/host/xhci.h
> +++ b/drivers/usb/host/xhci.h
> @@ -1295,7 +1295,6 @@ struct xhci_td {
>  
>  /* command descriptor */
>  struct xhci_cd {
> -	struct list_head	cancel_cmd_list;
>  	struct xhci_command	*command;
>  	union xhci_trb		*cmd_trb;
>  };
> @@ -1479,9 +1478,10 @@ struct xhci_hcd {
>  #define CMD_RING_STATE_RUNNING         (1 << 0)
>  #define CMD_RING_STATE_ABORTED         (1 << 1)
>  #define CMD_RING_STATE_STOPPED         (1 << 2)
> -	struct list_head        cancel_cmd_list;
>  	struct list_head        cmd_list;
>  	unsigned int		cmd_ring_reserved_trbs;
> +	struct timer_list	cmd_timer;
> +	struct xhci_command	*current_cmd;
>  	struct xhci_ring	*event_ring;
>  	struct xhci_erst	erst;
>  	/* Scratchpad */
> @@ -1845,8 +1845,8 @@ void xhci_queue_config_ep_quirk(struct xhci_hcd *xhci,
>  		unsigned int slot_id, unsigned int ep_index,
>  		struct xhci_dequeue_state *deq_state);
>  void xhci_stop_endpoint_command_watchdog(unsigned long arg);
> -int xhci_cancel_cmd(struct xhci_hcd *xhci, struct xhci_command *command,
> -		union xhci_trb *cmd_trb);
> +void xhci_handle_command_timeout(unsigned long data);
> +
>  void xhci_ring_ep_doorbell(struct xhci_hcd *xhci, unsigned int slot_id,
>  		unsigned int ep_index, unsigned int stream_id);
>  
> -- 
> 1.8.1.2
> 

^ permalink raw reply related	[flat|nested] 7+ messages in thread

end of thread, other threads:[~2014-03-06 21:44 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2014-02-26 19:38 [RFCv3 0/4] xhci: re-work command queue management Mathias Nyman
2014-02-26 19:38 ` [RFCv3 1/4] xhci: Use command structures when queuing commands on the command ring Mathias Nyman
2014-03-06 21:15   ` Sarah Sharp
2014-02-26 19:38 ` [RFCv3 2/4] xhci: Add a global command queue Mathias Nyman
2014-02-26 19:38 ` [RFCv3 3/4] xhci: Use completion and status in " Mathias Nyman
2014-02-26 19:38 ` [RFCv3 4/4] xhci: rework command timeout and cancellation, Mathias Nyman
2014-03-06 21:44   ` Sarah Sharp

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox