USB: how to pick segment lengths?

hi

I would like to know what values you folks are specifying in your read/write handlers to make your XP USB bulk transfers efficient.

( 1 ) For the DDK Bulk sample, I see that it makes an initial check to see if the total length to transfer is greater than BULKUSB_TEST_BOARD_TRANSFER_BUFFER_SIZE, which is 64K and I guess is the maximum amount of data the USB device can store for the bulk endpoint.

( a ) Is this correct? Is the max buffer side on the usb device dictating the total length of transfer (the sum of the segment length transfers)?

( b ) Must this check be made? For example, if this was a write transaction in the function driver and the data to be written was 128K but the USB device could only store 64 K in its buffers, would the USBD subsystem fail the transaction? Or would the problem be that the transaction would end up pending until the USB device read data out of its buffers which would make room for the USBD system to write more data? I could see that pending would be bad because you would be wasting bandwidth while pending.

(2 ) For a multiple stage transfer (I.e. multiple calls to USBBuildInterruptOrBulkTransferRequest), how do you determine what to pass as the stage length (the number of bytes to transfer for each UsbBuildInterruptOrBulkTransfer request)?

( a ) I know the USB spec says that this length has to be a multiple of the MaxPacketSize, but how do you pick the segment length? In other words, how do you pick what multiple of MaxPacketSize should be specified as the segment length?

I could see that the bigger the segment length value, the less number of stage lengths you need, so you might be more efficient.
I could also see picking this segment length dynamically - for example, for the write case, you would pick the stage length to be the maximum number that does not exceed the total data buffer length.

The DDK bulk sample uses a fixed constant (#define) for this: 4 * 64 (BULKUSB_MAX_TRANSFER_SIZE) as the segment length.
( b ) How was this value picked (given that 64 is the max packet size for USB 1.1 bulk transfers)?

Does this have anything to do with some sort of buffer size in the USB device? If so, typically what would this be?

The reason I ask this is because I have a USB 1.1 bulk in and bulk out endpoints and I want to make sure I maximize throughput by adjusting the parameters correctly. I hope that some of you have already gone down this path before and have words of wisdom of what these values should be, before I start experimenting.

thanks

S. Drasnin wrote:

I would like to know what values you folks are specifying in your
read/write handlers to make your XP USB bulk transfers efficient.

Experimentation. Trial and error.

( 1 ) For the DDK Bulk sample, I see that it makes an initial check to
see if the total length to transfer is greater than
BULKUSB_TEST_BOARD_TRANSFER_BUFFER_SIZE, which is 64K and I guess is
the maximum amount of data the USB device can store for the bulk
endpoint.

( a ) Is this correct? Is the max buffer side on the usb device
dictating the total length of transfer (the sum of the segment length
transfers)?

( b ) Must this check be made? For example, if this was a write
transaction in the function driver and the data to be written was 128K
but the USB device could only store 64 K in its buffers, would the
USBD subsystem fail the transaction?

USBD has absolutely no idea how large the device’s FIFOs are. It will
keep sending data blindly. If the device’s FIFO fills, it needs to
figure out how to handle things. Will it throw away excess data? Will
it fail the transfer?

Remember that a single USB 1.1 frame can only transfer about 1,200
bytes. If you send down a single URB with 512k bytes, it will hang
around for half a second before it completely drained. That’s a long
time for your driver to be in the dark. In many cases, that’s OK, but
you need to think about it.

Or would the problem be that the transaction would end up
pending until the USB device read data out of its buffers which would
make room for the USBD system to write more data? I could see that
pending would be bad because you would be wasting bandwidth while pending.

It’s not really wasting bandwidth. The bus can still be used by other
devices. Only your device is blocked, and if the FIFOs are full, you
don’t want any more data anyway.

The DDK bulk sample uses a fixed constant (#define) for this: 4 * 64
(BULKUSB_MAX_TRANSFER_SIZE) as the segment length.
( b ) How was this value picked (given that 64 is the max packet size
for USB 1.1 bulk transfers)?

Does this have anything to do with some sort of buffer size in the USB
device? If so, typically what would this be?

I suspect it is a random number, chosen because they had to choose SOME
number. Remember this sample is for a fictional device.

There is no “typical” size of a FIFO in a USB device. The hardware
designers sit around the lunch table and decide, “I think our FIFO
should allow us to ride through a delay of 37 microseconds.” One of
them gets out their slide rule, and next thing you know, the FIFO size
is settled.

The reason I ask this is because I have a USB 1.1 bulk in and bulk out
endpoints and I want to make sure I maximize throughput by adjusting
the parameters correctly. I hope that some of you have already gone
down this path before and have words of wisdom of what these values
should be, before I start experimenting.

Experimentation is the right way to go. It’s very difficult to give
general rules because of variations in the size and meaning of buffers,
the size of FIFOs, and the rate at which devices accept data. The key
is never to let the queue run dry. If USBD gets to the start of a frame
and finds there are no URBs queued up for your device, you’re going to
miss that frame. You need to have URBs queued up and ready to go. You
cannot, for example, use one URB, and wait until it comes back before
resubmitting. That will suck.

Is your device faster than the bus, or slower than the bus? That makes
a difference, too. If your device is slower than the bus, the
requirements are simpler.


Tim Roberts, xxxxx@probo.com
Providenza & Boekelheide, Inc.

> ----------

From: xxxxx@lists.osr.com[SMTP:xxxxx@lists.osr.com] on behalf of Tim Roberts[SMTP:xxxxx@probo.com]
Reply To: Windows System Software Devs Interest List
Sent: Tuesday, August 30, 2005 6:52 PM
To: Windows System Software Devs Interest List
Subject: Re: [ntdev] USB: how to pick segment lengths?

> I would like to know what values you folks are specifying in your
> read/write handlers to make your XP USB bulk transfers efficient.

Experimentation. Trial and error.

Exactly. And I guess I already posted some numbers.

USBD has absolutely no idea how large the device’s FIFOs are. It will
keep sending data blindly. If the device’s FIFO fills, it needs to
figure out how to handle things. Will it throw away excess data? Will
it fail the transfer?

Usually devices send NAKs until there is space available.

I suspect it is a random number, chosen because they had to choose SOME
number. Remember this sample is for a fictional device.

I suspect it, too :slight_smile: It isn’t too important number. I set it to 256 kB because it is the largest transfer size for our communication protocol. If performance is the main goal, it is better to queue more smaller buffers.

Experimentation is the right way to go. It’s very difficult to give
general rules because of variations in the size and meaning of buffers,
the size of FIFOs, and the rate at which devices accept data. The key
is never to let the queue run dry. If USBD gets to the start of a frame
and finds there are no URBs queued up for your device, you’re going to
miss that frame. You need to have URBs queued up and ready to go. You
cannot, for example, use one URB, and wait until it comes back before
resubmitting. That will suck.

Two URBs should be enough but is computer is busy, app may not be able to feed driver with buffer quickly enough. In my experience, 4 pending request are minimum, 8 is better and 16 reasonable. But all depends on the device, data rate, protocol used etc. Time to start with experiments :slight_smile:

Best regards,

Michal Vodicka
UPEK, Inc.
[xxxxx@upek.com, http://www.upek.com]

Thanks Michal and Tim for the good info.
----- Original Message -----
From: Michal Vodickamailto:xxxxx
To: Windows System Software Devs Interest Listmailto:xxxxx
Sent: Tuesday, August 30, 2005 11:56 AM
Subject: RE: [ntdev] USB: how to pick segment lengths?

> ----------
> From: xxxxx@lists.osr.com[SMTP:xxxxx@lists.osr.commailto:xxxxx] on behalf of Tim Roberts[SMTP:xxxxx@probo.com]
> Reply To: Windows System Software Devs Interest List
> Sent: Tuesday, August 30, 2005 6:52 PM
> To: Windows System Software Devs Interest List
> Subject: Re: [ntdev] USB: how to pick segment lengths?
>
> > I would like to know what values you folks are specifying in your
> > read/write handlers to make your XP USB bulk transfers efficient.
>
> Experimentation. Trial and error.
>
Exactly. And I guess I already posted some numbers.

> USBD has absolutely no idea how large the device’s FIFOs are. It will
> keep sending data blindly. If the device’s FIFO fills, it needs to
> figure out how to handle things. Will it throw away excess data? Will
> it fail the transfer?
>
Usually devices send NAKs until there is space available.

> I suspect it is a random number, chosen because they had to choose SOME
> number. Remember this sample is for a fictional device.
>
I suspect it, too :slight_smile: It isn’t too important number. I set it to 256 kB because it is the largest transfer size for our communication protocol. If performance is the main goal, it is better to queue more smaller buffers.

> Experimentation is the right way to go. It’s very difficult to give
> general rules because of variations in the size and meaning of buffers,
> the size of FIFOs, and the rate at which devices accept data. The key
> is never to let the queue run dry. If USBD gets to the start of a frame
> and finds there are no URBs queued up for your device, you’re going to
> miss that frame. You need to have URBs queued up and ready to go. You
> cannot, for example, use one URB, and wait until it comes back before
> resubmitting. That will suck.
>
Two URBs should be enough but is computer is busy, app may not be able to feed driver with buffer quickly enough. In my experience, 4 pending request are minimum, 8 is better and 16 reasonable. But all depends on the device, data rate, protocol used etc. Time to start with experiments :slight_smile:

Best regards,

Michal Vodicka
UPEK, Inc.
[xxxxx@upek.com, http://www.upek.comhttp:</http:>]


Questions? First check the Kernel Driver FAQ at http://www.osronline.com/article.cfm?id=256http:

You are currently subscribed to ntdev as: unknown lmsubst tag argument: ‘’
To unsubscribe send a blank email to xxxxx@lists.osr.commailto:xxxxx</mailto:xxxxx></http:></mailto:xxxxx></mailto:xxxxx></mailto:xxxxx>