[RFC][PATCH 00/20] USB: serial: major refactoring work

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Hi,

Looking through the USB serial driver code one is quite quickly struck by the
amount of code which could have been shared but instead is reimplemented (or
even copied more or less verbatim) in many drivers. The various custom
fifo-implementations are obvious examples, but there is even more that can be
be done in terms of code reuse.

I've worked with three drivers that have somewhat different characteristics: 

cp210x		a generic driver which uses the generic read and write (fifo)
		implementations

ftdi_sio	custom read and write implementations, where the latter 
		allocates urbs and buffer on the fly

pl2303		custom read and write implementations, where the latter uses a
		custom fifo implementation

My plan was to improve the generic driver and its interfaces and to make
ftdi_sio and pl2303 use the generic implementations as well, while using
cp210x as a baseline for my changes to the generic driver.


It turns out that the amount of code that can be shared is quite high:

 drivers/usb/serial/cp210x.c     |   16 +--
 drivers/usb/serial/ftdi_sio.c   |  375 +++++------------------------------
 drivers/usb/serial/generic.c    |  280 +++++++++++---------------
 drivers/usb/serial/pl2303.c     |  421 +++------------------------------------
 drivers/usb/serial/usb-serial.c |    2 +
 drivers/usb/serial/usb_debug.c  |    4 +-
 include/linux/usb/serial.h      |   19 ++-
 7 files changed, 208 insertions(+), 909 deletions(-)


As a further example of the potential of the interface changes I propose below,
I also turned the aircable driver into a generic one:

 drivers/usb/serial/aircable.c |  498 ++++-------------------------------------
 1 files changed, 46 insertions(+), 452 deletions(-)


The patches listed below can be divided into sub-series that are fairly
independent but I decided to submit them all at once. I would claim that most
of them are fairly uncontroversial but I'm specifically asking for comments
on the prepare_write_buffer interface.

The patches are against 2.6.34-rc1 with the patches from Greg's tree applied.
Note that they also depend on the patch series of fixes I recently submitted
separately (USB: serial: generic driver fixes and bulk buffer feature).


Here is a summary:

1. Read patches
These patches clean up the generic driver's read implementation and generalises
it by adding a new function pointer to usb_serial_driver called
process_read_urb. The idea is that drivers should not have to reimplement read
urb handling (submission, re-submission, throttling etc) but rather be handed
the received bulk data to be processed as needed before pushing it to the line
discipline.

Both pl2303 and ftdi_sio handles overruns, breaks, etc here, whereas cp210x
uses the default implementation which simply pushes to ldisc. The ftdi_sio (and
aircable) also takes care of headers in incoming data here.


2. Fifo write patches
This sub-series starts off with a couple of clean-ups. The custom pl2303
fifo-based write implementation is then thrown out and replaced by the generic
kfifo-based one. This patch was actually submitted a couple of days ago (and
this is the reason why I did not merge it with the following patch -- "use
generic close").


3. Multi-urb write patches
There are currently two write implementations in the generic driver -- one
uses a kfifo and the other allocates urbs and buffer on the fly. The latter is
similar to what the ftdi_sio is doing but it is still not quite the same.

The current generic multi-urb implementation splits an incoming write request
into multiple urbs and endpoint-sized buffers (e.g. 64b) instead of
allocating a single urb and large-enough buffer (e.g. 2k) and let the host
controller to the partitioning to fit end-point size which is more efficient.

Based on this observation I reimplement multi-urb writes so that only one
buffer allocation and one urb allocation is done per write request. 

Before changing this I decided to let the usb_debug driver -- the only
current user of multi-urb writes -- use the kfifo-based write-implementation
(which wasn't available when multi-urb writes was added to usb_debug). It seems
to make more sense to use a fifo with a small bulk_out_size (the device seem to
require 8 byte buffers) than to allow up to 4000 urbs and buffers to be
allocated and dispatched to the host stack.


4. Write prepare
Now we have all the infrastructure in place to turn most drivers into generic
ones: either using fifo-based or multi-urb-based writes. The rationale for
keeping both schemes is that some devices require more than a single urb to
achieve maximum throughput at high baudrates (e.g. ftdi_sio at 3Mbaud).

There is however a category of devices which can't easily be turned into
generic ones -- devices that require headers to be added to the bulk out data
before it is sent. The legacy FTDI SIO device is an example of this.

I propose an interface to let drivers process the outgoing data by adding a new
function prototype to usb_serial_driver called prepare_write_buffer which will
be called from the generic write implementations.

Unfortunately, things get a little more complicated than in the read case as
we have two generic write implementations. The solution I've chosen (after some
iteration), and which I'm asking for feedback on, is to have one function being
able to handle both schemes. The prototype looks like this:

	int (*prepare_write_buffer)(struct usb_serial_port *port,
		void **dest, size_t size, const void *src, size_t count);

With rules such as "allocate *dest if NULL", and "use port->write_fifo if src is
NULL" both schemes can be incorporated. Perhaps two different prototypes could be
used instead (prepare_write_buffer_fifo/prepare_write_buffer_multi). The
generic prepare_write_buffer implementation handles both cases, but drivers
could choose to only support only one mode (e.g. only fifo-based writes).

I use the prepare_write feature to finally turn ftdi_sio into a fully generic
driver as well.


5. Example
To further exemplify the power and usefulness of prepare_write_urb and
process_read_urb I also convert the aircable driver into a generic one. This
drivers does not handle line status, but the aircable protocol uses headers
for both incoming and outgoing bulk data.

Note however that this final patch has been compile-only tested.


Thanks,
Johan


Johan Hovold (20):
1. read
  USB: serial: refactor read urb submission in generic driver
  USB: serial: remove unnecessary re-initialisation of generic urbs
  USB: cp210x: use generic submit_read_urb at open
  USB: serial: clean up read processing in generic driver
  USB: serial: generalise generic read implementation
  USB: pl2303: switch to generic read implementation
  USB: serial: export generic throttle and unthrottle
  USB: ftdi_sio: switch to generic read implementation
2. write-kfifo
  USB: serial: clean up some error and debug messages in generic driver
  USB: serial: clean up generic write start busy test
  USB: pl2303: switch to generic write implementation
  USB: pl2303: use generic close
3. write-multi
  USB: usb_debug: use the generic kfifo-based write implementation
  USB: serial: allow custom multi-urb write bulk callbacks
  USB: serial: re-implement multi-urb writes in generic driver
4. write-prepare
  USB: serial: generalise write buffer preparation
  USB: ftdi_sio: fix some coding style issues
  USB: ftdi_sio: switch to generic write implementation
  USB: ftdi_sio: clean up SIO write support
5. example
  USB: aircable: rewrite using generic read and write implementations

 drivers/usb/serial/aircable.c   |  498 ++++-----------------------------------
 drivers/usb/serial/cp210x.c     |   16 +-
 drivers/usb/serial/ftdi_sio.c   |  375 ++++--------------------------
 drivers/usb/serial/generic.c    |  280 +++++++++-------------
 drivers/usb/serial/pl2303.c     |  421 ++-------------------------------
 drivers/usb/serial/usb-serial.c |    2 +
 drivers/usb/serial/usb_debug.c  |    4 +-
 include/linux/usb/serial.h      |   19 ++-
 8 files changed, 254 insertions(+), 1361 deletions(-)

--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html

[Index of Archives]     [Linux Media]     [Linux Input]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]     [Old Linux USB Devel Archive]

  Powered by Linux