From: Udipto Goswami quic_ugoswami@quicinc.com
stable inclusion from stable-v5.10.101 commit 3bfca38914807293faa3d9b748bb1bec894e909a bugzilla: https://gitee.com/openeuler/kernel/issues/I5669Z
Reference: https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/commit/?id=...
--------------------------------
commit 117b4e96c7f362eb6459543883fc07f77662472c upstream.
With CPU re-ordering on write instructions, there might be a chance that the HWO is set before the TRB is updated with the new mapped buffer address. And in the case where core is processing a list of TRBs it is possible that it fetched the TRBs when the HWO is set but before the buffer address is updated. Prevent this by adding a memory barrier before the HWO is updated to ensure that the core always process the updated TRBs.
Fixes: f6bafc6a1c9d ("usb: dwc3: convert TRBs into bitshifts") Cc: stable stable@vger.kernel.org Reviewed-by: Pavankumar Kondeti quic_pkondeti@quicinc.com Signed-off-by: Udipto Goswami quic_ugoswami@quicinc.com Link: https://lore.kernel.org/r/1644207958-18287-1-git-send-email-quic_ugoswami@qu... Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org Signed-off-by: Yu Liao liaoyu15@huawei.com Reviewed-by: Wei Li liwei391@huawei.com Signed-off-by: Zheng Zengkai zhengzengkai@huawei.com --- drivers/usb/dwc3/gadget.c | 13 +++++++++++++ 1 file changed, 13 insertions(+)
diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c index e9a87e1f4950..9095ce52c28c 100644 --- a/drivers/usb/dwc3/gadget.c +++ b/drivers/usb/dwc3/gadget.c @@ -1072,6 +1072,19 @@ static void __dwc3_prepare_one_trb(struct dwc3_ep *dep, struct dwc3_trb *trb, if (usb_endpoint_xfer_bulk(dep->endpoint.desc) && dep->stream_capable) trb->ctrl |= DWC3_TRB_CTRL_SID_SOFN(stream_id);
+ /* + * As per data book 4.2.3.2TRB Control Bit Rules section + * + * The controller autonomously checks the HWO field of a TRB to determine if the + * entire TRB is valid. Therefore, software must ensure that the rest of the TRB + * is valid before setting the HWO field to '1'. In most systems, this means that + * software must update the fourth DWORD of a TRB last. + * + * However there is a possibility of CPU re-ordering here which can cause + * controller to observe the HWO bit set prematurely. + * Add a write memory barrier to prevent CPU re-ordering. + */ + wmb(); trb->ctrl |= DWC3_TRB_CTRL_HWO;
dwc3_ep_inc_enq(dep);