Skip to content

Commit 2f27224

Browse files
P33Mpelwell
authored andcommitted
usb: dwc2: use temporary URB buffer for small control transfers
As a result of a hardware bug, small IN packets with length < 4 cause a 4-byte write to memory. Generally, buffers allocated with kmalloc reserve at least one cacheline of memory, but the UVC driver passes offsets into a struct as the buffer. This causes trampling of video control min/max/default/range data. e.g. on a generic UVC camera, these default values are nonsense: $ v4l2-ctl -d0 --all [...] brightness 0x00980900 (int) : min=0 max=255 step=1 default=-8193 value=128 contrast 0x00980901 (int) : min=0 max=100 step=1 default=57343 value=67 saturation 0x00980902 (int) : min=0 max=100 step=1 default=57343 value=62 hue 0x00980903 (int) : min=-90 max=90 step=2 default=12287 value=0 gamma 0x00980910 (int) : min=1 max=30 step=1 default=57343 value=29 [...] Update the pre-existing DMA alignment code to catch this case. Link: #3148 Signed-off-by: Jonathan Bell <jonathan@raspberrypi.com>
1 parent 1f73a67 commit 2f27224

File tree

1 file changed

+16
-3
lines changed

1 file changed

+16
-3
lines changed

drivers/usb/dwc2/hcd.c

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2469,10 +2469,23 @@ static int dwc2_alloc_dma_aligned_buffer(struct urb *urb, gfp_t mem_flags)
24692469
{
24702470
void *kmalloc_ptr;
24712471
size_t kmalloc_size;
2472+
bool small_ctrl;
24722473

2473-
if (urb->num_sgs || urb->sg ||
2474-
urb->transfer_buffer_length == 0 ||
2475-
!((uintptr_t)urb->transfer_buffer & (DWC2_USB_DMA_ALIGN - 1)))
2474+
if (urb->num_sgs || urb->sg || urb->transfer_buffer_length == 0)
2475+
return 0;
2476+
2477+
/*
2478+
* Hardware bug: small IN packets with length < 4 cause a
2479+
* 4-byte write to memory. This is only an issue for drivers that
2480+
* insist on packing a device's various properties into a struct
2481+
* and filling them one at a time with Control transfers (uvcvideo).
2482+
* Force the use of align_buf so that the subsequent memcpy puts
2483+
* the right number of bytes in the URB's buffer.
2484+
*/
2485+
small_ctrl = (urb->setup_packet &&
2486+
le16_to_cpu(((struct usb_ctrlrequest *)(urb->setup_packet))->wLength) < 4);
2487+
2488+
if (!small_ctrl && !((uintptr_t)urb->transfer_buffer & (DWC2_USB_DMA_ALIGN - 1)))
24762489
return 0;
24772490

24782491
/*

0 commit comments

Comments
 (0)