Skip to content

Commit 2ca57fc

Browse files
sregregkh
authored andcommitted
i2c: i2c-tiny-usb: fix buffer not being DMA capable
commit 5165da5 upstream. Since v4.9 i2c-tiny-usb generates the below call trace and longer works, since it can't communicate with the USB device. The reason is, that since v4.9 the USB stack checks, that the buffer it should transfer is DMA capable. This was a requirement since v2.2 days, but it usually worked nevertheless. [ 17.504959] ------------[ cut here ]------------ [ 17.505488] WARNING: CPU: 0 PID: 93 at drivers/usb/core/hcd.c:1587 usb_hcd_map_urb_for_dma+0x37c/0x570 [ 17.506545] transfer buffer not dma capable [ 17.507022] Modules linked in: [ 17.507370] CPU: 0 PID: 93 Comm: i2cdetect Not tainted 4.11.0-rc8+ OnePlusOSS#10 [ 17.508103] Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.10.2-1 04/01/2014 [ 17.509039] Call Trace: [ 17.509320] ? dump_stack+0x5c/0x78 [ 17.509714] ? __warn+0xbe/0xe0 [ 17.510073] ? warn_slowpath_fmt+0x5a/0x80 [ 17.510532] ? nommu_map_sg+0xb0/0xb0 [ 17.510949] ? usb_hcd_map_urb_for_dma+0x37c/0x570 [ 17.511482] ? usb_hcd_submit_urb+0x336/0xab0 [ 17.511976] ? wait_for_completion_timeout+0x12f/0x1a0 [ 17.512549] ? wait_for_completion_timeout+0x65/0x1a0 [ 17.513125] ? usb_start_wait_urb+0x65/0x160 [ 17.513604] ? usb_control_msg+0xdc/0x130 [ 17.514061] ? usb_xfer+0xa4/0x2a0 [ 17.514445] ? __i2c_transfer+0x108/0x3c0 [ 17.514899] ? i2c_transfer+0x57/0xb0 [ 17.515310] ? i2c_smbus_xfer_emulated+0x12f/0x590 [ 17.515851] ? _raw_spin_unlock_irqrestore+0x11/0x20 [ 17.516408] ? i2c_smbus_xfer+0x125/0x330 [ 17.516876] ? i2c_smbus_xfer+0x125/0x330 [ 17.517329] ? i2cdev_ioctl_smbus+0x1c1/0x2b0 [ 17.517824] ? i2cdev_ioctl+0x75/0x1c0 [ 17.518248] ? do_vfs_ioctl+0x9f/0x600 [ 17.518671] ? vfs_write+0x144/0x190 [ 17.519078] ? SyS_ioctl+0x74/0x80 [ 17.519463] ? entry_SYSCALL_64_fastpath+0x1e/0xad [ 17.519959] ---[ end trace d047c04982f5ac50 ]--- Signed-off-by: Sebastian Reichel <[email protected]> Reviewed-by: Greg Kroah-Hartman <[email protected]> Acked-by: Till Harbaum <[email protected]> Signed-off-by: Wolfram Sang <[email protected]> Signed-off-by: Greg Kroah-Hartman <[email protected]>
1 parent 1b5286b commit 2ca57fc

File tree

1 file changed

+21
-4
lines changed

1 file changed

+21
-4
lines changed

drivers/i2c/busses/i2c-tiny-usb.c

+21-4
Original file line numberDiff line numberDiff line change
@@ -178,22 +178,39 @@ static int usb_read(struct i2c_adapter *adapter, int cmd,
178178
int value, int index, void *data, int len)
179179
{
180180
struct i2c_tiny_usb *dev = (struct i2c_tiny_usb *)adapter->algo_data;
181+
void *dmadata = kmalloc(len, GFP_KERNEL);
182+
int ret;
183+
184+
if (!dmadata)
185+
return -ENOMEM;
181186

182187
/* do control transfer */
183-
return usb_control_msg(dev->usb_dev, usb_rcvctrlpipe(dev->usb_dev, 0),
188+
ret = usb_control_msg(dev->usb_dev, usb_rcvctrlpipe(dev->usb_dev, 0),
184189
cmd, USB_TYPE_VENDOR | USB_RECIP_INTERFACE |
185-
USB_DIR_IN, value, index, data, len, 2000);
190+
USB_DIR_IN, value, index, dmadata, len, 2000);
191+
192+
memcpy(data, dmadata, len);
193+
kfree(dmadata);
194+
return ret;
186195
}
187196

188197
static int usb_write(struct i2c_adapter *adapter, int cmd,
189198
int value, int index, void *data, int len)
190199
{
191200
struct i2c_tiny_usb *dev = (struct i2c_tiny_usb *)adapter->algo_data;
201+
void *dmadata = kmemdup(data, len, GFP_KERNEL);
202+
int ret;
203+
204+
if (!dmadata)
205+
return -ENOMEM;
192206

193207
/* do control transfer */
194-
return usb_control_msg(dev->usb_dev, usb_sndctrlpipe(dev->usb_dev, 0),
208+
ret = usb_control_msg(dev->usb_dev, usb_sndctrlpipe(dev->usb_dev, 0),
195209
cmd, USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
196-
value, index, data, len, 2000);
210+
value, index, dmadata, len, 2000);
211+
212+
kfree(dmadata);
213+
return ret;
197214
}
198215

199216
static void i2c_tiny_usb_free(struct i2c_tiny_usb *dev)

0 commit comments

Comments
 (0)