summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorThinh Nguyen <Thinh.Nguyen@synopsys.com>2022-10-25 15:10:14 -0700
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2022-11-03 23:52:27 +0900
commit5a8fe9a5e0e26ae13ff82d122ed2d7f3ea6ed2a2 (patch)
tree6fbe7d31ba7b324e0842643aac1a5dcc0ac46d44
parent126b0a2dc0a69c8130217903b17d9d575c704900 (diff)
downloadlinux-stable-5a8fe9a5e0e26ae13ff82d122ed2d7f3ea6ed2a2.tar.gz
linux-stable-5a8fe9a5e0e26ae13ff82d122ed2d7f3ea6ed2a2.tar.bz2
linux-stable-5a8fe9a5e0e26ae13ff82d122ed2d7f3ea6ed2a2.zip
usb: dwc3: gadget: Stop processing more requests on IMI
commit f78961f8380b940e0cfc7e549336c21a2ad44f4d upstream. When servicing a transfer completion event, the dwc3 driver will reclaim TRBs of started requests up to the request associated with the interrupt event. Currently we don't check for interrupt due to missed isoc, and the driver may attempt to reclaim TRBs beyond the associated event. This causes invalid memory access when the hardware still owns the TRB. If there's a missed isoc TRB with IMI (interrupt on missed isoc), make sure to stop servicing further. Note that only the last TRB of chained TRBs has its status updated with missed isoc. Fixes: 72246da40f37 ("usb: Introduce DesignWare USB3 DRD Driver") Cc: stable@vger.kernel.org Reported-by: Jeff Vanhoof <jdv1029@gmail.com> Reported-by: Dan Vacura <w36195@motorola.com> Signed-off-by: Thinh Nguyen <Thinh.Nguyen@synopsys.com> Reviewed-by: Jeff Vanhoof <jdv1029@gmail.com> Tested-by: Jeff Vanhoof <jdv1029@gmail.com> Link: https://lore.kernel.org/r/b29acbeab531b666095dfdafd8cb5c7654fbb3e1.1666735451.git.Thinh.Nguyen@synopsys.com Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-rw-r--r--drivers/usb/dwc3/gadget.c4
1 files changed, 4 insertions, 0 deletions
diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c
index 3c8ec1c07ef3..c1f4459f3493 100644
--- a/drivers/usb/dwc3/gadget.c
+++ b/drivers/usb/dwc3/gadget.c
@@ -2363,6 +2363,10 @@ static int dwc3_gadget_ep_reclaim_completed_trb(struct dwc3_ep *dep,
if (event->status & DEPEVT_STATUS_SHORT && !chain)
return 1;
+ if ((trb->ctrl & DWC3_TRB_CTRL_ISP_IMI) &&
+ DWC3_TRB_SIZE_TRBSTS(trb->size) == DWC3_TRBSTS_MISSED_ISOC)
+ return 1;
+
if ((trb->ctrl & DWC3_TRB_CTRL_IOC) ||
(trb->ctrl & DWC3_TRB_CTRL_LST))
return 1;