Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>

authored by

Thinh Nguyen and committed by
Greg Kroah-Hartman
04914233 0ce0f9d0

+12 -2
+12 -2
drivers/usb/dwc3/gadget.c
··· 1463 1463 */ 1464 1464 if (num_trbs_left == 1 || (needs_extra_trb && 1465 1465 num_trbs_left <= 2 && 1466 - sg_dma_len(sg_next(s)) >= length)) 1467 - must_interrupt = true; 1466 + sg_dma_len(sg_next(s)) >= length)) { 1467 + struct dwc3_request *r; 1468 + 1469 + /* Check if previous requests already set IOC */ 1470 + list_for_each_entry(r, &dep->started_list, list) { 1471 + if (r != req && !r->request.no_interrupt) 1472 + break; 1473 + 1474 + if (r == req) 1475 + must_interrupt = true; 1476 + } 1477 + } 1468 1478 1469 1479 dwc3_prepare_one_trb(dep, req, trb_length, 1, i, false, 1470 1480 must_interrupt);