Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit dbc33303 authored by Sarah Sharp's avatar Sarah Sharp
Browse files

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: default avatarSarah Sharp <sarah.a.sharp@linux.intel.com>
parent 4b266541
Loading
Loading
Loading
Loading
+12 −0
Original line number Original line Diff line number Diff line
@@ -1815,6 +1815,8 @@ void xhci_mem_cleanup(struct xhci_hcd *xhci)
	xhci->event_ring = NULL;
	xhci->event_ring = NULL;
	xhci_dbg(xhci, "Freed event ring\n");
	xhci_dbg(xhci, "Freed event ring\n");


	if (xhci->lpm_command)
		xhci_free_command(xhci, xhci->lpm_command);
	xhci->cmd_ring_reserved_trbs = 0;
	xhci->cmd_ring_reserved_trbs = 0;
	if (xhci->cmd_ring)
	if (xhci->cmd_ring)
		xhci_ring_free(xhci, xhci->cmd_ring);
		xhci_ring_free(xhci, xhci->cmd_ring);
@@ -2377,6 +2379,16 @@ int xhci_mem_init(struct xhci_hcd *xhci, gfp_t flags)
	xhci_write_64(xhci, val_64, &xhci->op_regs->cmd_ring);
	xhci_write_64(xhci, val_64, &xhci->op_regs->cmd_ring);
	xhci_dbg_cmd_ptrs(xhci);
	xhci_dbg_cmd_ptrs(xhci);


	xhci->lpm_command = xhci_alloc_command(xhci, true, true, flags);
	if (!xhci->lpm_command)
		goto fail;

	/* Reserve one command ring TRB for disabling LPM.
	 * Since the USB core grabs the shared usb_bus bandwidth mutex before
	 * disabling LPM, we only need to reserve one TRB for all devices.
	 */
	xhci->cmd_ring_reserved_trbs++;

	val = xhci_readl(xhci, &xhci->cap_regs->db_off);
	val = xhci_readl(xhci, &xhci->cap_regs->db_off);
	val &= DBOFF_MASK;
	val &= DBOFF_MASK;
	xhci_dbg(xhci, "// Doorbell array is located at offset 0x%x"
	xhci_dbg(xhci, "// Doorbell array is located at offset 0x%x"
+2 −0
Original line number Original line Diff line number Diff line
@@ -1426,6 +1426,8 @@ struct xhci_hcd {
	/* slot enabling and address device helpers */
	/* slot enabling and address device helpers */
	struct completion	addr_dev;
	struct completion	addr_dev;
	int slot_id;
	int slot_id;
	/* For USB 3.0 LPM enable/disable. */
	struct xhci_command		*lpm_command;
	/* Internal mirror of the HW's dcbaa */
	/* Internal mirror of the HW's dcbaa */
	struct xhci_virt_device	*devs[MAX_HC_SLOTS];
	struct xhci_virt_device	*devs[MAX_HC_SLOTS];
	/* For keeping track of bandwidth domains per roothub. */
	/* For keeping track of bandwidth domains per roothub. */