Re: Split bulk transfers

Laurent Pinchart <[email protected]>
Newsgroups gmane.linux.usb.devel
Message-ID <[email protected]>
Hi Alan,

thanks for your clear answer. A few questions follow.

On Wednesday 09 May 2007, Alan Stern wrote:
> On Wed, 9 May 2007, Laurent Pinchart wrote:
> > Hi everybody,
> >
> > I'm running into an issue where large bulk transfers require lots of host
> > memory. To fix the problem (without upgrading the system memory), I tried
> > to implement "split bulk transfers". The first test results are
> > promising, but there are a few borderline cases that I'm not able to
> > test. I'd like to have your opinion on those. First of all, a little
> > background (I'll be talking about IN bulk transfers here) to make sure I
> > got everything right.
> >
> > Bulk transfers are payload oriented. The device usually reports the
> > maximum payload size, and the host allocated URBs big enough to transfer
> > a complete payload. The URBs are then divided in packets (by the host USB
> > stack or the host controller, I'm not sure about this), and data is
> > transfered packet by packet until the device signals the end of the
> > payload by a packet shorter than the maximum packet size, which can lead
> > to a 0-byte packet if the payload size is an exact multiple of the packet
> > size. The host detects that short packet, finishes processing the URB and
> > calls the completion handler. The short packet is required to detect
> > payload end, as the actual payload size might be smaller than the maximum
> > payload size reported by the device (payloads can have variable sizes).
> >
> > This works fine, but requires a lot of memory when the maximum payload
> > size is big. Someone reported running across a device with a maximum
> > payload size of 2.7MB, and as my driver allocates 5 bulk URBs, that makes
> > a lot of memory especially for embedded or other memory constrained
> > hosts. To work around this, the idea was to use smaller URBs that would
> > not carry a complete payload, but part of a payload. A payload would thus
> > be divided across several URBs, which would in turn be divided in USB
> > packets.
>
> The scatter-gather routines in drivers/usb/core/message.c do something
> similar to what you're describing.  But they assume that all the memory
> buffers have already been allocated, so they won't help solve your main
> problem (memory usage).

I wasn't aware of those functions. Just to make sure I get this right, am I 
right to say that URB buffers should be allocated as contiguous cache 
coherent physical memory (using usb_buffer_alloc, which in turns call 
dma_alloc_coherent for big DMAable buffers) or as normal memory using 
scatter-gather routines ?

I currently allocate big bulk buffers using usb_buffer_alloc, which puts a lot 
of pressure on the memory allocator. Using scatter-gather mappings would 
help. However, if I'm not mistaken, the usb_sg_* routines are designed for 
synchronous use (with usb_sg_wait), and thus can't be used for streaming 
data.

> > The problem I now have is to make sure I can detect the payload end
> > reliably. When the payload size is not an exact multiple of the URB size,
> > all the URBs except the last one will be filled with data. The last URB
> > will have an actual size smaller than its maximum size, which is how I
> > detect the payload end. When the payload size is an exact multiple of the
> > URB size, all URBs will have the same actual length. I would like to know
> > (and I can't test this as my test device has fixed-size payloads with
> > sizes that are not an exact multiple of the bulk packet size) if the USB
> > stack will return an empty URB to the completion handler, much like the
> > USB device sends an empty packet.
>
> Yes, it will.

Great.

> > If so, are there any other caveats I should be aware of when splitting the
> > payload across multiple bulk URBs ? And if no empty URB is currently
> > returned by the Linux USB stack, is that something that could/should/will
> > be fixed ?
>
> I assume that you submit your URBs one at a time, waiting for each one to
> complete before submitting the next, since the idea is to minimize memory
> usage.  If you were to submit several URBs at once, you would need to set
> the URB_SHORT_NOT_OK flag transfer flag on all but the last -- just
> theoretical, since you're not in this situation.

Actually I'm not. I submit a few URBs to get high throughput. Even with 
several URBs, memory usage is smaller than with a single payload-sized URB.

Why do I need to set URB_SHORT_NOT_OK on all but the last URB ? As the actual 
payload size isn't known (only the maximum payload size is known), a short 
packet can be received at any time. The next URBs will be filled with the 
next payload, right ?

> You should make sure that each URB's transfer_buffer_length is a multiple
> of the maxpacket size.  This is probably obvious; if you didn't do it then
> you would get an EOVERFLOW error.  There aren't any other constraints on
> the transfer sizes; you can make them as big or as small as you see fit.

That was indeed obvious, but still worth mentioning.

> There's a possible ambiguity if the maximum payload size is a multiple of
> the maxpacket size. If it is, and if the device wants to send a
> maximum-sized payload, does it also send a 0-length packet at the end?

That's a very good question. I haven't come across devices with a maximum 
payload size multiple of the maximum packet size.

> In theory it should not, but devices don't always obey the spec in this
> regard. Anyway, you will need to cope with the device's behavior.

I didn't know about that. Thanks.

> If it doesn't send the extra 0-length packet, then you have to make sure
> that your last URB's length is exactly the right amount to make up a
> maximum-sized payload.

Otherwise the last URB will be filled with packet from the next payload, 
right ?

> If it does send an extra 0-length packet then your last URB needs a larger
> length, so that the 0-length packet will be received properly.

If the last URB doesn't have a larger length, won't the 0-length packet be 
received by the next URB, making the USB stack call the completion handler 
with a 0-length URB ?

> Other than that, you should be okay.

Thanks a lot for your help once again.

Laurent Pinchart

-------------------------------------------------------------------------
This SF.net email is sponsored by DB2 Express
Download DB2 Express C - the FREE version of DB2 express and take
control of your XML. No limits. Just data. Click to get it now.
http://sourceforge.net/powerbar/db2/
_______________________________________________
[email protected]
To unsubscribe, use the last form field at:
https://lists.sourceforge.net/lists/listinfo/linux-usb-devel
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.