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/56] xHCI: add aborting command ring function
Date: Thu, 4 Oct 2012 14:15:50 -0700 [thread overview]
Message-ID: <20121004211155.428441312@linuxfoundation.org> (raw)
In-Reply-To: <20121004211152.101901246@linuxfoundation.org>
3.6-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
@@ -1772,6 +1772,7 @@ void xhci_mem_cleanup(struct xhci_hcd *x
{
struct pci_dev *pdev = to_pci_dev(xhci_to_hcd(xhci)->self.controller);
struct dev_info *dev_info, *next;
+ struct xhci_cd *cur_cd, *next_cd;
unsigned long flags;
int size;
int i, j, num_ports;
@@ -1795,6 +1796,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);
@@ -2340,6 +2346,7 @@ int xhci_mem_init(struct xhci_hcd *xhci,
xhci->cmd_ring = xhci_ring_alloc(xhci, 1, 1, TYPE_COMMAND, 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
@@ -289,6 +289,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
@@ -52,7 +52,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
@@ -1256,6 +1256,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;
@@ -1425,6 +1432,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;
@@ -1709,6 +1717,8 @@ static inline void xhci_unregister_plat(
/* xHCI host controller glue */
typedef void (*xhci_get_quirks_t)(struct device *, struct xhci_hcd *);
+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);
@@ -1799,6 +1809,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-04 22:11 UTC|newest]
Thread overview: 57+ messages / expand[flat|nested] mbox.gz Atom feed top
2012-10-04 21:15 [ 00/56] 3.6.1-stable review Greg Kroah-Hartman
2012-10-04 21:15 ` [ 01/56] usb: gadget: make g_printer enumerate again Greg Kroah-Hartman
2012-10-04 21:15 ` [ 02/56] usb: gadget: initialize the strings in tcm_usb_gadget properly Greg Kroah-Hartman
2012-10-04 21:15 ` [ 03/56] usb: otg: mxs-phy: Fix mx23 operation Greg Kroah-Hartman
2012-10-04 21:15 ` [ 04/56] USB: option: blacklist QMI interface on ZTE MF683 Greg Kroah-Hartman
2012-10-04 21:15 ` [ 05/56] USB: ftdi_sio: add TIAO USB Multi-Protocol Adapter (TUMPA) support Greg Kroah-Hartman
2012-10-04 21:15 ` [ 06/56] USB: EHCI: convert warning messages to debug-level Greg Kroah-Hartman
2012-10-04 21:15 ` [ 07/56] USB: qcaux: add Pantech vendor class match Greg Kroah-Hartman
2012-10-04 21:15 ` [ 08/56] usb: host: xhci: Fix Null pointer dereferencing with 71c731a for non-x86 systems Greg Kroah-Hartman
2012-10-04 21:15 ` [ 09/56] USB: serial: fix up bug with missing {} Greg Kroah-Hartman
2012-10-04 21:15 ` [ 10/56] staging: speakup_soft: Fix reading of init string Greg Kroah-Hartman
2012-10-04 21:15 ` [ 11/56] tty: keyboard.c: Remove locking from vt_get_leds Greg Kroah-Hartman
2012-10-04 21:15 ` [ 12/56] staging: r8712u: Do not queue cloned skb Greg Kroah-Hartman
2012-10-04 21:15 ` [ 13/56] staging: comedi: s626: dont dereference insn->data Greg Kroah-Hartman
2012-10-04 21:15 ` [ 14/56] staging: comedi: jr3_pci: fix iomem dereference Greg Kroah-Hartman
2012-10-04 21:15 ` [ 15/56] staging: comedi: dont dereference user memory for INSN_INTTRIG Greg Kroah-Hartman
2012-10-04 21:15 ` [ 16/56] staging: comedi: fix memory leak for saved channel list Greg Kroah-Hartman
2012-10-04 21:15 ` [ 17/56] Remove BUG_ON from n_tty_read() Greg Kroah-Hartman
2012-10-04 21:15 ` [ 18/56] TTY: ttyprintk, dont touch behind tty->write_buf Greg Kroah-Hartman
2012-10-04 21:15 ` [ 19/56] serial: omap: fix software flow control Greg Kroah-Hartman
2012-10-04 21:15 ` [ 20/56] serial: pl011: handle corruption at high clock speeds Greg Kroah-Hartman
2012-10-04 21:15 ` [ 21/56] serial: set correct baud_base for EXSYS EX-41092 Dual 16950 Greg Kroah-Hartman
2012-10-04 21:15 ` [ 22/56] tools/hv: Fix file handle leak Greg Kroah-Hartman
2012-10-04 21:15 ` [ 23/56] tools/hv: Fix exit() error code Greg Kroah-Hartman
2012-10-04 21:15 ` [ 24/56] tools/hv: Check for read/write errors Greg Kroah-Hartman
2012-10-04 21:15 ` [ 25/56] b43legacy: Fix crash on unload when firmware not available Greg Kroah-Hartman
2012-10-04 21:15 ` [ 26/56] firmware: Add missing attributes to EFI variable attribute print out from sysfs Greg Kroah-Hartman
2012-10-04 21:15 ` [ 27/56] xhci: Intel Panther Point BEI quirk Greg Kroah-Hartman
2012-10-04 21:15 ` [ 28/56] xHCI: add cmd_ring_state Greg Kroah-Hartman
2012-10-04 21:15 ` Greg Kroah-Hartman [this message]
2012-10-04 21:15 ` [ 30/56] xHCI: cancel command after command timeout Greg Kroah-Hartman
2012-10-04 21:15 ` [ 31/56] xHCI: handle command after aborting the command ring Greg Kroah-Hartman
2012-10-04 21:15 ` [ 32/56] Increase XHCI suspend timeout to 16ms Greg Kroah-Hartman
2012-10-04 21:15 ` [ 33/56] HID: keep dev_rdesc unmodified and use it for comparisons Greg Kroah-Hartman
2012-10-04 21:15 ` [ 34/56] ath9k: Disable ASPM only for AR9285 Greg Kroah-Hartman
2012-10-04 21:15 ` [ 35/56] xen/pciback: Restore the PCI config space after an FLR Greg Kroah-Hartman
2012-10-04 21:15 ` [ 36/56] coredump: prevent double-free on an error path in core dumper Greg Kroah-Hartman
2012-10-04 21:15 ` [ 37/56] n_gsm.c: Implement 3GPP27.010 DLC start-up procedure in MUX Greg Kroah-Hartman
2012-10-04 21:15 ` [ 38/56] n_gsm: uplink SKBs accumulate on list Greg Kroah-Hartman
2012-10-04 21:16 ` [ 39/56] n_gsm: added interlocking for gsm_data_lock for certain code paths Greg Kroah-Hartman
2012-10-04 21:16 ` [ 40/56] n_gsm: memory leak in uplink error path Greg Kroah-Hartman
2012-10-04 21:16 ` [ 41/56] UBI: fix autoresize handling in R/O mode Greg Kroah-Hartman
2012-10-04 21:16 ` [ 42/56] UBI: erase free PEB with bitflip in EC header Greg Kroah-Hartman
2012-10-04 21:16 ` [ 43/56] Yama: handle 32-bit userspace prctl Greg Kroah-Hartman
2012-10-04 21:16 ` [ 44/56] SCSI: ibmvscsi: Fix host config length field overflow Greg Kroah-Hartman
2012-10-04 21:16 ` [ 45/56] SCSI: hpsa: Use LUN reset instead of target reset Greg Kroah-Hartman
2012-10-04 21:16 ` [ 46/56] can: mscan-mpc5xxx: fix return value check in mpc512x_can_get_clock() Greg Kroah-Hartman
2012-10-04 21:16 ` [ 47/56] Input: synaptics - adjust threshold for treating position values as negative Greg Kroah-Hartman
2012-10-04 21:16 ` [ 48/56] remoteproc: select VIRTIO to avoid build breakage Greg Kroah-Hartman
2012-10-04 21:16 ` [ 49/56] remoteproc: fix a potential NULL-dereference on cleanup Greg Kroah-Hartman
2012-10-04 21:16 ` [ 50/56] IPoIB: Fix use-after-free of multicast object Greg Kroah-Hartman
2012-10-04 21:16 ` [ 51/56] IB/srp: Fix use-after-free in srp_reset_req() Greg Kroah-Hartman
2012-10-04 21:16 ` [ 52/56] IB/srp: Avoid having aborted requests hang Greg Kroah-Hartman
2012-10-04 21:16 ` [ 53/56] IB/qib: Fix local access validation for user MRs Greg Kroah-Hartman
2012-10-04 21:16 ` [ 54/56] isci: fix isci_pci_probe() generates warning on efi failure path Greg Kroah-Hartman
2012-10-04 21:16 ` [ 55/56] SCSI: scsi_remove_target: fix softlockup regression on hot remove Greg Kroah-Hartman
2012-10-04 21:16 ` [ 56/56] SCSI: scsi_dh_alua: Enable STPG for unavailable ports 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=20121004211155.428441312@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.