| From f7fac17ca925faa03fc5eb854c081a24075f8bad Mon Sep 17 00:00:00 2001 |
| From: Andrey Smirnov <andrew.smirnov@gmail.com> |
| Date: Wed, 22 May 2019 14:34:01 +0300 |
| Subject: xhci: Convert xhci_handshake() to use readl_poll_timeout_atomic() |
| |
| From: Andrey Smirnov <andrew.smirnov@gmail.com> |
| |
| commit f7fac17ca925faa03fc5eb854c081a24075f8bad upstream. |
| |
| Xhci_handshake() implements the algorithm already captured by |
| readl_poll_timeout_atomic(). Convert the former to use the latter to |
| avoid repetition. |
| |
| Turned out this patch also fixes a bug on the AMD Stoneyridge platform |
| where usleep(1) sometimes takes over 10ms. |
| This means a 5 second timeout can easily take over 15 seconds which will |
| trigger the watchdog and reboot the system. |
| |
| [Add info about patch fixing a bug to commit message -Mathias] |
| Signed-off-by: Andrey Smirnov <andrew.smirnov@gmail.com> |
| Tested-by: Raul E Rangel <rrangel@chromium.org> |
| Reviewed-by: Raul E Rangel <rrangel@chromium.org> |
| Cc: <stable@vger.kernel.org> |
| Signed-off-by: Mathias Nyman <mathias.nyman@linux.intel.com> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| |
| --- |
| drivers/usb/host/xhci.c | 22 ++++++++++------------ |
| 1 file changed, 10 insertions(+), 12 deletions(-) |
| |
| --- a/drivers/usb/host/xhci.c |
| +++ b/drivers/usb/host/xhci.c |
| @@ -9,6 +9,7 @@ |
| */ |
| |
| #include <linux/pci.h> |
| +#include <linux/iopoll.h> |
| #include <linux/irq.h> |
| #include <linux/log2.h> |
| #include <linux/module.h> |
| @@ -52,7 +53,6 @@ static bool td_on_ring(struct xhci_td *t |
| return false; |
| } |
| |
| -/* TODO: copied from ehci-hcd.c - can this be refactored? */ |
| /* |
| * xhci_handshake - spin reading hc until handshake completes or fails |
| * @ptr: address of hc register to be read |
| @@ -69,18 +69,16 @@ static bool td_on_ring(struct xhci_td *t |
| int xhci_handshake(void __iomem *ptr, u32 mask, u32 done, int usec) |
| { |
| u32 result; |
| + int ret; |
| |
| - do { |
| - result = readl(ptr); |
| - if (result == ~(u32)0) /* card removed */ |
| - return -ENODEV; |
| - result &= mask; |
| - if (result == done) |
| - return 0; |
| - udelay(1); |
| - usec--; |
| - } while (usec > 0); |
| - return -ETIMEDOUT; |
| + ret = readl_poll_timeout_atomic(ptr, result, |
| + (result & mask) == done || |
| + result == U32_MAX, |
| + 1, usec); |
| + if (result == U32_MAX) /* card removed */ |
| + return -ENODEV; |
| + |
| + return ret; |
| } |
| |
| /* |