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

Commit 40ca9e4e authored by Hemant Kumar's avatar Hemant Kumar
Browse files

usb: XHCI: Implement xhci_handshake_check_state() API



This API is called to handle command timeout which may
happen upon XHCI stack removal. Since handshake is performed
by polling long duration for status, this can cause watchdog
timeout if status does not change for entire duration of
polling. Hence add new API which also checks for xhci state
and exit the handshake if xhci is removed. Use this api and
bailout command abort operation upon XHCI remove.

Change-Id: I9a90b2dd83d76f80e3f6fd4546b949c88850edd3
Signed-off-by: default avatarHemant Kumar <hemantk@codeaurora.org>
parent f854d758
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -356,7 +356,7 @@ static int xhci_abort_cmd_ring(struct xhci_hcd *xhci, unsigned long flags)
	 * In the future we should distinguish between -ENODEV and -ETIMEDOUT
	 * and try to recover a -ETIMEDOUT with a host controller reset.
	 */
	ret = xhci_handshake(&xhci->op_regs->cmd_ring,
	ret = xhci_handshake_check_state(xhci, &xhci->op_regs->cmd_ring,
			CMD_RING_RUNNING, 0, 1000 * 1000);
	if (ret < 0) {
		xhci_err(xhci, "Abort failed to stop command ring: %d\n", ret);
+22 −1
Original line number Diff line number Diff line
@@ -83,6 +83,27 @@ int xhci_handshake(void __iomem *ptr, u32 mask, u32 done, int usec)
	return -ETIMEDOUT;
}

int xhci_handshake_check_state(struct xhci_hcd *xhci,
		void __iomem *ptr, u32 mask, u32 done, int usec)
{
	u32	result;

	do {
		result = readl_relaxed(ptr);
		if (result == ~(u32)0)	/* card removed */
			return -ENODEV;
		/* host removed. Bail out */
		if (xhci->xhc_state & XHCI_STATE_REMOVING)
			return -ENODEV;
		result &= mask;
		if (result == done)
			return 0;
		udelay(1);
		usec--;
	} while (usec > 0);
	return -ETIMEDOUT;
}

/*
 * Disable interrupts and begin the xHCI halting process.
 */
@@ -206,7 +227,7 @@ int xhci_reset(struct xhci_hcd *xhci)
	if (xhci->quirks & XHCI_INTEL_HOST)
		udelay(1000);

	ret = xhci_handshake(&xhci->op_regs->command,
	ret = xhci_handshake_check_state(xhci, &xhci->op_regs->command,
			CMD_RESET, 0, 10 * 1000 * 1000);
	if (ret)
		return ret;
+2 −0
Original line number Diff line number Diff line
@@ -2040,6 +2040,8 @@ int xhci_sec_event_ring_cleanup(struct usb_hcd *hcd, unsigned int intr_num);
/* xHCI host controller glue */
typedef void (*xhci_get_quirks_t)(struct device *, struct xhci_hcd *);
int xhci_handshake(void __iomem *ptr, u32 mask, u32 done, int usec);
int xhci_handshake_check_state(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_start(struct xhci_hcd *xhci);