From: Vishal Kumar <vishalmimani008@gmail.com>
To: linux-usb@vger.kernel.org
Cc: linux-tegra@vger.kernel.org, stable@vger.kernel.org,
gregkh@linuxfoundation.org, thierry.reding@gmail.com,
jonathanh@nvidia.com, digetx@gmail.com
Subject: [PATCH] usb: gadget: tegra-xudc: drain EP pipeline before DMA unmap
Date: Fri, 05 Jun 2026 00:27:19 -0700 (PDT) [thread overview]
Message-ID: <6a227a57.b453d089.3d0874.3012@mx.google.com> (raw)
From: Vishal Kumar <vishalmimani008@gmail.com>
Date: Fri, 5 Jun 2026 14:08:54 +0900
Subject: [PATCH] usb: gadget: tegra-xudc: drain EP pipeline before DMA
unmap
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
On Tegra186/194/234 the XUDC appears to post a transfer-completion
event when the DMA write is dispatched to the AXI interconnect, before
the store is committed to memory. Under SMMU strict mode dma_unmap()
synchronously removes the IOVA TLB entry. If an in-flight AXI write
to that IOVA has not yet been committed, the SMMU raises a translation
fault (fsr=0x402) that permanently wedges the bulk endpoint; the host
cdc_ncm TX queue stalls and fires NETDEV WATCHDOG after 5 s.
Fix for non-control endpoints: poll EP_THREAD_ACTIVE until the endpoint
sequencer goes idle before calling dma_unmap(). Follow the poll with an
MMIO read-back that orders prior CPU writes to device memory. Only
after that does dma_unmap() invalidate the TLB entry.
On timeout, skip the dma_unmap to avoid triggering the SMMU fault. The
DMA mapping leaks, but the hardware is already in an unrecoverable state
at that point.
ep_wait_for_inactive() uses readl_poll_timeout_atomic() (1 µs poll,
100 µs timeout), already called from IRQ context in
__tegra_xudc_ep_dequeue(). Change its return type from void to int so
both call sites can detect and report a timeout.
Control endpoints (EP0) are excluded: their completions go through the
control-transfer state machine where the DMA is fully committed before
req_done is called.
Fixes: d720f0f7bfa0 ("usb: gadget: Add Tegra XUSB device mode controller driver")
Cc: stable@vger.kernel.org
Cc: Thierry Reding <thierry.reding@gmail.com>
Cc: Jonathan Hunter <jonathanh@nvidia.com>
Cc: Dmitry Osipenko <digetx@gmail.com>
Cc: linux-tegra@vger.kernel.org
Signed-off-by: Vishal Kumar <vishalmimani008@gmail.com>
---
drivers/usb/gadget/udc/tegra-xudc.c | 35 ++++++++++++++++++++++++-----
1 file changed, 30 insertions(+), 5 deletions(-)
diff --git a/drivers/usb/gadget/udc/tegra-xudc.c b/drivers/usb/gadget/udc/tegra-xudc.c
index e9d33be02..8f1d52af0 100644
--- a/drivers/usb/gadget/udc/tegra-xudc.c
+++ b/drivers/usb/gadget/udc/tegra-xudc.c
@@ -1026,9 +1026,9 @@ static void ep_wait_for_stopped(struct tegra_xudc *xudc, unsigned int ep)
xudc_writel(xudc, BIT(ep), EP_STOPPED);
}
-static void ep_wait_for_inactive(struct tegra_xudc *xudc, unsigned int ep)
+static int ep_wait_for_inactive(struct tegra_xudc *xudc, unsigned int ep)
{
- xudc_readl_poll(xudc, EP_THREAD_ACTIVE, BIT(ep), 0);
+ return xudc_readl_poll(xudc, EP_THREAD_ACTIVE, BIT(ep), 0);
}
static void tegra_xudc_req_done(struct tegra_xudc_ep *ep,
@@ -1049,8 +1049,31 @@ static void tegra_xudc_req_done(struct tegra_xudc_ep *ep,
(xudc->setup_state ==
DATA_STAGE_XFER));
} else {
- usb_gadget_unmap_request(&xudc->gadget, &req->usb_req,
- usb_endpoint_dir_in(ep->desc));
+ /*
+ * Drain the endpoint DMA pipeline before unmapping.
+ *
+ * Under SMMU strict mode dma_unmap() synchronously
+ * invalidates the IOVA TLB entry. On Tegra186/194/234 the
+ * XUDC appears to post the completion event when the DMA
+ * write is dispatched to the AXI interconnect, before the
+ * store is committed to memory. A subsequent dma_unmap()
+ * can remove the IOVA translation while the write is still
+ * in-flight, triggering a translation fault (fsr=0x402) that
+ * permanently wedges the bulk endpoint.
+ *
+ * Wait for EP_THREAD_ACTIVE to clear (endpoint sequencer
+ * idle). On timeout skip the unmap to avoid the SMMU fault;
+ * the DMA mapping leaks but the hardware is already in an
+ * unrecoverable state.
+ */
+ if (!WARN_ONCE(ep_wait_for_inactive(xudc, ep->index),
+ "ep%u: DMA drain timed out; skipping dma_unmap\n",
+ ep->index)) {
+ /* MMIO read-back orders prior CPU writes to device memory. */
+ xudc_readl(xudc, EP_THREAD_ACTIVE);
+ usb_gadget_unmap_request(&xudc->gadget, &req->usb_req,
+ usb_endpoint_dir_in(ep->desc));
+ }
}
spin_unlock(&xudc->lock);
@@ -1451,7 +1474,9 @@ __tegra_xudc_ep_dequeue(struct tegra_xudc_ep *ep,
/* Halt DMA for this endpoint. */
if (ep_ctx_read_state(ep->context) == EP_STATE_RUNNING) {
ep_pause(xudc, ep->index);
- ep_wait_for_inactive(xudc, ep->index);
+ if (ep_wait_for_inactive(xudc, ep->index))
+ dev_warn(xudc->dev, "ep%u: DMA drain timed out during dequeue\n",
+ ep->index);
}
deq_trb = trb_phys_to_virt(ep, ep_ctx_read_deq_ptr(ep->context));
--
2.25.1
next reply other threads:[~2026-06-05 7:27 UTC|newest]
Thread overview: 4+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-06-05 7:27 Vishal Kumar [this message]
2026-06-05 14:59 ` [PATCH] usb: gadget: tegra-xudc: drain EP pipeline before DMA unmap Greg KH
-- strict thread matches above, loose matches on Subject: below --
2026-06-06 2:40 [PATCH] usb: gadget: tegra-xudc: drain EP pipeline before dma_unmap Vishal Kumar
[not found] <6a226993.a5745248.34e478.a9cd@mx.google.com>
2026-06-05 6:35 ` [PATCH] usb: gadget: tegra-xudc: drain EP pipeline before DMA unmap Greg KH
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=6a227a57.b453d089.3d0874.3012@mx.google.com \
--to=vishalmimani008@gmail.com \
--cc=digetx@gmail.com \
--cc=gregkh@linuxfoundation.org \
--cc=jonathanh@nvidia.com \
--cc=linux-tegra@vger.kernel.org \
--cc=linux-usb@vger.kernel.org \
--cc=stable@vger.kernel.org \
--cc=thierry.reding@gmail.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
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.