Skip to content
This repository was archived by the owner on Nov 8, 2023. It is now read-only.

Commit c96e672

Browse files
Anurag Kumar VulishaFelipe Balbi
authored andcommitted
usb: dwc3: gadget: Correct the logic for queuing sgs
The present code correctly fetches the req which were previously not queued from the started_list but fails to continue queuing from the sg where it previously stopped queuing (because of the unavailable TRB's). This patch correct's the code to continue queuing from the correct sg present in the sglist. For example, consider 5 sgs in req. Because of limited TRB's among the 5 sgs only 3 got queued. This patch corrects the code to start queuing from correct sg i.e 4th sg when the TRBs are available. Signed-off-by: Anurag Kumar Vulisha <[email protected]> Signed-off-by: Felipe Balbi <[email protected]>
1 parent a31e63b commit c96e672

File tree

2 files changed

+22
-3
lines changed

2 files changed

+22
-3
lines changed

drivers/usb/dwc3/core.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -834,6 +834,7 @@ struct dwc3_hwparams {
834834
* @sg: pointer to first incomplete sg
835835
* @start_sg: pointer to the sg which should be queued next
836836
* @num_pending_sgs: counter to pending sgs
837+
* @num_queued_sgs: counter to the number of sgs which already got queued
837838
* @remaining: amount of data remaining
838839
* @epnum: endpoint number to which this request refers
839840
* @trb: pointer to struct dwc3_trb
@@ -852,6 +853,7 @@ struct dwc3_request {
852853
struct scatterlist *start_sg;
853854

854855
unsigned num_pending_sgs;
856+
unsigned int num_queued_sgs;
855857
unsigned remaining;
856858
u8 epnum;
857859
struct dwc3_trb *trb;

drivers/usb/dwc3/gadget.c

Lines changed: 20 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1067,7 +1067,10 @@ static void dwc3_prepare_one_trb_sg(struct dwc3_ep *dep,
10671067
struct scatterlist *s;
10681068
int i;
10691069

1070-
for_each_sg(sg, s, req->num_pending_sgs, i) {
1070+
unsigned int remaining = req->request.num_mapped_sgs
1071+
- req->num_queued_sgs;
1072+
1073+
for_each_sg(sg, s, remaining, i) {
10711074
unsigned int length = req->request.length;
10721075
unsigned int maxp = usb_endpoint_maxp(dep->endpoint.desc);
10731076
unsigned int rem = length % maxp;
@@ -1106,6 +1109,8 @@ static void dwc3_prepare_one_trb_sg(struct dwc3_ep *dep,
11061109
if (chain)
11071110
req->start_sg = sg_next(s);
11081111

1112+
req->num_queued_sgs++;
1113+
11091114
if (!dwc3_calc_trbs_left(dep))
11101115
break;
11111116
}
@@ -1197,6 +1202,7 @@ static void dwc3_prepare_trbs(struct dwc3_ep *dep)
11971202

11981203
req->sg = req->request.sg;
11991204
req->start_sg = req->sg;
1205+
req->num_queued_sgs = 0;
12001206
req->num_pending_sgs = req->request.num_mapped_sgs;
12011207

12021208
if (req->num_pending_sgs > 0)
@@ -2380,8 +2386,19 @@ static int dwc3_cleanup_done_reqs(struct dwc3 *dwc, struct dwc3_ep *dep,
23802386

23812387
req->request.actual = length - req->remaining;
23822388

2383-
if ((req->request.actual < length) && req->num_pending_sgs)
2384-
return __dwc3_gadget_kick_transfer(dep);
2389+
if (req->request.actual < length || req->num_pending_sgs) {
2390+
/*
2391+
* There could be a scenario where the whole req can't
2392+
* be mapped into available TRB's. In that case, we need
2393+
* to kick transfer again if (req->num_pending_sgs > 0)
2394+
*/
2395+
if (req->num_pending_sgs) {
2396+
dev_WARN_ONCE(dwc->dev,
2397+
(req->request.actual == length),
2398+
"There are some pending sg's that needs to be queued again\n");
2399+
return __dwc3_gadget_kick_transfer(dep);
2400+
}
2401+
}
23852402

23862403
dwc3_gadget_giveback(dep, req, status);
23872404

0 commit comments

Comments
 (0)