Date: Fri, 27 Mar 2009 11:27:40 -0700 From: Andrew Thompson <thompsa@FreeBSD.org> To: usb <usb@freebsd.org> Cc: current@freebsd.org Subject: Proposed USB data buffer changes Message-ID: <20090327182740.GB26662@citylink.fud.org.nz>
next in thread | raw e-mail | index | archive | help
Hi, I want the USB peripheral driver API to be solid before 8.0 so things dont bite us down the line. I have discussed this privately with Hans already and want to put it out for public consumption. With the new USB code the buffer management has been merged into the xfer structure and this dictates the layout of the usb drivers and how locking is performed. This uses a state machine (my attempt to show below) |-< |-< XFER <-| <-| | | | | --------- callback_fn --------- | | | | | -> SETUP (copyin) >-| | | | -> COMPLETE (copyout) >-| It can take an external buffer instead of the copyin/out but it doesnt really simplify things at all. The problems I see with this approach are 1. It is in contrast to other major operating systems, making porting drivers harder. Windows, Linux and oldUSB all use a URB style of data handling. 2. It greatly complicates locking as the xfer lock can not be dropped until the xfer is resubmitted. This requirement to hold the lock creates a big problem for get/put of data to another layer (eg TTY), to avoid lock order reversals the drivers are generally written to share the lock with the lower/upper layer (eg TTY). 3. In the general case data can not be directly queued on the xfer (must be "picked" up by the state machine callback). This limits the options for designing a driver and may require the driver to implement a queue. I think its vital that we separate out the data buffers from the xfer (its actually a pipe in usb speak). It should draw from the Linux API which is simple and I believe works quite well. The data buffer is represented as a usb URB which is allocated either at attach or on the fly and then queued on the xfer (pipe) for processing. An arbitrary number of URB buffers can be on the queue. As the buffer would only have a single reference it would not need explicit locking, the callback would not need the xfer lock to be held at all and this would make it _much_ easier to handoff the data without LOR. This reduction in locking means that the driver and the xfer do not need to share a lock either, something that is mandatory now. The xfer can have a private lock for enqueue/start/stop. Example functions could be, usb_alloc_urb - Creates a URB representing data and housekeeping, the data section can be allocated or passed in from say a mbuf. This can also perform the DMA foo. usb_submit_urb - Queues the URB on the usb pipe. I dont think this would take much work. The xfer callbacks would be changed to take a URB and a few changes to queuing. It was mentioned the reason for this approach was to preallocate and do DMA setup on attach but this can still easily be done with the above. Comments? cheers, Andrew
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20090327182740.GB26662>