summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThinh Nguyen <Thinh.Nguyen@synopsys.com>2024-11-14 01:02:18 +0000
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2024-11-16 09:04:56 +0100
commitb7fc65f5141c24785dc8c19249ca4efcf71b3524 (patch)
tree39d5436a08c7d0461b34e1c8a746ff30556f1b1b
parent02a6982b0ccfcdc39e20016f5fc9a1b7826a6ee7 (diff)
downloadlwn-b7fc65f5141c24785dc8c19249ca4efcf71b3524.tar.gz
lwn-b7fc65f5141c24785dc8c19249ca4efcf71b3524.zip
usb: dwc3: gadget: Fix looping of queued SG entries
The dwc3_request->num_queued_sgs is decremented on completion. If a partially completed request is handled, then the dwc3_request->num_queued_sgs no longer reflects the total number of num_queued_sgs (it would be cleared). Correctly check the number of request SG entries remained to be prepare and queued. Failure to do this may cause null pointer dereference when accessing non-existent SG entry. Cc: stable@vger.kernel.org Fixes: c96e6725db9d ("usb: dwc3: gadget: Correct the logic for queuing sgs") Signed-off-by: Thinh Nguyen <Thinh.Nguyen@synopsys.com> Link: https://lore.kernel.org/r/d07a7c4aa0fcf746cdca0515150dbe5c52000af7.1731545781.git.Thinh.Nguyen@synopsys.com Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-rw-r--r--drivers/usb/dwc3/gadget.c6
1 files changed, 3 insertions, 3 deletions
diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c
index 38c3769a6c48..3a5a0d8be33c 100644
--- a/drivers/usb/dwc3/gadget.c
+++ b/drivers/usb/dwc3/gadget.c
@@ -1470,8 +1470,8 @@ static int dwc3_prepare_trbs_sg(struct dwc3_ep *dep,
struct scatterlist *s;
int i;
unsigned int length = req->request.length;
- unsigned int remaining = req->request.num_mapped_sgs
- - req->num_queued_sgs;
+ unsigned int remaining = req->num_pending_sgs;
+ unsigned int num_queued_sgs = req->request.num_mapped_sgs - remaining;
unsigned int num_trbs = req->num_trbs;
bool needs_extra_trb = dwc3_needs_extra_trb(dep, req);
@@ -1479,7 +1479,7 @@ static int dwc3_prepare_trbs_sg(struct dwc3_ep *dep,
* If we resume preparing the request, then get the remaining length of
* the request and resume where we left off.
*/
- for_each_sg(req->request.sg, s, req->num_queued_sgs, i)
+ for_each_sg(req->request.sg, s, num_queued_sgs, i)
length -= sg_dma_len(s);
for_each_sg(sg, s, remaining, i) {