[PATCH v2 2/2] usb: dwc2: wa for isoc packet tx fifo flush at periodic frame boundary
From: Fabrice Gasnier
Date: Wed Nov 04 2026 - 08:21:31 EST
If an isochronous packet is still being transmitted, when the end of
periodic frame interval elapses, using dma desc on dwc2 controller,
the device wrongly flushes the pending packets from the tx fifo.
This can lead to a huge packet is sent on the bus, leading to the host
finally reset the bus, and re-enumerate it.
Workaround it by tuning the periodic frame interval limit from 80% to 95%,
on the affected cores (2.70a to 4.00a). It makes the issue very unlikely
to occur.
Fixes: 540ccba08599 ("usb: dwc2: gadget: Start and complete DDMA isoc transfers")
Cc: stable@xxxxxxxxxxxxxxx
Signed-off-by: Fabrice Gasnier <fabrice.gasnier@xxxxxxxxxxx>
---
Changes in v2:
- Thinh review comments:
- Fix a typo 'flushes'
- Use DCFG_PERFRINT() macro
- Add DWC2_HS_IOT_REV_1_00a and DWC2_FS_IOT_REV_1_00a core revisions.
- Add a Fixes tag, and Cc stable
---
drivers/usb/dwc2/core.h | 1 +
drivers/usb/dwc2/gadget.c | 15 +++++++++++++++
2 files changed, 16 insertions(+)
diff --git a/drivers/usb/dwc2/core.h b/drivers/usb/dwc2/core.h
index 015a5fb7842d..54c040da0cae 100644
--- a/drivers/usb/dwc2/core.h
+++ b/drivers/usb/dwc2/core.h
@@ -1108,6 +1108,7 @@ struct dwc2_hsotg {
/* DWC OTG HW Release versions */
#define DWC2_CORE_REV_4_30a 0x4f54430a
+#define DWC2_CORE_REV_2_70a 0x4f54270a
#define DWC2_CORE_REV_2_71a 0x4f54271a
#define DWC2_CORE_REV_2_72a 0x4f54272a
#define DWC2_CORE_REV_2_80a 0x4f54280a
diff --git a/drivers/usb/dwc2/gadget.c b/drivers/usb/dwc2/gadget.c
index bdabf3c39da1..b84cb6b2cefa 100644
--- a/drivers/usb/dwc2/gadget.c
+++ b/drivers/usb/dwc2/gadget.c
@@ -3511,6 +3511,21 @@ void dwc2_hsotg_core_init_disconnected(struct dwc2_hsotg *hsotg,
if (hsotg->params.ipg_isoc_en)
dcfg |= DCFG_IPG_ISOC_SUPPORDED;
+ /*
+ * WA for Device Flushes Ongoing ISOC IN Packet at End-of-Periodic-Frame Boundary.
+ * Once passed the end of periodic frame, and the controller is transmitting an
+ * ISOC IN packet, the device flushes the transmit FIFO. Tune periodic frame
+ * interval to 95% instead of 80% to avoid it.
+ */
+ if (using_desc_dma(hsotg) &&
+ ((hsotg->hw_params.snpsid >= DWC2_CORE_REV_2_70a &&
+ hsotg->hw_params.snpsid <= DWC2_CORE_REV_4_00a) ||
+ hsotg->hw_params.snpsid == DWC2_FS_IOT_REV_1_00a ||
+ hsotg->hw_params.snpsid == DWC2_HS_IOT_REV_1_00a)) {
+ dcfg &= ~DCFG_PERFRINT_MASK;
+ dcfg |= DCFG_PERFRINT(DCFG_PERFRINT_LIMIT);
+ }
+
dwc2_writel(hsotg, dcfg, DCFG);
dwc2_hsotg_init_fifo(hsotg);
--
2.43.0