fbfef019b0b7584ba21ee7761226f6b82de804af
[oweals/openwrt.git] /
1 From 0c6190fa3cfeafd773b51b751a473d6775c23309 Mon Sep 17 00:00:00 2001
2 From: P33M <2474547+P33M@users.noreply.github.com>
3 Date: Wed, 14 Aug 2019 14:35:50 +0100
4 Subject: [PATCH] dwc_otg: use align_buf for small IN control transfers
5  (#3150)
6
7 The hardware will do a 4-byte write to memory on any IN packet received
8 that is between 1 and 3 bytes long. This tramples memory in the uvcvideo
9 driver, as it uses a sequence of 1- and 2-byte control transfers to
10 query the min/max/range/step of each individual camera control and
11 gives us buffers that are offsets into a struct.
12
13 Catch small control transfers in the data phase and use the align_buf
14 to bounce the correct number of bytes into the URB's buffer.
15
16 In general, short packets on non-control endpoints should be OK as URBs
17 should have enough buffer space for a wMaxPacket size transfer.
18
19 See: https://github.com/raspberrypi/linux/issues/3148
20
21 Signed-off-by: Jonathan Bell <jonathan@raspberrypi.org>
22 ---
23  drivers/usb/host/dwc_otg/dwc_otg_hcd.c | 18 ++++++++++++++++++
24  1 file changed, 18 insertions(+)
25
26 --- a/drivers/usb/host/dwc_otg/dwc_otg_hcd.c
27 +++ b/drivers/usb/host/dwc_otg/dwc_otg_hcd.c
28 @@ -1182,6 +1182,7 @@ static void assign_and_init_hc(dwc_otg_h
29         dwc_otg_qtd_t *qtd;
30         dwc_otg_hcd_urb_t *urb;
31         void* ptr = NULL;
32 +       uint16_t wLength;
33         uint32_t intr_enable;
34         unsigned long flags;
35         gintmsk_data_t gintmsk = { .d32 = 0, };
36 @@ -1293,6 +1294,23 @@ static void assign_and_init_hc(dwc_otg_h
37                         break;
38                 case DWC_OTG_CONTROL_DATA:
39                         DWC_DEBUGPL(DBG_HCDV, "  Control data transaction\n");
40 +                       /*
41 +                        * Hardware bug: small IN packets with length < 4
42 +                        * cause a 4-byte write to memory. We can only catch
43 +                        * the case where we know a short packet is going to be
44 +                        * returned in a control transfer, as the length is
45 +                        * specified in the setup packet. This is only an issue
46 +                        * for drivers that insist on packing a device's various
47 +                        * properties into a struct and querying them one at a
48 +                        * time (uvcvideo).
49 +                        * Force the use of align_buf so that the subsequent
50 +                        * memcpy puts the right number of bytes in the URB's
51 +                        * buffer.
52 +                        */
53 +                       wLength = ((uint16_t *)urb->setup_packet)[3];
54 +                       if (hc->ep_is_in && wLength < 4)
55 +                               ptr = hc->xfer_buff;
56 +
57                         hc->data_pid_start = qtd->data_toggle;
58                         break;
59                 case DWC_OTG_CONTROL_STATUS: