Hoi,
This patch series fixes a subtle regression introduced in the recent scatter-gather cleanup for the DWC3 USB gadget driver, and follows up with two clean-up patches to simplify and clarify related logic.
Background:
Commit 61440628a4ff ("usb: dwc3: gadget: Cleanup SG handling") removed some redundant state tracking in the DWC3 gadget driver, including how scatter-gather TRBs are reclaimed after use. However, the reclaim logic began relying on the TRB CHN (chain) bit to determine whether TRBs belonged to a chain — which led to missed TRB reclamation in some cases.
This broke userspace-facing protocols like MTP (Media Transfer Protocol) when used via FunctionFS, causing incomplete transfers due to skipped zero-length packets (ZLPs) or improperly reclaimed short TRBs.
The "offending" chunk from 61440628a4ff: 80 ret = dwc3_gadget_ep_reclaim_completed_trb(dep, req, 81 - trb, event, status, true); 82 + trb, event, status, 83 + !!(trb->ctrl & DWC3_TRB_CTRL_CHN));
Patch 1 fixes the issue by ensuring the HWO bit is always cleared on reclaimed TRBs, regardless of the CHN bit.
Patches 2 and 3 follow up with simplifications: - Patch 2 removes the now-redundant `chain` argument to the reclaim function - Patch 3 simplifies the logic in `dwc3_needs_extra_trb()` to make the conditions easier to read and maintain
All three patches have been tested on a imx8mp based hardware, with userspace MTP (viveris/uMTP-Responder) over FunctionFS and resolve the regression while preserving the recent cleanup work.
Signed-off-by: Johannes Schneider johannes.schneider@leica-geosystems.com --- Changes in v2: - dropped Patch 3, as it did change the logic - CC to stable - Link to v1: https://lore.kernel.org/r/20250621-dwc3-fix-gadget-mtp-v1-0-a45e6def71bb@lei...
--- Johannes Schneider (2): usb: dwc3: gadget: Fix TRB reclaim logic for short transfers and ZLPs usb: dwc3: gadget: Simplify TRB reclaim logic by removing redundant 'chain' argument
drivers/usb/dwc3/gadget.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) --- base-commit: d0c22de9995b624f563bc5004d44ac2655712a56 change-id: 20250621-dwc3-fix-gadget-mtp-3c09a6ab84c6
Best regards,
Commit 61440628a4ff ("usb: dwc3: gadget: Cleanup SG handling") updated the TRB reclaim path to use the TRB CHN (Chain) bit to determine whether a TRB was part of a chain. However, this inadvertently changed the behavior of reclaiming the final TRB in some scatter-gather or short transfer cases.
In particular, if the final TRB did not have the CHN bit set, the cleanup path could incorrectly skip clearing the HWO (Hardware Own) bit, leaving stale TRBs in the ring. This resulted in broken data transfer completions in userspace, notably for MTP over FunctionFS.
Fix this by unconditionally clearing the HWO bit during TRB reclaim, regardless of the CHN bit state. This restores correct behavior especially for transfers that require ZLPs or end on non-CHN TRBs.
Fixes: 61440628a4ff ("usb: dwc3: gadget: Cleanup SG handling") Acked-by: Thinh Nguyen Thinh.Nguyen@synopsys.com Signed-off-by: Johannes Schneider johannes.schneider@leica-geosystems.com --- drivers/usb/dwc3/gadget.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c index 321361288935db4b773cd06235a16670a6adda1a..99fbd29d8f46d30df558ceb23d2afe7187b4244c 100644 --- a/drivers/usb/dwc3/gadget.c +++ b/drivers/usb/dwc3/gadget.c @@ -3516,7 +3516,7 @@ static int dwc3_gadget_ep_reclaim_completed_trb(struct dwc3_ep *dep, * We're going to do that here to avoid problems of HW trying * to use bogus TRBs for transfers. */ - if (chain && (trb->ctrl & DWC3_TRB_CTRL_HWO)) + if (trb->ctrl & DWC3_TRB_CTRL_HWO) trb->ctrl &= ~DWC3_TRB_CTRL_HWO;
/*
Hi,
Thanks for your patch.
FYI: kernel test robot notices the stable kernel rule is not satisfied.
The check is based on https://www.kernel.org/doc/html/latest/process/stable-kernel-rules.html#opti...
Rule: add the tag "Cc: stable@vger.kernel.org" in the sign-off area to have the patch automatically included in the stable tree. Subject: [PATCH v2 1/2] usb: dwc3: gadget: Fix TRB reclaim logic for short transfers and ZLPs Link: https://lore.kernel.org/stable/20250624-dwc3-fix-gadget-mtp-v2-1-0e2d9979328...
Now that the TRB reclaim logic always inspects the TRB's CHN (Chain) bit directly to determine whether a TRB is part of a chain, the explicit 'chain' parameter passed into dwc3_gadget_ep_reclaim_completed_trb() is no longer necessary.
This cleanup simplifies the reclaim code by avoiding duplication of chain state tracking, and makes the reclaim logic rely entirely on the hardware descriptor flags — which are already present and accurate at this stage.
No functional changes intended.
Acked-by: Thinh Nguyen Thinh.Nguyen@synopsys.com Signed-off-by: Johannes Schneider johannes.schneider@leica-geosystems.com --- drivers/usb/dwc3/gadget.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c index 99fbd29d8f46d30df558ceb23d2afe7187b4244c..a4a2bf273f943fa112f49979297023a732e0af2e 100644 --- a/drivers/usb/dwc3/gadget.c +++ b/drivers/usb/dwc3/gadget.c @@ -3497,7 +3497,7 @@ static void dwc3_gadget_free_endpoints(struct dwc3 *dwc)
static int dwc3_gadget_ep_reclaim_completed_trb(struct dwc3_ep *dep, struct dwc3_request *req, struct dwc3_trb *trb, - const struct dwc3_event_depevt *event, int status, int chain) + const struct dwc3_event_depevt *event, int status) { unsigned int count;
@@ -3549,7 +3549,8 @@ static int dwc3_gadget_ep_reclaim_completed_trb(struct dwc3_ep *dep, if ((trb->ctrl & DWC3_TRB_CTRL_HWO) && status != -ESHUTDOWN) return 1;
- if (event->status & DEPEVT_STATUS_SHORT && !chain) + if (event->status & DEPEVT_STATUS_SHORT && + !(trb->ctrl & DWC3_TRB_CTRL_CHN)) return 1;
if ((trb->ctrl & DWC3_TRB_CTRL_ISP_IMI) && @@ -3576,8 +3577,7 @@ static int dwc3_gadget_ep_reclaim_trb_sg(struct dwc3_ep *dep, trb = &dep->trb_pool[dep->trb_dequeue];
ret = dwc3_gadget_ep_reclaim_completed_trb(dep, req, - trb, event, status, - !!(trb->ctrl & DWC3_TRB_CTRL_CHN)); + trb, event, status); if (ret) break; }
linux-stable-mirror@lists.linaro.org