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

Commit c9daedf4 authored by Jack Pham's avatar Jack Pham
Browse files

usb: xhci: Release spinlock during command cancellation



When a command fails due to timeout, during the command
cancellation handled in xhci_cancel_cmd() the call to
xhci_abort_cmd_ring() is called while the xhci spinlock
is held and with interrupts disabled. However, if the
abortion itself fails because of a dead host controller,
it may take up to 5 seconds before it returns, during
which time a watchdog will time out. Fix this by releasing
the spin lock prior to attempting to abort the command ring.

Change-Id: I3be0edbbd8a6f1c39ef0c563b10de050527e97e9
Signed-off-by: default avatarJack Pham <jackp@codeaurora.org>
parent 8643ff14
Loading
Loading
Loading
Loading
+6 −6
Original line number Diff line number Diff line
@@ -379,31 +379,31 @@ int xhci_cancel_cmd(struct xhci_hcd *xhci, struct xhci_command *command,
	if (xhci->xhc_state & XHCI_STATE_DYING) {
		xhci_warn(xhci, "Abort the command ring,"
				" but the xHCI is dead.\n");
		retval = -ESHUTDOWN;
		goto fail;
		spin_unlock_irqrestore(&xhci->lock, flags);
		return -ESHUTDOWN;
	}

	/* 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;
		spin_unlock_irqrestore(&xhci->lock, flags);
		return retval;
	}

	spin_unlock_irqrestore(&xhci->lock, flags);

	/* 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;
}