]> www.infradead.org Git - users/hch/dma-mapping.git/commitdiff
usb: dwc3: Wait for EndXfer completion before restoring GUSB2PHYCFG
authorPrashanth K <quic_prashk@quicinc.com>
Tue, 24 Sep 2024 09:32:08 +0000 (15:02 +0530)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Wed, 16 Oct 2024 08:25:28 +0000 (10:25 +0200)
DWC3 programming guide mentions that when operating in USB2.0 speeds,
if GUSB2PHYCFG[6] or GUSB2PHYCFG[8] is set, it must be cleared prior
to issuing commands and may be set again  after the command completes.
But currently while issuing EndXfer command without CmdIOC set, we
wait for 1ms after GUSB2PHYCFG is restored. This results in cases
where EndXfer command doesn't get completed and causes SMMU faults
since requests are unmapped afterwards. Hence restore GUSB2PHYCFG
after waiting for EndXfer command completion.

Cc: stable@vger.kernel.org
Fixes: 1d26ba0944d3 ("usb: dwc3: Wait unconditionally after issuing EndXfer command")
Signed-off-by: Prashanth K <quic_prashk@quicinc.com>
Acked-by: Thinh Nguyen <Thinh.Nguyen@synopsys.com>
Link: https://lore.kernel.org/r/20240924093208.2524531-1-quic_prashk@quicinc.com
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
drivers/usb/dwc3/gadget.c

index 10178e5eda5a3fcdca48783762f5eb7de7fc1853..4959c26d3b71b89347e9118b1fb732b512ba8c05 100644 (file)
@@ -438,6 +438,10 @@ skip_status:
                        dwc3_gadget_ep_get_transfer_index(dep);
        }
 
+       if (DWC3_DEPCMD_CMD(cmd) == DWC3_DEPCMD_ENDTRANSFER &&
+           !(cmd & DWC3_DEPCMD_CMDIOC))
+               mdelay(1);
+
        if (saved_config) {
                reg = dwc3_readl(dwc->regs, DWC3_GUSB2PHYCFG(0));
                reg |= saved_config;
@@ -1715,12 +1719,10 @@ static int __dwc3_stop_active_transfer(struct dwc3_ep *dep, bool force, bool int
        WARN_ON_ONCE(ret);
        dep->resource_index = 0;
 
-       if (!interrupt) {
-               mdelay(1);
+       if (!interrupt)
                dep->flags &= ~DWC3_EP_TRANSFER_STARTED;
-       } else if (!ret) {
+       else if (!ret)
                dep->flags |= DWC3_EP_END_TRANSFER_PENDING;
-       }
 
        dep->flags &= ~DWC3_EP_DELAY_STOP;
        return ret;