* [PATCH v2] usb: XHCI: Implement xhci_handshake_check_state() API
@ 2023-09-19 8:58 Udipto Goswami
2023-10-03 5:41 ` Udipto Goswami
0 siblings, 1 reply; 3+ messages in thread
From: Udipto Goswami @ 2023-09-19 8:58 UTC (permalink / raw)
To: Mathias Nyman; +Cc: Greg Kroah-Hartman, linux-usb, Udipto Goswami
In some situations where xhci removal happens parallel to
xhci_handshake, we enoughter a scenario where the
xhci_handshake will fails because the status does not change
the entire duration of polling. This causes the xhci_handshake
to timeout resulting in long wait which might lead to watchdog
timeout.
The API handles command timeout which may happen upon XHCI
stack removal. Check for xhci state and exit the handshake if
xhci is removed.
Signed-off-by: Udipto Goswami <quic_ugoswami@quicinc.com>
---
v2: Fixed compilation error.
drivers/usb/host/xhci-ring.c | 5 +++--
drivers/usb/host/xhci.c | 21 ++++++++++++++++++++-
drivers/usb/host/xhci.h | 2 ++
3 files changed, 25 insertions(+), 3 deletions(-)
diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c
index 1dde53f6eb31..26add6c23a1d 100644
--- a/drivers/usb/host/xhci-ring.c
+++ b/drivers/usb/host/xhci-ring.c
@@ -450,8 +450,9 @@ 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,
- CMD_RING_RUNNING, 0, 5 * 1000 * 1000);
+ ret = xhci_handshake_check_state(xhci, &xhci->op_regs->cmd_ring,
+ CMD_RING_RUNNING, 0, 5 * 1000 * 1000,
+ XHCI_STATE_REMOVING);
if (ret < 0) {
xhci_err(xhci, "Abort failed to stop command ring: %d\n", ret);
xhci_halt(xhci);
diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c
index e1b1b64a0723..95b4c63dbeba 100644
--- a/drivers/usb/host/xhci.c
+++ b/drivers/usb/host/xhci.c
@@ -84,6 +84,24 @@ int xhci_handshake(void __iomem *ptr, u32 mask, u32 done, u64 timeout_us)
/*
* Disable interrupts and begin the xHCI halting process.
*/
+int xhci_handshake_check_state(struct xhci_hcd *xhci, void __iomem *ptr,
+ u32 mask, u32 done, int usec, unsigned int exit_state)
+{
+ u32 result;
+ int ret;
+
+ ret = readl_poll_timeout_atomic(ptr, result,
+ (result & mask) == done ||
+ result == U32_MAX ||
+ xhci->xhc_state & exit_state,
+ 1, usec);
+
+ if (result == U32_MAX || xhci->xhc_state & exit_state)
+ return -ENODEV;
+
+ return ret;
+}
+
void xhci_quiesce(struct xhci_hcd *xhci)
{
u32 halted;
@@ -201,7 +219,8 @@ int xhci_reset(struct xhci_hcd *xhci, u64 timeout_us)
if (xhci->quirks & XHCI_INTEL_HOST)
udelay(1000);
- ret = xhci_handshake(&xhci->op_regs->command, CMD_RESET, 0, timeout_us);
+ ret = xhci_handshake_check_state(xhci, &xhci->op_regs->command,
+ CMD_RESET, 0, timeout_us, XHCI_STATE_REMOVING);
if (ret)
return ret;
diff --git a/drivers/usb/host/xhci.h b/drivers/usb/host/xhci.h
index 7e282b4522c0..06d5a90dedd5 100644
--- a/drivers/usb/host/xhci.h
+++ b/drivers/usb/host/xhci.h
@@ -2119,6 +2119,8 @@ void xhci_free_container_ctx(struct xhci_hcd *xhci,
/* 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, u64 timeout_us);
+int xhci_handshake_check_state(struct xhci_hcd *xhci, void __iomem *ptr,
+ u32 mask, u32 done, int usec, unsigned int exit_state);
void xhci_quiesce(struct xhci_hcd *xhci);
int xhci_halt(struct xhci_hcd *xhci);
int xhci_start(struct xhci_hcd *xhci);
--
2.17.1
^ permalink raw reply related [flat|nested] 3+ messages in thread
* Re: [PATCH v2] usb: XHCI: Implement xhci_handshake_check_state() API
2023-09-19 8:58 [PATCH v2] usb: XHCI: Implement xhci_handshake_check_state() API Udipto Goswami
@ 2023-10-03 5:41 ` Udipto Goswami
2023-10-04 14:53 ` Mathias Nyman
0 siblings, 1 reply; 3+ messages in thread
From: Udipto Goswami @ 2023-10-03 5:41 UTC (permalink / raw)
To: Mathias Nyman; +Cc: Greg Kroah-Hartman, linux-usb
On 9/19/2023 2:28 PM, Udipto Goswami wrote:
> In some situations where xhci removal happens parallel to
> xhci_handshake, we enoughter a scenario where the
> xhci_handshake will fails because the status does not change
> the entire duration of polling. This causes the xhci_handshake
> to timeout resulting in long wait which might lead to watchdog
> timeout.
>
> The API handles command timeout which may happen upon XHCI
> stack removal. Check for xhci state and exit the handshake if
> xhci is removed.
>
> Signed-off-by: Udipto Goswami <quic_ugoswami@quicinc.com>
> ---
> v2: Fixed compilation error.
>
> drivers/usb/host/xhci-ring.c | 5 +++--
> drivers/usb/host/xhci.c | 21 ++++++++++++++++++++-
> drivers/usb/host/xhci.h | 2 ++
> 3 files changed, 25 insertions(+), 3 deletions(-)
>
> diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c
> index 1dde53f6eb31..26add6c23a1d 100644
> --- a/drivers/usb/host/xhci-ring.c
> +++ b/drivers/usb/host/xhci-ring.c
> @@ -450,8 +450,9 @@ 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,
> - CMD_RING_RUNNING, 0, 5 * 1000 * 1000);
> + ret = xhci_handshake_check_state(xhci, &xhci->op_regs->cmd_ring,
> + CMD_RING_RUNNING, 0, 5 * 1000 * 1000,
> + XHCI_STATE_REMOVING);
> if (ret < 0) {
> xhci_err(xhci, "Abort failed to stop command ring: %d\n", ret);
> xhci_halt(xhci);
> diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c
> index e1b1b64a0723..95b4c63dbeba 100644
> --- a/drivers/usb/host/xhci.c
> +++ b/drivers/usb/host/xhci.c
> @@ -84,6 +84,24 @@ int xhci_handshake(void __iomem *ptr, u32 mask, u32 done, u64 timeout_us)
> /*
> * Disable interrupts and begin the xHCI halting process.
> */
> +int xhci_handshake_check_state(struct xhci_hcd *xhci, void __iomem *ptr,
> + u32 mask, u32 done, int usec, unsigned int exit_state)
> +{
> + u32 result;
> + int ret;
> +
> + ret = readl_poll_timeout_atomic(ptr, result,
> + (result & mask) == done ||
> + result == U32_MAX ||
> + xhci->xhc_state & exit_state,
> + 1, usec);
> +
> + if (result == U32_MAX || xhci->xhc_state & exit_state)
> + return -ENODEV;
> +
> + return ret;
> +}
> +
> void xhci_quiesce(struct xhci_hcd *xhci)
> {
> u32 halted;
> @@ -201,7 +219,8 @@ int xhci_reset(struct xhci_hcd *xhci, u64 timeout_us)
> if (xhci->quirks & XHCI_INTEL_HOST)
> udelay(1000);
>
> - ret = xhci_handshake(&xhci->op_regs->command, CMD_RESET, 0, timeout_us);
> + ret = xhci_handshake_check_state(xhci, &xhci->op_regs->command,
> + CMD_RESET, 0, timeout_us, XHCI_STATE_REMOVING);
> if (ret)
> return ret;
>
> diff --git a/drivers/usb/host/xhci.h b/drivers/usb/host/xhci.h
> index 7e282b4522c0..06d5a90dedd5 100644
> --- a/drivers/usb/host/xhci.h
> +++ b/drivers/usb/host/xhci.h
> @@ -2119,6 +2119,8 @@ void xhci_free_container_ctx(struct xhci_hcd *xhci,
> /* 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, u64 timeout_us);
> +int xhci_handshake_check_state(struct xhci_hcd *xhci, void __iomem *ptr,
> + u32 mask, u32 done, int usec, unsigned int exit_state);
> void xhci_quiesce(struct xhci_hcd *xhci);
> int xhci_halt(struct xhci_hcd *xhci);
> int xhci_start(struct xhci_hcd *xhci);
Hi All,
Gentle Reminder on this.
Thanks,
-Udipto
^ permalink raw reply [flat|nested] 3+ messages in thread
* Re: [PATCH v2] usb: XHCI: Implement xhci_handshake_check_state() API
2023-10-03 5:41 ` Udipto Goswami
@ 2023-10-04 14:53 ` Mathias Nyman
0 siblings, 0 replies; 3+ messages in thread
From: Mathias Nyman @ 2023-10-04 14:53 UTC (permalink / raw)
To: Udipto Goswami, Mathias Nyman; +Cc: Greg Kroah-Hartman, linux-usb
On 3.10.2023 8.41, Udipto Goswami wrote:
>
>
> On 9/19/2023 2:28 PM, Udipto Goswami wrote:
>> In some situations where xhci removal happens parallel to
>> xhci_handshake, we enoughter a scenario where the
>> xhci_handshake will fails because the status does not change
>> the entire duration of polling. This causes the xhci_handshake
>> to timeout resulting in long wait which might lead to watchdog
>> timeout.
>>
>> The API handles command timeout which may happen upon XHCI
>> stack removal. Check for xhci state and exit the handshake if
>> xhci is removed.
>>
>> Signed-off-by: Udipto Goswami <quic_ugoswami@quicinc.com>
>> ---
>> v2: Fixed compilation error.
>>
...
>
> Hi All,
>
> Gentle Reminder on this.
>
Thanks, added to queue
Modified the commit message a bit
-Mathias
^ permalink raw reply [flat|nested] 3+ messages in thread
end of thread, other threads:[~2023-10-04 14:51 UTC | newest]
Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2023-09-19 8:58 [PATCH v2] usb: XHCI: Implement xhci_handshake_check_state() API Udipto Goswami
2023-10-03 5:41 ` Udipto Goswami
2023-10-04 14:53 ` Mathias Nyman
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).