aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb
diff options
context:
space:
mode:
authorSarah Sharp <sarah.a.sharp@linux.intel.com>2012-05-08 10:32:03 -0400
committerSarah Sharp <sarah.a.sharp@linux.intel.com>2012-05-18 18:42:01 -0400
commitdbc33303e457bc9d9179d628951e6b7c7a3f6056 (patch)
tree4c0c1daf3895f65a65e7714a5f0e3e3ea7e12f81 /drivers/usb
parent4b2665418c81c87e7a46df690a443b3d5ac5b088 (diff)
xhci: Reserve one command for USB3 LPM disable.
We want to do everything we can to ensure that USB 3.0 Link Power Management (LPM) can be disabled when it is enabled. If LPM can't be disabled, we can't suspend USB 3.0 devices, or reset them. To make sure we can submit the command to disable LPM, allocate a command in the xhci_hcd structure, and reserve one TRB on the command ring. We only need one command per xHCI driver instance, because LPM is only disabled or enabled while the USB core is holding the bandwidth_mutex that is shared between the xHCI USB 2.0 and USB 3.0 roothubs. The bandwidth_mutex will be held until the command completes, or times out. Signed-off-by: Sarah Sharp <sarah.a.sharp@linux.intel.com>
Diffstat (limited to 'drivers/usb')
-rw-r--r--drivers/usb/host/xhci-mem.c12
-rw-r--r--drivers/usb/host/xhci.h2
2 files changed, 14 insertions, 0 deletions
diff --git a/drivers/usb/host/xhci-mem.c b/drivers/usb/host/xhci-mem.c
index 497ed7723e4..ec4338eec82 100644
--- a/drivers/usb/host/xhci-mem.c
+++ b/drivers/usb/host/xhci-mem.c
@@ -1815,6 +1815,8 @@ void xhci_mem_cleanup(struct xhci_hcd *xhci)
1815 xhci->event_ring = NULL; 1815 xhci->event_ring = NULL;
1816 xhci_dbg(xhci, "Freed event ring\n"); 1816 xhci_dbg(xhci, "Freed event ring\n");
1817 1817
1818 if (xhci->lpm_command)
1819 xhci_free_command(xhci, xhci->lpm_command);
1818 xhci->cmd_ring_reserved_trbs = 0; 1820 xhci->cmd_ring_reserved_trbs = 0;
1819 if (xhci->cmd_ring) 1821 if (xhci->cmd_ring)
1820 xhci_ring_free(xhci, xhci->cmd_ring); 1822 xhci_ring_free(xhci, xhci->cmd_ring);
@@ -2377,6 +2379,16 @@ int xhci_mem_init(struct xhci_hcd *xhci, gfp_t flags)
2377 xhci_write_64(xhci, val_64, &xhci->op_regs->cmd_ring); 2379 xhci_write_64(xhci, val_64, &xhci->op_regs->cmd_ring);
2378 xhci_dbg_cmd_ptrs(xhci); 2380 xhci_dbg_cmd_ptrs(xhci);
2379 2381
2382 xhci->lpm_command = xhci_alloc_command(xhci, true, true, flags);
2383 if (!xhci->lpm_command)
2384 goto fail;
2385
2386 /* Reserve one command ring TRB for disabling LPM.
2387 * Since the USB core grabs the shared usb_bus bandwidth mutex before
2388 * disabling LPM, we only need to reserve one TRB for all devices.
2389 */
2390 xhci->cmd_ring_reserved_trbs++;
2391
2380 val = xhci_readl(xhci, &xhci->cap_regs->db_off); 2392 val = xhci_readl(xhci, &xhci->cap_regs->db_off);
2381 val &= DBOFF_MASK; 2393 val &= DBOFF_MASK;
2382 xhci_dbg(xhci, "// Doorbell array is located at offset 0x%x" 2394 xhci_dbg(xhci, "// Doorbell array is located at offset 0x%x"
diff --git a/drivers/usb/host/xhci.h b/drivers/usb/host/xhci.h
index 59248449b25..f5cb7417f23 100644
--- a/drivers/usb/host/xhci.h
+++ b/drivers/usb/host/xhci.h
@@ -1426,6 +1426,8 @@ struct xhci_hcd {
1426 /* slot enabling and address device helpers */ 1426 /* slot enabling and address device helpers */
1427 struct completion addr_dev; 1427 struct completion addr_dev;
1428 int slot_id; 1428 int slot_id;
1429 /* For USB 3.0 LPM enable/disable. */
1430 struct xhci_command *lpm_command;
1429 /* Internal mirror of the HW's dcbaa */ 1431 /* Internal mirror of the HW's dcbaa */
1430 struct xhci_virt_device *devs[MAX_HC_SLOTS]; 1432 struct xhci_virt_device *devs[MAX_HC_SLOTS];
1431 /* For keeping track of bandwidth domains per roothub. */ 1433 /* For keeping track of bandwidth domains per roothub. */