summaryrefslogtreecommitdiffstats
path: root/drivers/usb/dwc3/gadget.c
diff options
context:
space:
mode:
authorThinh Nguyen <Thinh.Nguyen@synopsys.com>2022-11-07 16:37:55 -0800
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2022-11-08 16:46:46 +0100
commit04914233561377fc0369b984c9d19ec1b6ce2845 (patch)
tree54c4f916875776b5db8da350df9fadb76a057bba /drivers/usb/dwc3/gadget.c
parent0ce0f9d0785a7ba5637a22b63332cf747772da2a (diff)
downloadlinux-04914233561377fc0369b984c9d19ec1b6ce2845.tar.bz2
usb: dwc3: gadget: Reduce TRB IOC settings
When the TRB ring is full, the dwc3 driver must make sure that there's at least 1 TRB with Interrupt On Completion (IOC) set to notify of available TRBs. The current logic just sets the TRB's IOC whenever we run out of TRBs, but it doesn't consider that there may be other TRBs with IOC/LST set already. This creates more events and unnecessary delay from interrupt handling. Only forcefully set IOC when we run out of TRBs and none of the TRBs in the TRB ring has had IOC set. Signed-off-by: Thinh Nguyen <Thinh.Nguyen@synopsys.com> Link: https://lore.kernel.org/r/72a1fa448eb1201b152e65be7902a5d1c75b9f3a.1667867687.git.Thinh.Nguyen@synopsys.com Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers/usb/dwc3/gadget.c')
-rw-r--r--drivers/usb/dwc3/gadget.c14
1 files changed, 12 insertions, 2 deletions
diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c
index 5fe2d136dff5..ecddb144871b 100644
--- a/drivers/usb/dwc3/gadget.c
+++ b/drivers/usb/dwc3/gadget.c
@@ -1463,8 +1463,18 @@ static int dwc3_prepare_trbs_sg(struct dwc3_ep *dep,
*/
if (num_trbs_left == 1 || (needs_extra_trb &&
num_trbs_left <= 2 &&
- sg_dma_len(sg_next(s)) >= length))
- must_interrupt = true;
+ sg_dma_len(sg_next(s)) >= length)) {
+ struct dwc3_request *r;
+
+ /* Check if previous requests already set IOC */
+ list_for_each_entry(r, &dep->started_list, list) {
+ if (r != req && !r->request.no_interrupt)
+ break;
+
+ if (r == req)
+ must_interrupt = true;
+ }
+ }
dwc3_prepare_one_trb(dep, req, trb_length, 1, i, false,
must_interrupt);