Commit 0f8f0f79 authored by Prashanth K's avatar Prashanth K Committed by Wen Zhiwei
Browse files

usb: dwc3: Wait for EndXfer completion before restoring GUSB2PHYCFG

stable inclusion
from stable-v6.6.58
commit c3d3501cf896cd6b75f9b018d59247322ac5a4eb
category: bugfix
bugzilla: https://gitee.com/openeuler/kernel/issues/IB3BSC

Reference: https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/commit/?id=c3d3501cf896cd6b75f9b018d59247322ac5a4eb



--------------------------------

commit c96e31252110a84dcc44412e8a7b456b33c3e298 upstream.

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: default avatarPrashanth K <quic_prashk@quicinc.com>
Acked-by: default avatarThinh Nguyen <Thinh.Nguyen@synopsys.com>
Link: https://lore.kernel.org/r/20240924093208.2524531-1-quic_prashk@quicinc.com


Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Signed-off-by: default avatarWen Zhiwei <wenzhiwei@kylinos.cn>
parent 7e5870a7
Loading
Loading
Loading
Loading
+6 −4
Original line number Diff line number Diff line
@@ -438,6 +438,10 @@ int dwc3_send_gadget_ep_cmd(struct dwc3_ep *dep, unsigned int cmd,
			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;
@@ -1734,12 +1738,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;