summaryrefslogtreecommitdiffstats
path: root/drivers/usb
diff options
context:
space:
mode:
authorPratham Pratap <prathampratap@codeaurora.org>2020-03-02 21:44:43 +0000
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2020-03-11 14:14:58 +0100
commit0c6023a3f0e20c8ceff4ee660f0453a0423f5295 (patch)
treef77359172173a8b5d3f8430011da4c10637b1e4b /drivers/usb
parent505107c0d172f094fc1cbd83a37172b24f8b1bb0 (diff)
downloadlinux-stable-0c6023a3f0e20c8ceff4ee660f0453a0423f5295.tar.gz
linux-stable-0c6023a3f0e20c8ceff4ee660f0453a0423f5295.tar.bz2
linux-stable-0c6023a3f0e20c8ceff4ee660f0453a0423f5295.zip
usb: dwc3: gadget: Update chain bit correctly when using sg list
commit dad2aff3e827b112f27fa5e6f2bf87a110067c3f upstream. 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 <anurag.kumar.vulisha@xilinx.com> who implemented a very similar fix to this issue. Cc: Felipe Balbi <balbi@kernel.org> Cc: Yang Fei <fei.yang@intel.com> Cc: Thinh Nguyen <thinhn@synopsys.com> Cc: Tejas Joglekar <tejas.joglekar@synopsys.com> Cc: Andrzej Pietrasiewicz <andrzej.p@collabora.com> Cc: Jack Pham <jackp@codeaurora.org> Cc: Todd Kjos <tkjos@google.com> Cc: Greg KH <gregkh@linuxfoundation.org> Cc: Linux USB List <linux-usb@vger.kernel.org> Cc: stable <stable@vger.kernel.org> #4.20+ Signed-off-by: Pratham Pratap <prathampratap@codeaurora.org> [jstultz: Slight tweak to remove sg_is_last() usage, reworked commit message, minor comment tweak] Signed-off-by: John Stultz <john.stultz@linaro.org> Link: https://lore.kernel.org/r/20200302214443.55783-1-john.stultz@linaro.org Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers/usb')
-rw-r--r--drivers/usb/dwc3/gadget.c9
1 files changed, 8 insertions, 1 deletions
diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c
index 430cfd620854..d482f89ffae2 100644
--- a/drivers/usb/dwc3/gadget.c
+++ b/drivers/usb/dwc3/gadget.c
@@ -1067,7 +1067,14 @@ static void dwc3_prepare_one_trb_sg(struct dwc3_ep *dep,
unsigned int rem = length % maxp;
unsigned chain = true;
- if (sg_is_last(s))
+ /*
+ * IOMMU driver is coalescing the list of sgs which shares a
+ * page boundary into one and giving it to USB driver. With
+ * this the number of sgs mapped is not equal to the number of
+ * sgs passed. So mark the chain bit to false if it isthe last
+ * mapped sg.
+ */
+ if (i == remaining - 1)
chain = false;
if (rem && usb_endpoint_dir_out(dep->endpoint.desc) && !chain) {