Commit 452a2de3 authored by Duncan Sands's avatar Duncan Sands Committed by Greg Kroah-Hartman

[PATCH] USB speedtouch: new speedtouch send path

Finally, here is the new code for sending packets.  The ATM layer passes us a skb
containing the packet to be sent.  We need to encode that as AAL5, and then encapsulate
the result in a series of ATM cells.  Finally, the result has to be sent to the modem.
When we have finished with the skb, we need to pass it back to the ATM layer.

The old code did this as follows: (1) Try to do the AAL5 encoding in place in the skb.
This fattens the packet, so there is not always enough room.  Thus sometimes a new skb
is allocated.  (2) Try to form the frame of ATM cells in place.  This also fattens the
packet, so sometimes another skb is allocated here too.  (3) send the urb, using the
skb as buffer.

The main problems with this are: (1) in the urb completion handler, we need to pass
the skb back to the ATM layer, or free it ourselves if we allocated a new one.  The
driver was pretty confused about which to do.  Also, error conditions were not
always handled right.  (2) if the ATM layer wants to close the VCC (connection),
any urbs in flight using skbs from that VCC need to be shot down, otherwise the
skb may be returned to a VCC that no longer exists when the urb completes.  You
have to be careful to shoot down the right urb (beware of resubmission), and deal
with failures of usb_unlink_urb.  (3) There may need to be several memory allocations.

The new code sidesteps all this by (1) not sending the skb off with the urb, and
(2) not reallocating the skb at all.  It simply has a couple of buffers of fixed
size: the encoded and encapsulated content of the skb is placed in a buffer.  The
skb is sent back down to the ATM layer and the buffer is sent off with the urb.
Et voila, as they say around here.

Now for the complicating factors: (1) if there are no spare buffers, the incoming
skb needs to be queued (this was already the case if there were no free urbs).  If
the VCC is closed, the skbs from that VCC need to be removed from the queue.  This
is trivial and is done in udsl_usb_cancelsends.  (2) The skbs can be quite big.  In
practice, with the default configuration for pppd, they contain at most 1502 bytes.
However pppd can be configured to send up to 16k packets, and who says everyone
is using pppd? - the ATM layer allows up to 64k packets.  So how big should the
buffers be?  Not 64k, that's for sure - I've set them to about 6k (128 ATM cells).
So there needs to be a way to encode/encapsulate and transfer only part of the skb's
payload into a buffer.  This is done by udsl_write_cell, which extracts one ATM
cell from the skb.  The data needed is precalculated by udsl_groom_skb and stored
in the skb's cb field.  This also means that if there is only a little room left
in a buffer, it can still be filled by extracting part of a skb.  A nice consequence
is that under heavy load (many packets being sent), the driver starts streaming the
data to the USB subsystem: every time a send urb completes, there is a completely
filled buffer waiting to be sent, so not only is the time between urb completion and
resubmission essentially zero, but the amount of data sent in each USB transaction is
as big as possible, each buffer containing the contents of several skbs (typically 4).

And the best thing is: it actually works!
parent 210e817e
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment