usb_submit_urb - 发送一个端点的异步传输请求 @urb: 描述请求的urb指针 @mem_flags: 分配内存的类型,参见kmalloc()获取可用选项列表。

这将提交一个传输请求,并将描述该请求的URB的控制权转移给USB子系统。 后续将异步地通过调用完成处理程序来指示请求完成。完成有三种类型:成功、错误和unlink (软件引起的故障,也称为“请求取消”)。

URBs可以在中断上下文中提交。

在提交之前,调用方必须正确初始化URB。可使用诸如usb_fill_bulk_urb()和usb_fill_control_urb()等函数,以确保大多数字段正确初始化,针对特定类型的传输,尽管它们不会初始化任何传输标志。

如果提交成功,URB中的complete()回调将在USB核心和主机控制器驱动程序(HCD)完成URB时被调用一次。当调用完成函数时,URB的控制权将返回发出请求的设备驱动程序。完成处理程序随即可以立即释放或重用该URB。

除了定期传输调度之外,USB设备驱动程序不应访问usbcore或HCD提供的URB字段,直到调用了其complete()方法。这些例外与定期传输调度有关。对于中断和等时urb,作为成功URB提交的一部分,urb->interval会被修改以反映实际使用的传输周期(通常是2的幂单位)。对于等时urb,urb->start_frame将被修改以反映URB的传输何时被调度开始。

并非所有等时传输调度策略都起作用,但大多数主机控制器驱动程序应该可以轻松处理从现在开始到未来的10-200毫秒的ISO队列。驱动程序应该尝试保持队列中至少1或2毫秒的数据;许多控制器要求添加新传输时至少在未来1毫秒开始。如果驱动程序无法跟上并且队列已清空,则新提交的行为受URB_ISO_ASAP标志控制。如果设置了标志或队列处于空闲状态,则URB始终分配给端点计划中第一个可用(且尚未过期)的插槽。如果未设置标志且队列处于活动状态,则URB始终分配给端点上一个URB结束后的计划中的下一个插槽,即使该插槽在过去。当以这种方式将数据包分配给已经过期的插槽时,该数据包不会被传输,并且相应的usb_iso_packet_descriptor的状态字段将返回-EXDEV。如果此情况发生在URB的所有数据包中,则提交将以-EXDEV错误代码失败。

对于控制端点,通常使用同步的usb_control_msg()调用(在非中断上下文中)而不是此调用。这通常通过便捷包装器用于USB 2.0规范中标准化的请求。对于批量端点,有一个同步的usb_bulk_msg()调用可用。

返回: 成功提交为0。否则为负的错误号。

请求排队:

可以在前一个请求完成之前向端点提交URB,以最小化中断延迟和系统开销对数据吞吐量的影响。使用此排队策略,端点的队列将永远不会为空。这对于连续的等时数据流是必需的,对于某些类型的中断传输也可能是必需的。这样的排队还通过在驱动程序软件完成先前(成功)请求的完成处理之前,允许USB控制器开始处理后续请求,从而最大化了带宽利用率。

从Linux 2.6开始,所有USB端点传输队列支持深度大于1。这以前是特定于HCD的行为,除了ISO传输外。非等时端点队列在故障清理(传输错误或取消)后处于非活动状态。

预留带宽传输:

重复执行周期传输(中断或等时),使用urb中指定的间隔。向端点提交第一个urb会保留执行这些传输所需的带宽。如果USB子系统无法分配足够的带宽来执行定期请求,则提交此类定期请求应失败。

对于xHCI下的设备,带宽在配置时或选择alt设置时预留。如果总线带宽不足,则配置/alt设置请求将失败。因此,在xHCI设备上定期端点的提交不应由于带宽限制而失败。

设备驱动程序必须显式请求重复,方法是确保某些URB始终位于端点的队列中(除了在完成回调期间可能短暂的时期之外)。当不再排队URB时,端点的带宽预留会被取消。这意味着驱动程序可以使用其完成处理程序来确保它们保持所需的带宽,方法是重新初始化并重新提交刚刚完成的URB,直到驱动程序不再需要该定期带宽。

内存标志:

决定使用哪个mem_flags的一般规则与kmalloc相同。有四个不同的可能值;GFP_KERNEL、GFP_NOFS、GFP_NOIO和GFP_ATOMIC。

暂时不使用GFP_NOFS,因为它尚未实现。

当 (a)您在完成处理程序、中断、底半部、任务或计时器中,或者 (b)您持有自旋锁或rwlock(不适用于信号量)时,使用GFP_ATOMIC,或者 (c)current->state != TASK_RUNNING,仅在更改状态后才适用。

在块io路径和存储设备的错误处理中使用GFP_NOIO。

所有其他情况都使用GFP_KERNEL。

还可以推断一些mem_flags的更具体规则,例如 (1) 网络驱动程序的start_xmit、timeout和receive方法必须使用GFP_ATOMIC(它们在持有自旋锁时被调用); (2) scsi驱动程序的queuecommand方法必须使用GFP_ATOMIC(也使用自旋锁); (3) 如果您使用带有网络驱动程序的内核线程,则必须使用GFP_NOIO,除非(b)或(c)适用; (4) 在执行down()后,您可以使用GFP_KERNEL,除非(b)或(c)适用或者您在存储驱动程序的块io路径中; (5) USB探测和断开连接可以使用GFP_KERNEL,除非(b)或(c)适用;和 (6) 更改正在运行的存储或网络设备的固件使用GFP_NOIO,除非b)或c)适用

请帮忙翻译以下英文 里面的回车有些地方是为了换行显示是不能用作断句的请注意辨别: usb_submit_urb - issue an asynchronous transfer request for an endpoint urb pointer to the urb describing the request mem_flags the type of memory to allocat

原文地址: https://www.cveoy.top/t/topic/ePGe 著作权归作者所有。请勿转载和采集!

免费AI点我,无需注册和登录