aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMarian Hello <marian.hello@gmail.com>2016-12-07 17:06:47 +0100
committerZoltan HERPAI <wigyori@uid0.hu>2016-12-07 17:06:47 +0100
commit6ee59728b9c293d76146d9021639b72147065aad (patch)
tree77115643a5689c4edf25b439d10d7b8407f89c4d
parent2aefb514a4852f4c427b467150bbc7cdfe024528 (diff)
downloadupstream-6ee59728b9c293d76146d9021639b72147065aad.tar.gz
upstream-6ee59728b9c293d76146d9021639b72147065aad.tar.bz2
upstream-6ee59728b9c293d76146d9021639b72147065aad.zip
CC: brcm2708: Fix Kernel Panic: DM9601 Fast Ethernet Adapter
The dm9601 driver expects to receive a single encapsulated ethernet frame from the device in one URB transfer, and it provides an URB buffer of length 1,522 to receive it. This is not a round multiple of USB transfer packets. The device in question [1] provides a stream of such frames and it does not conveniently slice them up as the dm9601 driver expects. We can end up with 1,536 (0x600) bytes returned by the device in response to the URB request. This may include several encapsulated ethernet frames, and/or fragments thereof. It seems to me that the kernel 'Oops' arises because the dwc_otg driver does not notice that the destination buffer is too small to receive the full 1,536 bytes. Comparing dwc_otg's update_urb_state_xfer_comp with dwc2's dwc2_update_urb_state is suggestive. More details: https://github.com/raspberrypi/linux/issues/1045 All Credits to: https://github.com/mw9 Signed-off-by: Marian Hello <marian.hello@gmail.com> Reviewed-by: Zoltan HERPAI <wigyori@uid0.hu>
-rw-r--r--target/linux/brcm2708/patches-3.18/0700-dm9601-kernel-panic.patch14
1 files changed, 14 insertions, 0 deletions
diff --git a/target/linux/brcm2708/patches-3.18/0700-dm9601-kernel-panic.patch b/target/linux/brcm2708/patches-3.18/0700-dm9601-kernel-panic.patch
new file mode 100644
index 0000000000..30a979dd1f
--- /dev/null
+++ b/target/linux/brcm2708/patches-3.18/0700-dm9601-kernel-panic.patch
@@ -0,0 +1,14 @@
+--- a/drivers/usb/host/dwc_otg/dwc_otg_hcd_intr.c
++++ b/drivers/usb/host/dwc_otg/dwc_otg_hcd_intr.c
+@@ -738,6 +738,11 @@ static int update_urb_state_xfer_comp(dw
+ DWC_OTG_HC_XFER_COMPLETE,
+ &short_read);
+
++ if (urb->actual_length + xfer_length > urb->length) {
++ /* dev_warn(hsotg->dev, "%s(): trimming xfer length\n", __func__);*/
++ xfer_length = urb->length - urb->actual_length;
++ }
++
+ /* non DWORD-aligned buffer case handling. */
+ if (hc->align_buff && xfer_length && hc->ep_is_in) {
+ dwc_memcpy(urb->buf + urb->actual_length, hc->qh->dw_align_buf,