From: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
To: linux-kernel@vger.kernel.org, stable@vger.kernel.org
Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>,
alan@lxorguk.ukuu.org.uk, Elric Fu <elricfu1@gmail.com>,
Sarah Sharp <sarah.a.sharp@linux.intel.com>,
Miroslav Sabljic <miroslav.sabljic@avl.com>
Subject: [ 29/31] xHCI: add aborting command ring function
Date: Thu, 25 Oct 2012 17:04:36 -0700 [thread overview]
Message-ID: <20121026000217.926284717@linuxfoundation.org> (raw)
In-Reply-To: <20121026000214.941721299@linuxfoundation.org>
3.0-stable review patch. If anyone has any objections, please let me know.
------------------
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);
next prev parent reply other threads:[~2012-10-26 0:47 UTC|newest]
Thread overview: 35+ messages / expand[flat|nested] mbox.gz Atom feed top
2012-10-26 0:04 [ 00/31] 3.0.49-stable review Greg Kroah-Hartman
2012-10-26 0:04 ` [ 01/31] arch/tile: avoid generating .eh_frame information in modules Greg Kroah-Hartman
2012-10-26 0:04 ` [ 02/31] NLM: nlm_lookup_file() may return NLMv4-specific error codes Greg Kroah-Hartman
2012-10-26 0:04 ` [ 03/31] oprofile, x86: Fix wrapping bug in op_x86_get_ctrl() Greg Kroah-Hartman
2012-10-26 0:04 ` [ 04/31] SUNRPC: Prevent kernel stack corruption on long values of flush Greg Kroah-Hartman
2012-10-26 0:04 ` [ 05/31] Revert: lockd: use rpc clients cl_nodename for id encoding Greg Kroah-Hartman
2012-10-26 0:04 ` [ 06/31] pcmcia: sharpsl: dont discard sharpsl_pcmcia_ops Greg Kroah-Hartman
2012-10-26 0:04 ` [ 07/31] kernel/sys.c: fix stack memory content leak via UNAME26 Greg Kroah-Hartman
2012-10-26 0:04 ` [ 08/31] use clamp_t in UNAME26 fix Greg Kroah-Hartman
2012-10-26 0:11 ` Jonathan Nieder
2012-10-26 2:28 ` Greg Kroah-Hartman
2012-10-26 8:07 ` Jonathan Nieder
2012-10-26 0:04 ` [ 09/31] x86: Exclude E820_RESERVED regions and memory holes above 4 GB from direct mapping Greg Kroah-Hartman
2012-10-26 0:04 ` [ 10/31] xen/x86: dont corrupt %eip when returning from a signal handler Greg Kroah-Hartman
2012-10-26 0:04 ` [ 11/31] USB: cdc-acm: fix pipe type of write endpoint Greg Kroah-Hartman
2012-10-26 0:04 ` [ 12/31] usb: acm: fix the computation of the number of data bits Greg Kroah-Hartman
2012-10-26 0:04 ` [ 13/31] USB: option: blacklist net interface on ZTE devices Greg Kroah-Hartman
2012-10-26 0:04 ` [ 14/31] USB: option: add more " Greg Kroah-Hartman
2012-10-26 0:04 ` [ 15/31] cgroup: notify_on_release may not be triggered in some cases Greg Kroah-Hartman
2012-10-26 0:04 ` [ 16/31] amd64_edac:__amd64_set_scrub_rate(): avoid overindexing scrubrates[] Greg Kroah-Hartman
2012-10-26 0:04 ` [ 17/31] media: au0828: fix case where STREAMOFF being called on stopped stream causes BUG() Greg Kroah-Hartman
2012-10-26 0:04 ` [ 18/31] drm/i915: apply timing generator bug workaround on CPT and PPT Greg Kroah-Hartman
2012-10-26 0:04 ` [ 19/31] net: Fix skb_under_panic oops in neigh_resolve_output Greg Kroah-Hartman
2012-10-26 0:04 ` [ 20/31] skge: Add DMA mask quirk for Marvell 88E8001 on ASUS P5NSLI motherboard Greg Kroah-Hartman
2012-10-26 0:04 ` [ 21/31] RDS: fix rds-ping spinlock recursion Greg Kroah-Hartman
2012-10-26 0:04 ` [ 22/31] tcp: resets are misrouted Greg Kroah-Hartman
2012-10-26 0:04 ` [ 23/31] sparc64: fix ptrace interaction with force_successful_syscall_return() Greg Kroah-Hartman
2012-10-26 0:04 ` [ 24/31] sparc64: Like x86 we should check current->mm during perf backtrace generation Greg Kroah-Hartman
2012-10-26 0:04 ` [ 25/31] sparc64: Fix bit twiddling in sparc_pmu_enable_event() Greg Kroah-Hartman
2012-10-26 0:04 ` [ 26/31] sparc64: do not clobber personality flags in sys_sparc64_personality() Greg Kroah-Hartman
2012-10-26 0:04 ` [ 27/31] sparc64: Be less verbose during vmemmap population Greg Kroah-Hartman
2012-10-26 0:04 ` [ 28/31] xHCI: add cmd_ring_state Greg Kroah-Hartman
2012-10-26 0:04 ` Greg Kroah-Hartman [this message]
2012-10-26 0:04 ` [ 30/31] xHCI: cancel command after command timeout Greg Kroah-Hartman
2012-10-26 0:04 ` [ 31/31] xHCI: handle command after aborting the command ring Greg Kroah-Hartman
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20121026000217.926284717@linuxfoundation.org \
--to=gregkh@linuxfoundation.org \
--cc=alan@lxorguk.ukuu.org.uk \
--cc=elricfu1@gmail.com \
--cc=linux-kernel@vger.kernel.org \
--cc=miroslav.sabljic@avl.com \
--cc=sarah.a.sharp@linux.intel.com \
--cc=stable@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.