From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from mail-pg1-f176.google.com (mail-pg1-f176.google.com [209.85.215.176]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 3033647A0BA for ; Fri, 5 Jun 2026 07:27:21 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.215.176 ARC-Seal:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1780644443; cv=none; b=bSXl8oTlTw5hgQbQdoL9O8ryOOJJMnFc3tIYMza2/z3dWtxSb7Z1nbg6ASngTR8/aKLg1AxywL2tQ486whFDawDhYSoCKbIh8iQt+8NU1/IFTL86cWVuzmZZ3wr2hUXTkJ80M7SKbwL25GRGObhdsB4taRfbxTlS7s1ByZ7q/PI= ARC-Message-Signature:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1780644443; c=relaxed/simple; bh=J5yo9hb4DiG2V5nvVCbiSN6dy3FUvV2ZxvrOFGt4cIg=; h=Message-ID:Date:From:To:Cc:Subject:MIME-Version:Content-Type; b=aQdVAE4mP2vc0HrFtv4RJx45iD+eGv97A/HHOEBvAYCBasTq5AzY6hyOgpkeZHg52pAgt+ijPWoIzn17BXqxiBJ3GS1q4Okampg3mXDfyNEXYAwTFwXDLazigldsSAwNtlTx7Rfw3OUDdwSyc+xqIukY3HtxtLLSj8LKmflGtZY= ARC-Authentication-Results:i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=KE0RKmNq; arc=none smtp.client-ip=209.85.215.176 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="KE0RKmNq" Received: by mail-pg1-f176.google.com with SMTP id 41be03b00d2f7-c858dc05ee3so1046029a12.2 for ; Fri, 05 Jun 2026 00:27:21 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1780644440; x=1781249240; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:subject:cc:to:from:date :message-id:from:to:cc:subject:date:message-id:reply-to; bh=610gyzIqBO1JVhEX585ySATLb6xibPYUqJZc1nejfdI=; b=KE0RKmNq32w+Vxlo7XfRShbrnhFxSuPbHXS1TyWihVBdqVGHNYFwfxlOGHJwtu2LA2 Hf3l7JX6UmXQUJdKVmN0ugAdAhLkq9z68zhzqiOo02PprOk1Ios4pLliCp458NBzotJo eOdCW9bqVBm72aGHrCZqL4aDIiS1+eLLsDbj8AbX/YphXW5VdkcNXVx811Q9YkjWQQ3q AK/RvOu5gIzXB/hidRntjsOJeCkwDfHHpKywJPBmBakoLZQKPz+3xu5tpEIztRP+o9Ci z4m7v049R+4cSVkct0cehURfBqoXoOP1JBkL1zdPehgHrcP2e6SGVBjPh3S0Lh/HkIZM Y1cw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1780644440; x=1781249240; h=content-transfer-encoding:mime-version:subject:cc:to:from:date :message-id:x-gm-gg:x-gm-message-state:from:to:cc:subject:date :message-id:reply-to; bh=610gyzIqBO1JVhEX585ySATLb6xibPYUqJZc1nejfdI=; b=DFzy/JjJ2L6iZ80EpICQRXbBWr9mdqpJQtROBvJX0vD+TV4NiP5BjEq7r2Zoy+droa eGpUpv7/wC8vbSwSAQi5M02gGY/I/ks15jfvNeNpt/54zgr44u/2UUdE+3ST1rbJb8lh DOzHRksCjeLRvbq9cSJaDXWvHtTQFw2Pah2sP27PPh4akRdbaTrzKcI4GOxzG971LYSp WvYqtcRxc2L37yClllKCNWBlJDveNjSqcZ0SafJA/xPn6Le4pQBz4y24KKwOMF+vkFd3 wiHxjhrWJvC+F/g2f+QTPNz8v/Lg2AWkG67qgKbrhWBTjgjvmj8VdQjjRX25Rr2TjCbs IoYQ== X-Gm-Message-State: AOJu0Yy3q1uWnvVHkIy0coCoshvbN1RUlWnxWlsE00gRSmbhuL5jiIDq J492q/xp9saz9MHgqjGZSP5NYWN+unDQonWx5Xd3/dq83OPK03bjbAImjpA2JThQqro= X-Gm-Gg: Acq92OFprm/pHnbjZM8xOkpZDXl5vqd7yAXc9k9loV2ZR5H8+H+wQYVQyj0iQJFJpdV dApwQqPNRleXT2j9Pv/7Qrx4WyhivqVfOq/SyAZmh/EGRk+EoSvdCCfnF/300Q6GB0ezYV6knm1 DiLB1MYZvn4v6mnl4fFG6Dfw2yEvKPj89XVtUYUfSPHpxfAJWhPgpsq3WHuWN9HfEISrDKgbfef 2hAd/jHbBspolFBovrhJgEs23tP3BvNbxg02cRv8vIswnuauowGzJDpLSZoOfzCbsBu4+81BKNH cv4lI2+w+GwgjiD+BdFiG7VD6KHbHLoASAvIHurglIF38s3X63KzaZQnAY1Vp57ATGUI3GGZeZV j6awMUPpM8DNFCKuU6oIF5Fax0z/jiEureMJrad+30LWCwmziF5SUGWfItV6f/h//qpGZHTdOOl XU37ajri7STN+YRFoWKQQv2hm5p3ypm1fHXqPsf8XbPuAdjNc40SmRviY+T9VuoH6p9SDH7qNzI /I= X-Received: by 2002:a05:6a21:68b:b0:3b4:c9d5:cd5b with SMTP id adf61e73a8af0-3b4ccd5dcc5mr3306756637.13.1780644440283; Fri, 05 Jun 2026 00:27:20 -0700 (PDT) Received: from viku.office.rr.lan (fs79022602.tkyc410.ap.nuro.jp. [121.2.38.2]) by smtp.gmail.com with ESMTPSA id 41be03b00d2f7-c85df04311bsm6839996a12.9.2026.06.05.00.27.18 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 05 Jun 2026 00:27:19 -0700 (PDT) Message-ID: <6a227a57.b453d089.3d0874.3012@mx.google.com> Date: Fri, 05 Jun 2026 00:27:19 -0700 (PDT) From: Vishal Kumar 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 Precedence: bulk X-Mailing-List: linux-usb@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 8bit From: Vishal Kumar 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 Cc: Jonathan Hunter Cc: Dmitry Osipenko Cc: linux-tegra@vger.kernel.org Signed-off-by: Vishal Kumar --- 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