* [PATCH] usb: mtu3: wait for TX FIFO to drain before disconnect
@ 2026-07-17 13:05 Carlo Caione
2026-07-17 15:21 ` Marek Vasut
0 siblings, 1 reply; 3+ messages in thread
From: Carlo Caione @ 2026-07-17 13:05 UTC (permalink / raw)
To: GSS_MTK_Uboot_upstream, Bin Meng, Chunfeng Yun, u-boot
Cc: Ryder Lee, Weijie Gao, Igor Belwon, David Lechner, Julien Stephan,
Marek Vasut, Tom Rini, Vitor Sato Eschholz, Carlo Caione
Fastboot unregisters the USB gadget from the completion callback of
its final OKAY response. MTU3 QMU can report that request complete
while bytes remain in the endpoint TX FIFO. Disabling the USB function
immediately can therefore disconnect the host before it receives the
response.
Before selecting the high-speed or SuperSpeed disconnect operation,
poll the FIFO state of enabled IN endpoints that have no pending
requests. Bound the wait to 1 ms and proceed with the disconnect on
timeout. Endpoints with pending requests are skipped so an ordinary
disconnect does not wait for an active transfer.
Fixes: e09b88cd083d ("usb: add MediaTek USB3 DRD driver")
Signed-off-by: Vitor Sato Eschholz <vsatoes@baylibre.com>
Signed-off-by: Carlo Caione <ccaione@baylibre.com>
---
drivers/usb/mtu3/mtu3_core.c | 29 +++++++++++++++++++++++++++++
1 file changed, 29 insertions(+)
diff --git a/drivers/usb/mtu3/mtu3_core.c b/drivers/usb/mtu3/mtu3_core.c
index 2f5cc9b1480..aad03f3265a 100644
--- a/drivers/usb/mtu3/mtu3_core.c
+++ b/drivers/usb/mtu3/mtu3_core.c
@@ -10,10 +10,13 @@
#include <linux/log2.h>
#include <linux/bitmap.h>
+#include <linux/iopoll.h>
#include "mtu3.h"
#include "mtu3_dr.h"
+#define MTU3_TX_FIFO_DRAIN_TIMEOUT_US 1000
+
static int ep_fifo_alloc(struct mtu3_ep *mep, u32 seg_size)
{
struct mtu3_fifo_info *fifo = mep->fifo;
@@ -66,6 +69,28 @@ static inline void mtu3_ss_func_set(struct mtu3 *mtu, bool enable)
dev_dbg(mtu->dev, "USB3_EN = %d\n", !!enable);
}
+static void mtu3_wait_for_tx_fifo_empty(struct mtu3 *mtu)
+{
+ struct mtu3_ep *mep;
+ u32 value;
+ int ret;
+ int i;
+
+ for (i = 1; i < mtu->num_eps; i++) {
+ mep = mtu->in_eps + i;
+ if (!(mep->flags & MTU3_EP_ENABLED) ||
+ !list_empty(&mep->req_list))
+ continue;
+
+ ret = readl_poll_timeout(mtu->mac_base + MU3D_EP_TXCR0(i),
+ value, value & TX_FIFOEMPTY,
+ MTU3_TX_FIFO_DRAIN_TIMEOUT_US);
+ if (ret)
+ dev_warn(mtu->dev, "%s TX FIFO did not drain\n",
+ mep->name);
+ }
+}
+
/* set/clear U3D HS device soft connect */
static inline void mtu3_hs_softconn_set(struct mtu3 *mtu, bool enable)
{
@@ -263,6 +288,10 @@ void mtu3_ep_stall_set(struct mtu3_ep *mep, bool set)
void mtu3_dev_on_off(struct mtu3 *mtu, int is_on)
{
+ /* QMU completion may precede transmission from the TX FIFO. */
+ if (!is_on)
+ mtu3_wait_for_tx_fifo_empty(mtu);
+
if (mtu->is_u3_ip && mtu->speed >= USB_SPEED_SUPER)
mtu3_ss_func_set(mtu, is_on);
else
---
base-commit: 96c308b8d2a6a1496c0a7366db9a7becf42d2454
change-id: 20260717-ccaione-upstream-mtu3-tx-fifo-drain-fe4b66e5c1e4
Best regards,
--
Carlo Caione <ccaione@baylibre.com>
^ permalink raw reply related [flat|nested] 3+ messages in thread* Re: [PATCH] usb: mtu3: wait for TX FIFO to drain before disconnect
2026-07-17 13:05 [PATCH] usb: mtu3: wait for TX FIFO to drain before disconnect Carlo Caione
@ 2026-07-17 15:21 ` Marek Vasut
2026-07-18 10:15 ` Carlo Caione
0 siblings, 1 reply; 3+ messages in thread
From: Marek Vasut @ 2026-07-17 15:21 UTC (permalink / raw)
To: Carlo Caione, GSS_MTK_Uboot_upstream, Bin Meng, Chunfeng Yun,
u-boot
Cc: Ryder Lee, Weijie Gao, Igor Belwon, David Lechner, Julien Stephan,
Marek Vasut, Tom Rini, Vitor Sato Eschholz
On 7/17/26 3:05 PM, Carlo Caione wrote:
[...]
> @@ -66,6 +69,28 @@ static inline void mtu3_ss_func_set(struct mtu3 *mtu, bool enable)
> dev_dbg(mtu->dev, "USB3_EN = %d\n", !!enable);
> }
>
> +static void mtu3_wait_for_tx_fifo_empty(struct mtu3 *mtu)
> +{
> + struct mtu3_ep *mep;
> + u32 value;
> + int ret;
> + int i;
> +
> + for (i = 1; i < mtu->num_eps; i++) {
> + mep = mtu->in_eps + i;
> + if (!(mep->flags & MTU3_EP_ENABLED) ||
> + !list_empty(&mep->req_list))
> + continue;
> +
> + ret = readl_poll_timeout(mtu->mac_base + MU3D_EP_TXCR0(i),
> + value, value & TX_FIFOEMPTY,
> + MTU3_TX_FIFO_DRAIN_TIMEOUT_US);
> + if (ret)
> + dev_warn(mtu->dev, "%s TX FIFO did not drain\n",
> + mep->name);
Shouldn't there be some interface reset on failure ?
Shouldn't the failure be propagated ?
^ permalink raw reply [flat|nested] 3+ messages in thread* Re: [PATCH] usb: mtu3: wait for TX FIFO to drain before disconnect
2026-07-17 15:21 ` Marek Vasut
@ 2026-07-18 10:15 ` Carlo Caione
0 siblings, 0 replies; 3+ messages in thread
From: Carlo Caione @ 2026-07-18 10:15 UTC (permalink / raw)
To: Marek Vasut, Carlo Caione, GSS_MTK_Uboot_upstream, Bin Meng,
Chunfeng Yun, u-boot
Cc: Ryder Lee, Weijie Gao, Igor Belwon, David Lechner, Julien Stephan,
Marek Vasut, Tom Rini, Vitor Sato Eschholz
On Fri Jul 17, 2026 at 5:21 PM CEST, Marek Vasut wrote:
> On 7/17/26 3:05 PM, Carlo Caione wrote:
>
> [...]
>
>> @@ -66,6 +69,28 @@ static inline void mtu3_ss_func_set(struct mtu3 *mtu, bool enable)
>> dev_dbg(mtu->dev, "USB3_EN = %d\n", !!enable);
>> }
>>
>> +static void mtu3_wait_for_tx_fifo_empty(struct mtu3 *mtu)
>> +{
>> + struct mtu3_ep *mep;
>> + u32 value;
>> + int ret;
>> + int i;
>> +
>> + for (i = 1; i < mtu->num_eps; i++) {
>> + mep = mtu->in_eps + i;
>> + if (!(mep->flags & MTU3_EP_ENABLED) ||
>> + !list_empty(&mep->req_list))
>> + continue;
>> +
>> + ret = readl_poll_timeout(mtu->mac_base + MU3D_EP_TXCR0(i),
>> + value, value & TX_FIFOEMPTY,
>> + MTU3_TX_FIFO_DRAIN_TIMEOUT_US);
>> + if (ret)
>> + dev_warn(mtu->dev, "%s TX FIFO did not drain\n",
>> + mep->name);
> Shouldn't there be some interface reset on failure ?
Agree, I'll issue a reset.
> Shouldn't the failure be propagated ?
I'll propagate -ETIMEDOUT in v2.
Thanks,
--
Carlo Caione
^ permalink raw reply [flat|nested] 3+ messages in thread
end of thread, other threads:[~2026-07-18 10:16 UTC | newest]
Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-07-17 13:05 [PATCH] usb: mtu3: wait for TX FIFO to drain before disconnect Carlo Caione
2026-07-17 15:21 ` Marek Vasut
2026-07-18 10:15 ` Carlo Caione
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.