usb_control_msg返回-EAGAIN

时间:2018-10-07 05:16:06

标签: linux linux-kernel usb linux-device-driver yocto

我有一个通过USB接口的定制板。.我正在编写USB Linux驱动程序。

当我在虚拟机上对其进行测试时,一切正常。.但是当我切换到真实硬件并在硬件上使用Yocto并运行以下代码时。.-EAGAIN失败。.

retval = usb_control_msg(serial->dev,
        usb_rcvctrlpipe(serial->dev, 0),
        CP210X_GET_MDMSTS,
        USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
        0,
        i,
        (void *)&modem_status,
        1,
        USB_CTRL_SET_TIMEOUT);

retval返回-11。我不确定为什么在虚拟机上不会发生这种情况,因为唯一的区别是PIC板连接到X86定制板并运行linux。

dmesg输出:

transfer buffer not dma capable
------------[ cut here ]------------
WARNING: CPU: 1 PID: 754 at /usr/src/kernel/drivers/usb/core/hcd.c:1595 usb_hcd_map_urb_for_dma+0x3e6/0x5b0
Modules linked in: cp2108(O)
CPU: 1 PID: 754 Comm: test_quad Tainted: G           O    4.14.68-intel-pk-standard #1
task: ffff9a33b7d4a4c0 task.stack: ffff9ce5c0130000
RIP: 0010:usb_hcd_map_urb_for_dma+0x3e6/0x5b0
RSP: 0018:ffff9ce5c0133b08 EFLAGS: 00010296
RAX: 000000000000001f RBX: ffff9a33b7d89780 RCX: 0000000000000000
RDX: ffff9a33bfc9d680 RSI: ffff9a33bfc95598 RDI: ffff9a33bfc95598
RBP: ffff9ce5c0133b28 R08: 0000000000000001 R09: 0000000000000328
R10: ffff9a33ba840068 R11: 0000000000000000 R12: ffff9a33ba2ea000
R13: 00000000fffffff5 R14: 0000000001400000 R15: 0000000000000200
FS:  00007fac9eeed4c0(0000) GS:ffff9a33bfc80000(0000) knlGS:0000000000000000
CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
CR2: 0000003c334e3cb0 CR3: 0000000179498000 CR4: 00000000003406e0
Call Trace:
 usb_hcd_submit_urb+0x420/0xa00
 ? tty_port_open+0xa7/0xd0
 ? tty_ldisc_unlock+0x1a/0x20
 ? tty_open_proc_set_tty+0x7f/0xb0
 ? tty_unlock+0x29/0x40
 ? tty_open+0x38e/0x450
 usb_submit_urb+0x364/0x550
 usb_start_wait_urb+0x5f/0xe0
 usb_control_msg+0xc5/0x110
 cp210x_ioctl+0x4d2/0xe20 [cp2108]
 ? filemap_map_pages+0x129/0x290
 ? do_filp_open+0xa0/0xf0
 serial_ioctl+0x46/0x50
 tty_ioctl+0xe7/0x870
 do_vfs_ioctl+0x99/0x5e0
 ? putname+0x4c/0x60
 SyS_ioctl+0x79/0x90

你们能给我一些提示吗?。感谢您的时间和精力。

1 个答案:

答案 0 :(得分:1)

我得到了解决方案内核> = 4.9不再接受任何静态分配的缓冲区。

修改了代码以使用动态内存,并且有效。

   modem_status = kmalloc(sizeof(unsigned long), GFP_KERNEL);
    if (!modem_status)
        return -ENOMEM;
    for (i = 0; i < MAX_CP210x_INTERFACE_NUM; i++) {
        retval = usb_control_msg(serial->dev,
                usb_rcvctrlpipe(serial->dev, 0),
                CP210X_GET_MDMSTS,
                USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
                0,
                i,
                (void *)modem_status,
                1,
                USB_CTRL_SET_TIMEOUT);