aboutsummaryrefslogtreecommitdiffstats
path: root/target/linux/bcm27xx/patches-5.4/950-0405-dwc_otg-constrain-endpoint-max-packet-and-transfer-s.patch
diff options
context:
space:
mode:
Diffstat (limited to 'target/linux/bcm27xx/patches-5.4/950-0405-dwc_otg-constrain-endpoint-max-packet-and-transfer-s.patch')
-rw-r--r--target/linux/bcm27xx/patches-5.4/950-0405-dwc_otg-constrain-endpoint-max-packet-and-transfer-s.patch43
1 files changed, 43 insertions, 0 deletions
diff --git a/target/linux/bcm27xx/patches-5.4/950-0405-dwc_otg-constrain-endpoint-max-packet-and-transfer-s.patch b/target/linux/bcm27xx/patches-5.4/950-0405-dwc_otg-constrain-endpoint-max-packet-and-transfer-s.patch
new file mode 100644
index 0000000000..7e4a3f8b38
--- /dev/null
+++ b/target/linux/bcm27xx/patches-5.4/950-0405-dwc_otg-constrain-endpoint-max-packet-and-transfer-s.patch
@@ -0,0 +1,43 @@
+From b7944a79716c115d881898e6a95705b262e7c1c9 Mon Sep 17 00:00:00 2001
+From: Jonathan Bell <jonathan@raspberrypi.org>
+Date: Tue, 7 Jan 2020 10:08:19 +0000
+Subject: [PATCH] dwc_otg: constrain endpoint max packet and transfer
+ size on split IN
+
+The hcd would unconditionally set the transfer length to the endpoint
+packet size for non-isoc IN transfers. If the remaining buffer length
+was less than the length of returned data, random memory would get
+scribbled over, with bad effects if it crossed a page boundary.
+
+Force a babble error if this happens by limiting the max transfer size
+to the available buffer space. DMA will stop writing to memory on a
+babble condition.
+
+The hardware expects xfersize to be an integer multiple of maxpacket
+size, so override hcchar.b.mps as well.
+
+Signed-off-by: Jonathan Bell <jonathan@raspberrypi.org>
+---
+ drivers/usb/host/dwc_otg/dwc_otg_hcd.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+--- a/drivers/usb/host/dwc_otg/dwc_otg_hcd.c
++++ b/drivers/usb/host/dwc_otg/dwc_otg_hcd.c
+@@ -1813,7 +1813,7 @@ int fiq_fsm_queue_split_transaction(dwc_
+ st->nr_errors = 0;
+
+ st->hcchar_copy.d32 = 0;
+- st->hcchar_copy.b.mps = hc->max_packet;
++ st->hcchar_copy.b.mps = min_t(uint32_t, hc->xfer_len, hc->max_packet);
+ st->hcchar_copy.b.epdir = hc->ep_is_in;
+ st->hcchar_copy.b.devaddr = hc->dev_addr;
+ st->hcchar_copy.b.epnum = hc->ep_num;
+@@ -1858,7 +1858,7 @@ int fiq_fsm_queue_split_transaction(dwc_
+ st->hctsiz_copy.b.pid = hc->data_pid_start;
+
+ if (hc->ep_is_in || (hc->xfer_len > hc->max_packet)) {
+- hc->xfer_len = hc->max_packet;
++ hc->xfer_len = min_t(uint32_t, hc->xfer_len, hc->max_packet);
+ } else if (!hc->ep_is_in && (hc->xfer_len > 188)) {
+ hc->xfer_len = 188;
+ }