sparc64-fix-bit-twiddling-in-sparc_pmu_enable_event.patch
sparc64-do-not-clobber-personality-flags-in-sys_sparc64_personality.patch
sparc64-be-less-verbose-during-vmemmap-population.patch
+xhci-add-cmd_ring_state.patch
+xhci-add-aborting-command-ring-function.patch
+xhci-cancel-command-after-command-timeout.patch
+xhci-handle-command-after-aborting-the-command-ring.patch
--- /dev/null
+From b92cc66c047ff7cf587b318fe377061a353c120f Mon Sep 17 00:00:00 2001
+From: Elric Fu <elricfu1@gmail.com>
+Date: Wed, 27 Jun 2012 16:31:12 +0800
+Subject: xHCI: add aborting command ring function
+
+From: Elric Fu <elricfu1@gmail.com>
+
+commit b92cc66c047ff7cf587b318fe377061a353c120f upstream.
+
+Software have to abort command ring and cancel command
+when a command is failed or hang. Otherwise, the command
+ring will hang up and can't handle the others. An example
+of a command that may hang is the Address Device Command,
+because waiting for a SET_ADDRESS request to be acknowledged
+by a USB device is outside of the xHC's ability to control.
+
+To cancel a command, software will initialize a command
+descriptor for the cancel command, and add it into a
+cancel_cmd_list of xhci.
+
+Sarah: Fixed missing newline on "Have the command ring been stopped?"
+debugging statement.
+
+This patch should be backported to kernels as old as 3.0, that contain
+the commit 7ed603ecf8b68ab81f4c83097d3063d43ec73bb8 "xhci: Add an
+assertion to check for virt_dev=0 bug." That commit papers over a NULL
+pointer dereference, and this patch fixes the underlying issue that
+caused the NULL pointer dereference.
+
+Signed-off-by: Elric Fu <elricfu1@gmail.com>
+Signed-off-by: Sarah Sharp <sarah.a.sharp@linux.intel.com>
+Tested-by: Miroslav Sabljic <miroslav.sabljic@avl.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/usb/host/xhci-mem.c | 7 ++
+ drivers/usb/host/xhci-ring.c | 108 +++++++++++++++++++++++++++++++++++++++++++
+ drivers/usb/host/xhci.c | 2
+ drivers/usb/host/xhci.h | 12 ++++
+ 4 files changed, 128 insertions(+), 1 deletion(-)
+
+--- a/drivers/usb/host/xhci-mem.c
++++ b/drivers/usb/host/xhci-mem.c
+@@ -1505,6 +1505,7 @@ void xhci_free_command(struct xhci_hcd *
+ void xhci_mem_cleanup(struct xhci_hcd *xhci)
+ {
+ struct pci_dev *pdev = to_pci_dev(xhci_to_hcd(xhci)->self.controller);
++ struct xhci_cd *cur_cd, *next_cd;
+ int size;
+ int i;
+
+@@ -1525,6 +1526,11 @@ void xhci_mem_cleanup(struct xhci_hcd *x
+ xhci_ring_free(xhci, xhci->cmd_ring);
+ xhci->cmd_ring = NULL;
+ xhci_dbg(xhci, "Freed command ring\n");
++ 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);
++ }
+
+ for (i = 1; i < MAX_HC_SLOTS; ++i)
+ xhci_free_virt_device(xhci, i);
+@@ -2014,6 +2020,7 @@ int xhci_mem_init(struct xhci_hcd *xhci,
+ xhci->cmd_ring = xhci_ring_alloc(xhci, 1, true, false, flags);
+ if (!xhci->cmd_ring)
+ goto fail;
++ INIT_LIST_HEAD(&xhci->cancel_cmd_list);
+ xhci_dbg(xhci, "Allocated command ring at %p\n", xhci->cmd_ring);
+ xhci_dbg(xhci, "First segment DMA is 0x%llx\n",
+ (unsigned long long)xhci->cmd_ring->first_seg->dma);
+--- a/drivers/usb/host/xhci-ring.c
++++ b/drivers/usb/host/xhci-ring.c
+@@ -320,6 +320,114 @@ void xhci_ring_cmd_db(struct xhci_hcd *x
+ xhci_readl(xhci, &xhci->dba->doorbell[0]);
+ }
+
++static int xhci_abort_cmd_ring(struct xhci_hcd *xhci)
++{
++ u64 temp_64;
++ int ret;
++
++ xhci_dbg(xhci, "Abort command ring\n");
++
++ if (!(xhci->cmd_ring_state & CMD_RING_STATE_RUNNING)) {
++ xhci_dbg(xhci, "The command ring isn't running, "
++ "Have the command ring been stopped?\n");
++ return 0;
++ }
++
++ temp_64 = xhci_read_64(xhci, &xhci->op_regs->cmd_ring);
++ if (!(temp_64 & CMD_RING_RUNNING)) {
++ xhci_dbg(xhci, "Command ring had been stopped\n");
++ return 0;
++ }
++ xhci->cmd_ring_state = CMD_RING_STATE_ABORTED;
++ xhci_write_64(xhci, temp_64 | CMD_RING_ABORT,
++ &xhci->op_regs->cmd_ring);
++
++ /* Section 4.6.1.2 of xHCI 1.0 spec says software should
++ * time the completion od all xHCI commands, including
++ * the Command Abort operation. If software doesn't see
++ * CRR negated in a timely manner (e.g. longer than 5
++ * seconds), then it should assume that the there are
++ * larger problems with the xHC and assert HCRST.
++ */
++ ret = handshake(xhci, &xhci->op_regs->cmd_ring,
++ CMD_RING_RUNNING, 0, 5 * 1000 * 1000);
++ if (ret < 0) {
++ xhci_err(xhci, "Stopped the command ring failed, "
++ "maybe the host is dead\n");
++ xhci->xhc_state |= XHCI_STATE_DYING;
++ xhci_quiesce(xhci);
++ xhci_halt(xhci);
++ return -ESHUTDOWN;
++ }
++
++ 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,
+--- a/drivers/usb/host/xhci.c
++++ b/drivers/usb/host/xhci.c
+@@ -51,7 +51,7 @@ MODULE_PARM_DESC(link_quirk, "Don't clea
+ * handshake done). There are two failure modes: "usec" have passed (major
+ * hardware flakeout), or the register reads as all-ones (hardware removed).
+ */
+-static int handshake(struct xhci_hcd *xhci, void __iomem *ptr,
++int handshake(struct xhci_hcd *xhci, void __iomem *ptr,
+ u32 mask, u32 done, int usec)
+ {
+ u32 result;
+--- a/drivers/usb/host/xhci.h
++++ b/drivers/usb/host/xhci.h
+@@ -1111,6 +1111,13 @@ struct xhci_td {
+ union xhci_trb *last_trb;
+ };
+
++/* command descriptor */
++struct xhci_cd {
++ struct list_head cancel_cmd_list;
++ struct xhci_command *command;
++ union xhci_trb *cmd_trb;
++};
++
+ struct xhci_dequeue_state {
+ struct xhci_segment *new_deq_seg;
+ union xhci_trb *new_deq_ptr;
+@@ -1256,6 +1263,7 @@ 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;
+ unsigned int cmd_ring_reserved_trbs;
+ struct xhci_ring *event_ring;
+ struct xhci_erst erst;
+@@ -1490,6 +1498,8 @@ void xhci_unregister_pci(void);
+ #endif
+
+ /* xHCI host controller glue */
++int handshake(struct xhci_hcd *xhci, void __iomem *ptr,
++ u32 mask, u32 done, int usec);
+ void xhci_quiesce(struct xhci_hcd *xhci);
+ int xhci_halt(struct xhci_hcd *xhci);
+ int xhci_reset(struct xhci_hcd *xhci);
+@@ -1572,6 +1582,8 @@ void xhci_queue_config_ep_quirk(struct x
+ 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_ring_ep_doorbell(struct xhci_hcd *xhci, unsigned int slot_id,
+ unsigned int ep_index, unsigned int stream_id);
+
--- /dev/null
+From c181bc5b5d5c79b71203cd10cef97f802fb6f9c1 Mon Sep 17 00:00:00 2001
+From: Elric Fu <elricfu1@gmail.com>
+Date: Wed, 27 Jun 2012 16:30:57 +0800
+Subject: xHCI: add cmd_ring_state
+
+From: Elric Fu <elricfu1@gmail.com>
+
+commit c181bc5b5d5c79b71203cd10cef97f802fb6f9c1 upstream.
+
+Adding cmd_ring_state for command ring. It helps to verify
+the current command ring state for controlling the command
+ring operations.
+
+This patch should be backported to kernels as old as 3.0. The commit
+7ed603ecf8b68ab81f4c83097d3063d43ec73bb8 "xhci: Add an assertion to
+check for virt_dev=0 bug." papers over the NULL pointer dereference that
+I now believe is related to a timed out Set Address command. This (and
+the four patches that follow it) contain the real fix that also allows
+VIA USB 3.0 hubs to consistently re-enumerate during the plug/unplug
+stress tests.
+
+Signed-off-by: Elric Fu <elricfu1@gmail.com>
+Signed-off-by: Sarah Sharp <sarah.a.sharp@linux.intel.com>
+Tested-by: Miroslav Sabljic <miroslav.sabljic@avl.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/usb/host/xhci-ring.c | 3 +++
+ drivers/usb/host/xhci.c | 5 ++++-
+ drivers/usb/host/xhci.h | 4 ++++
+ 3 files changed, 11 insertions(+), 1 deletion(-)
+
+--- a/drivers/usb/host/xhci-ring.c
++++ b/drivers/usb/host/xhci-ring.c
+@@ -311,6 +311,9 @@ static int room_on_ring(struct xhci_hcd
+ /* 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))
++ return;
++
+ xhci_dbg(xhci, "// Ding dong!\n");
+ xhci_writel(xhci, DB_VALUE_HOST, &xhci->dba->doorbell[0]);
+ /* Flush PCI posted writes */
+--- a/drivers/usb/host/xhci.c
++++ b/drivers/usb/host/xhci.c
+@@ -104,8 +104,10 @@ int xhci_halt(struct xhci_hcd *xhci)
+
+ ret = handshake(xhci, &xhci->op_regs->status,
+ STS_HALT, STS_HALT, XHCI_MAX_HALT_USEC);
+- if (!ret)
++ if (!ret) {
+ xhci->xhc_state |= XHCI_STATE_HALTED;
++ xhci->cmd_ring_state = CMD_RING_STATE_STOPPED;
++ }
+ return ret;
+ }
+
+@@ -390,6 +392,7 @@ static int xhci_run_finished(struct xhci
+ return -ENODEV;
+ }
+ xhci->shared_hcd->state = HC_STATE_RUNNING;
++ xhci->cmd_ring_state = CMD_RING_STATE_RUNNING;
+
+ if (xhci->quirks & XHCI_NEC_HOST)
+ xhci_ring_cmd_db(xhci);
+--- a/drivers/usb/host/xhci.h
++++ b/drivers/usb/host/xhci.h
+@@ -1252,6 +1252,10 @@ struct xhci_hcd {
+ /* data structures */
+ struct xhci_device_context_array *dcbaa;
+ struct xhci_ring *cmd_ring;
++ unsigned int cmd_ring_state;
++#define CMD_RING_STATE_RUNNING (1 << 0)
++#define CMD_RING_STATE_ABORTED (1 << 1)
++#define CMD_RING_STATE_STOPPED (1 << 2)
+ unsigned int cmd_ring_reserved_trbs;
+ struct xhci_ring *event_ring;
+ struct xhci_erst erst;
--- /dev/null
+From 6e4468b9a0793dfb53eb80d9fe52c739b13b27fd Mon Sep 17 00:00:00 2001
+From: Elric Fu <elricfu1@gmail.com>
+Date: Wed, 27 Jun 2012 16:31:52 +0800
+Subject: xHCI: cancel command after command timeout
+
+From: Elric Fu <elricfu1@gmail.com>
+
+commit 6e4468b9a0793dfb53eb80d9fe52c739b13b27fd upstream.
+
+The patch is used to cancel command when the command isn't
+acknowledged and a timeout occurs.
+
+This patch should be backported to kernels as old as 3.0, that contain
+the commit 7ed603ecf8b68ab81f4c83097d3063d43ec73bb8 "xhci: Add an
+assertion to check for virt_dev=0 bug." That commit papers over a NULL
+pointer dereference, and this patch fixes the underlying issue that
+caused the NULL pointer dereference.
+
+Signed-off-by: Elric Fu <elricfu1@gmail.com>
+Signed-off-by: Sarah Sharp <sarah.a.sharp@linux.intel.com>
+Tested-by: Miroslav Sabljic <miroslav.sabljic@avl.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/usb/host/xhci.c | 26 +++++++++++++++++++-------
+ drivers/usb/host/xhci.h | 3 +++
+ 2 files changed, 22 insertions(+), 7 deletions(-)
+
+--- a/drivers/usb/host/xhci.c
++++ b/drivers/usb/host/xhci.c
+@@ -1778,6 +1778,7 @@ static int xhci_configure_endpoint(struc
+ struct completion *cmd_completion;
+ u32 *cmd_status;
+ struct xhci_virt_device *virt_dev;
++ union xhci_trb *cmd_trb;
+
+ spin_lock_irqsave(&xhci->lock, flags);
+ virt_dev = xhci->devs[udev->slot_id];
+@@ -1820,6 +1821,7 @@ static int xhci_configure_endpoint(struc
+ }
+ init_completion(cmd_completion);
+
++ cmd_trb = xhci->cmd_ring->dequeue;
+ if (!ctx_change)
+ ret = xhci_queue_configure_endpoint(xhci, in_ctx->dma,
+ udev->slot_id, must_succeed);
+@@ -1841,14 +1843,17 @@ static int xhci_configure_endpoint(struc
+ /* Wait for the configure endpoint command to complete */
+ timeleft = wait_for_completion_interruptible_timeout(
+ cmd_completion,
+- USB_CTRL_SET_TIMEOUT);
++ 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");
+- /* FIXME cancel the configure endpoint command */
++ /* cancel the configure endpoint command */
++ ret = xhci_cancel_cmd(xhci, command, cmd_trb);
++ if (ret < 0)
++ return ret;
+ return -ETIME;
+ }
+
+@@ -2781,8 +2786,10 @@ int xhci_alloc_dev(struct usb_hcd *hcd,
+ unsigned long flags;
+ int timeleft;
+ int ret;
++ union xhci_trb *cmd_trb;
+
+ spin_lock_irqsave(&xhci->lock, flags);
++ cmd_trb = xhci->cmd_ring->dequeue;
+ ret = xhci_queue_slot_control(xhci, TRB_ENABLE_SLOT, 0);
+ if (ret) {
+ spin_unlock_irqrestore(&xhci->lock, flags);
+@@ -2794,12 +2801,12 @@ int xhci_alloc_dev(struct usb_hcd *hcd,
+
+ /* XXX: how much time for xHC slot assignment? */
+ timeleft = wait_for_completion_interruptible_timeout(&xhci->addr_dev,
+- USB_CTRL_SET_TIMEOUT);
++ XHCI_CMD_DEFAULT_TIMEOUT);
+ if (timeleft <= 0) {
+ xhci_warn(xhci, "%s while waiting for a slot\n",
+ timeleft == 0 ? "Timeout" : "Signal");
+- /* FIXME cancel the enable slot request */
+- return 0;
++ /* cancel the enable slot request */
++ return xhci_cancel_cmd(xhci, NULL, cmd_trb);
+ }
+
+ if (!xhci->slot_id) {
+@@ -2860,6 +2867,7 @@ int xhci_address_device(struct usb_hcd *
+ struct xhci_slot_ctx *slot_ctx;
+ struct xhci_input_control_ctx *ctrl_ctx;
+ u64 temp_64;
++ union xhci_trb *cmd_trb;
+
+ if (!udev->slot_id) {
+ xhci_dbg(xhci, "Bad Slot ID %d\n", udev->slot_id);
+@@ -2898,6 +2906,7 @@ int xhci_address_device(struct usb_hcd *
+ xhci_dbg_ctx(xhci, virt_dev->in_ctx, 2);
+
+ spin_lock_irqsave(&xhci->lock, flags);
++ cmd_trb = xhci->cmd_ring->dequeue;
+ ret = xhci_queue_address_device(xhci, virt_dev->in_ctx->dma,
+ udev->slot_id);
+ if (ret) {
+@@ -2910,7 +2919,7 @@ int xhci_address_device(struct usb_hcd *
+
+ /* ctrl tx can take up to 5 sec; XXX: need more time for xHC? */
+ timeleft = wait_for_completion_interruptible_timeout(&xhci->addr_dev,
+- USB_CTRL_SET_TIMEOUT);
++ 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.
+@@ -2918,7 +2927,10 @@ int xhci_address_device(struct usb_hcd *
+ if (timeleft <= 0) {
+ xhci_warn(xhci, "%s while waiting for a slot\n",
+ timeleft == 0 ? "Timeout" : "Signal");
+- /* FIXME cancel the address device command */
++ /* cancel the address device command */
++ ret = xhci_cancel_cmd(xhci, NULL, cmd_trb);
++ if (ret < 0)
++ return ret;
+ return -ETIME;
+ }
+
+--- a/drivers/usb/host/xhci.h
++++ b/drivers/usb/host/xhci.h
+@@ -1111,6 +1111,9 @@ struct xhci_td {
+ union xhci_trb *last_trb;
+ };
+
++/* xHCI command default timeout value */
++#define XHCI_CMD_DEFAULT_TIMEOUT (5 * HZ)
++
+ /* command descriptor */
+ struct xhci_cd {
+ struct list_head cancel_cmd_list;
--- /dev/null
+From b63f4053cc8aa22a98e3f9a97845afe6c15d0a0d Mon Sep 17 00:00:00 2001
+From: Elric Fu <elricfu1@gmail.com>
+Date: Wed, 27 Jun 2012 16:55:43 +0800
+Subject: xHCI: handle command after aborting the command ring
+
+From: Elric Fu <elricfu1@gmail.com>
+
+commit b63f4053cc8aa22a98e3f9a97845afe6c15d0a0d upstream.
+
+According to xHCI spec section 4.6.1.1 and section 4.6.1.2,
+after aborting a command on the command ring, xHC will
+generate a command completion event with its completion
+code set to Command Ring Stopped at least. If a command is
+currently executing at the time of aborting a command, xHC
+also generate a command completion event with its completion
+code set to Command Abort. When the command ring is stopped,
+software may remove, add, or rearrage Command Descriptors.
+
+To cancel a command, software will initialize a command
+descriptor for the cancel command, and add it into a
+cancel_cmd_list of xhci. When the command ring is stopped,
+software will find the command trbs described by command
+descriptors in cancel_cmd_list and modify it to No Op
+command. If software can't find the matched trbs, we can
+think it had been finished.
+
+This patch should be backported to kernels as old as 3.0, that contain
+the commit 7ed603ecf8b68ab81f4c83097d3063d43ec73bb8 "xhci: Add an
+assertion to check for virt_dev=0 bug." That commit papers over a NULL
+pointer dereference, and this patch fixes the underlying issue that
+caused the NULL pointer dereference.
+
+Note from Sarah: The TRB_TYPE_LINK_LE32 macro is not in the 3.0 stable
+kernel, so I added it to this patch.
+
+Signed-off-by: Elric Fu <elricfu1@gmail.com>
+Signed-off-by: Sarah Sharp <sarah.a.sharp@linux.intel.com>
+Tested-by: Miroslav Sabljic <miroslav.sabljic@avl.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+
+---
+ drivers/usb/host/xhci-ring.c | 171 +++++++++++++++++++++++++++++++++++++++++--
+ drivers/usb/host/xhci.h | 3
+ 2 files changed, 168 insertions(+), 6 deletions(-)
+
+--- a/drivers/usb/host/xhci-ring.c
++++ b/drivers/usb/host/xhci-ring.c
+@@ -1157,6 +1157,20 @@ static void handle_reset_ep_completion(s
+ }
+ }
+
++/* 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);
++}
++
++
+ /* 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.
+@@ -1175,15 +1189,144 @@ static int handle_cmd_in_cmd_wait_list(s
+ if (xhci->cmd_ring->dequeue != command->command_trb)
+ return 0;
+
+- command->status = GET_COMP_CODE(le32_to_cpu(event->status));
+- list_del(&command->cmd_list);
+- if (command->completion)
+- complete(command->completion);
+- else
+- xhci_free_command(xhci, command);
++ 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
++ * 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);
++
++ /* 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 handle_cmd_completion(struct xhci_hcd *xhci,
+ struct xhci_event_cmd *event)
+ {
+@@ -1209,6 +1352,22 @@ static void handle_cmd_completion(struct
+ xhci->error_bitmask |= 1 << 5;
+ return;
+ }
++
++ if ((GET_COMP_CODE(le32_to_cpu(event->status)) == COMP_CMD_ABORT) ||
++ (GET_COMP_CODE(le32_to_cpu(event->status)) == 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,
++ GET_COMP_CODE(le32_to_cpu(event->status)))) {
++ inc_deq(xhci, xhci->cmd_ring, false);
++ return;
++ }
++ }
++
+ switch (le32_to_cpu(xhci->cmd_ring->dequeue->generic.field[3])
+ & TRB_TYPE_BITMASK) {
+ case TRB_TYPE(TRB_ENABLE_SLOT):
+--- a/drivers/usb/host/xhci.h
++++ b/drivers/usb/host/xhci.h
+@@ -1070,6 +1070,9 @@ union xhci_trb {
+ #define TRB_MFINDEX_WRAP 39
+ /* TRB IDs 40-47 reserved, 48-63 is vendor-defined */
+
++#define TRB_TYPE_LINK_LE32(x) (((x) & cpu_to_le32(TRB_TYPE_BITMASK)) == \
++ cpu_to_le32(TRB_TYPE(TRB_LINK)))
++
+ /* Nec vendor-specific command completion event. */
+ #define TRB_NEC_CMD_COMP 48
+ /* Get NEC firmware revision. */