summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHemant Kumar <hemantk@codeaurora.org>2018-03-05 18:43:38 -0800
committerChandana Kishori Chiluveru <cchiluve@codeaurora.org>2019-03-22 12:05:59 +0530
commit70dc54f5deaa8e64fdf9092a8fe2ba492cbd7e5a (patch)
treeaaeb246d8913bdb19afdeb4801b3b7e248188b08
parent0a0147a03eea011894e164fefda56e442b005389 (diff)
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. Change-Id: I9a90b2dd83d76f80e3f6fd4546b949c88850edd3 Signed-off-by: Hemant Kumar <hemantk@codeaurora.org>
-rw-r--r--drivers/usb/host/xhci.c21
-rw-r--r--drivers/usb/host/xhci.h2
2 files changed, 23 insertions, 0 deletions
diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c
index 3e11317db602..0ccd5cec42ff 100644
--- a/drivers/usb/host/xhci.c
+++ b/drivers/usb/host/xhci.c
@@ -77,6 +77,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.
*/
diff --git a/drivers/usb/host/xhci.h b/drivers/usb/host/xhci.h
index b3454c06bb0c..dd96dfa28718 100644
--- a/drivers/usb/host/xhci.h
+++ b/drivers/usb/host/xhci.h
@@ -1835,6 +1835,8 @@ int xhci_sec_event_ring_cleanup(struct usb_hcd *hcd, unsigned 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_reset(struct xhci_hcd *xhci);