Skip to content

Commit dad2aff

Browse files
Pratham Pratapgregkh
authored andcommitted
usb: dwc3: gadget: Update chain bit correctly when using sg list
If scatter-gather operation is allowed, a large USB request is split into multiple TRBs. For preparing TRBs for sg list, driver iterates over the list and creates TRB for each sg and mark the chain bit to false for the last sg. The current IOMMU driver is clubbing the list of sgs which shares a page boundary into one and giving it to USB driver. With this the number of sgs mapped it not equal to the the number of sgs passed. Because of this USB driver is not marking the chain bit to false since it couldn't iterate to the last sg. This patch addresses this issue by marking the chain bit to false if it is the last mapped sg. At a practical level, this patch resolves USB transfer stalls seen with adb on dwc3 based db845c, pixel3 and other qcom hardware after functionfs gadget added scatter-gather support around v4.20. Credit also to Anurag Kumar Vulisha <[email protected]> who implemented a very similar fix to this issue. Cc: Felipe Balbi <[email protected]> Cc: Yang Fei <[email protected]> Cc: Thinh Nguyen <[email protected]> Cc: Tejas Joglekar <[email protected]> Cc: Andrzej Pietrasiewicz <[email protected]> Cc: Jack Pham <[email protected]> Cc: Todd Kjos <[email protected]> Cc: Greg KH <[email protected]> Cc: Linux USB List <[email protected]> Cc: stable <[email protected]> #4.20+ Signed-off-by: Pratham Pratap <[email protected]> [jstultz: Slight tweak to remove sg_is_last() usage, reworked commit message, minor comment tweak] Signed-off-by: John Stultz <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Greg Kroah-Hartman <[email protected]>
1 parent 1f8b39b commit dad2aff

File tree

1 file changed

+8
-1
lines changed

1 file changed

+8
-1
lines changed

drivers/usb/dwc3/gadget.c

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1071,7 +1071,14 @@ static void dwc3_prepare_one_trb_sg(struct dwc3_ep *dep,
10711071
unsigned int rem = length % maxp;
10721072
unsigned chain = true;
10731073

1074-
if (sg_is_last(s))
1074+
/*
1075+
* IOMMU driver is coalescing the list of sgs which shares a
1076+
* page boundary into one and giving it to USB driver. With
1077+
* this the number of sgs mapped is not equal to the number of
1078+
* sgs passed. So mark the chain bit to false if it isthe last
1079+
* mapped sg.
1080+
*/
1081+
if (i == remaining - 1)
10751082
chain = false;
10761083

10771084
if (rem && usb_endpoint_dir_out(dep->endpoint.desc) && !chain) {

0 commit comments

Comments
 (0)