patch "usb: dwc3: gadget: Properly track pending and queued SG" added to usb-linus
Subsystems (3)
This is a note to let you know that I've just added the patch titled
usb: dwc3: gadget: Properly track pending and queued SG
to my usb git tree which can be found at
git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb.git
in the usb-linus branch.
The patch will show up in the next release of the linux-next tree (usually sometime within the next 24 hours during the week.)
The patch will hopefully also be merged in Linus's tree for the next -rc kernel release.
If you have any questions about this process, please let me know.
From 25dda9fc56bd90d45f9a4516bcfa5211e61b4290 Mon Sep 17 00:00:00 2001
From: Thinh Nguyen <[email protected]>
Date: Wed, 12 May 2021 20:17:09 -0700
Subject: usb: dwc3: gadget: Properly track pending and queued SG
The driver incorrectly uses req->num_pending_sgs to track both the number of pending and queued SG entries. It only prepares the next request if the previous is done, and it doesn't update num_pending_sgs until there is TRB completion interrupt. This may starve the controller of more TRBs until the num_pending_sgs is decremented.
Fix this by decrementing the num_pending_sgs after they are queued and properly track both num_mapped_sgs and num_queued_sgs.
--- drivers/usb/dwc3/gadget.c | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-)
drivers/usb/dwc3/gadget.c +7 -6
@@ -1244,6 +1244,7 @@ static int dwc3_prepare_trbs_sg(struct dwc3_ep *dep, req->start_sg =sg_next (s); req->num_queued_sgs++; + req->num_pending_sgs--;/* * The number of pending SG entries may not correspond to the
@@ -1251,7 +1252,7 @@ static int dwc3_prepare_trbs_sg(struct dwc3_ep *dep,* don't include unused SG entries. */ if (length ==0 ) { - req->num_pending_sgs -= req->request.num_mapped_sgs - req->num_queued_sgs; + req->num_pending_sgs =0 ;break ; }
@@ -2873,15 +2874,15 @@ static int dwc3_gadget_ep_reclaim_trb_sg(struct dwc3_ep *dep,struct dwc3_trb *trb = &dep->trb_pool[dep->trb_dequeue];struct scatterlist *sg = req->sg;struct scatterlist *s; -unsigned int pending = req->num_pending_sgs; +unsigned int num_queued = req->num_queued_sgs;unsigned int i;int ret =0 ; -for_each_sg (sg, s, pending, i) { +for_each_sg (sg, s, num_queued, i) { trb = &dep->trb_pool[dep->trb_dequeue]; req->sg =sg_next (s); - req->num_pending_sgs--; + req->num_queued_sgs--; ret =dwc3_gadget_ep_reclaim_completed_trb (dep, req, trb, event, status, true);
@@ -2904,7 +2905,7 @@ static int dwc3_gadget_ep_reclaim_trb_linear(struct dwc3_ep *dep,static bool dwc3_gadget_ep_request_completed (struct dwc3_request *req) { -return req->num_pending_sgs ==0 ; +return req->num_pending_sgs ==0 && req->num_queued_sgs ==0 ; } static int dwc3_gadget_ep_cleanup_completed_request(struct dwc3_ep *dep,
@@ -2913,7 +2914,7 @@ static int dwc3_gadget_ep_cleanup_completed_request(struct dwc3_ep *dep, {int ret; -if (req->num_pending_sgs) +if (req->request.num_mapped_sgs) ret =dwc3_gadget_ep_reclaim_trb_sg (dep, req, event, status);else
Signature · 1 line
2.31.1