Hi,

what I'm going to describe below is the result of some latency measurement
which I've repeated for UHCI (my primary target system is OHCI) and which
reveals some not-so-easy-to-observe differences between how uhci(JE) and
usb-uhci(GA) HCD manages usb transfers.

The short story is uhci.c may occasionally switch to some pathological
packet scheduling pattern during a running bulk transfer. Nothing is lost
and no error occurs but every few seconds or so some individual transfer
is executed a strange way leading to a massive momentary drop in bus time
usage (i.e. normal transfer time increased by several 100 msec!).

At a first glance, this seems to be a minor issue. Nevertheless it 
deserves some explanation. OTOH I would not be completely surprised to
find the reason behind might also have some impact on iso transfers, for
which some uhci.c related problems have been reported.

Since the problem is not very easy to observe with common usb device, let
me provide a detailed description of what I've done.

First, I've tried using different HCD: OHCI was always fine. UHCI was
always fine too - whenever I used usb-uhci.c. Tried with both Intel and
VIA HC's. As soon as I use uhci.c the issue appears for both Intel and
VIA. Besides using different HCD, nothing was changed for all these tests.
So I'm pretty sure it's specific for uhci.c

The device was an EZ-USB FX development board directly connected to one of
the ports on the mainboard (i.e. no hub in between).  The firmware of the
device represents simply an infinite source of data. Data is provided from
double-buffered bulk-in-ep with 64 byte packet size. Throughput and
maximum latency are _much_ better than what would be needed to saturate
the complete maximum bandwidth (1216 bytes per usb frame).

The thing came up when I created some timing statistics for several phases
of bulk-in transfers. Transfers were not queued and size=64kB each. All
measurement was done using the usb frame number as 1msec counter.
Following times where measured:

t1: before calling usb_submit_urb() until return from that call
t2: from return from usb_submit_urb() until first data packet transfered
t3: between sending first and last packet on the device side
t4: from device sending last packet until completion handler called
t5: from completion handler until sleeping process awoken
T: sum of t1..t5, i.e. from usb_submit_urb() until process wakeup

The observed average values (msec) for 64kB transfer to unloaded host:

                t1      t2      t3      t4      t5      T
usb-ohci        0.9     0.2     56      1       0       58      
usb-uhci        3.1     1       59      3       1       67
uhci            1.9     1       60      5       0       68

So, in the average there is nothing wrong with all this. OHCI is pretty
close to the theoretical optimum (1.13MB/sec compared to 1.2 - queueing
should get close to 1.17) and UHCI (both) somewhat behind.
[I'm not trying to comment on the apparent shift of about 2msec from
submit to completion position when comparing both uhci-flavours - but it
is definitely significant from the statistics]

The problem however becomes evident when looking at the individual
t3-values, which I've recorded over several minutes of continuous
transfer: They are pretty stable for both usb-ohci and usb-uhci (1-2 msec
maximum jitter). For uhci however, every few seconds this number jumps to
values of several 100 msec (up to 350 or so) for a single transfer. Other
t* values remain at their average. I.e. without an apparent scheme,
every few random seconds (1...15 to get an idea), uhci decides to
dramatically extend the time for which a single transfer is on the wire.

Since I don't have a special analyzer at hand, I've used a scope to get
more information. First I've excluded things like noise/spikes/other
distortions on the wire - fine.

Looking at a "normal" transfer, the 1msec frame was well filled with
typically 16 data-packets placed after the SOF-packet in every frame
for the whole transfer (typically, because usb-uhci sometimes decided to
put a 17th data-packet into the not so small idle-gap at the end of the
frame).
Remark: when talking about data-packet I mean the complete interaction,
i.e. the token packet from host to device, the data payload packet from
the device and the handshake packet returned by the host.

For the strange "long" transfers of uhci the following happens:

At some instant _during_ the running transfer the data-packet arrangement
switches from 16-per-frame to 1-per frame. Apparently this never happens
within the first 40kB or so - that's why you need at least about 50KB
transfer size to detect this! If it happens, the remaining 10..20kB are
transfered using only about 1/16 of the bus time.

Although it's pretty hard to do with the scope, I've managed to catch some
of these alone-in-frame packets. There's nothing wrong with them. They are
properly ACK'ed by the host well in time (16-18 bit bus turnaround time).
There is no IN token following. Seems the host for some unknown reason
decides not to want more than one packet per frame.

Hopefully, this detailed description might help somebody who has a good
understanding of the internal details for both UHCI HC's to get some idea
what might happen for uhci but not for usb-uhci. For me, the described
behavior is no problem at all. But, if similar dropouts would happen for
iso-transfer it might cause some trouble rather easy.

One idea I have is based on the "usb-uhci sometimes uses 17 data-packets
per frame" observation. This works fine for usb-uhci. For uhci however
I've never seen this on the wire. Simply looking at the bus-idle intervall
at the end of each frame, my conclusion is, 17 packets should be possible
for every frame - with still about 2-3 usec left. Don't know, why usb-uhci
does only occasionally picks this up. Well, I'm blindly guessing, but it
might be possible the "long" transfers for uhci are exactly those which
are scheduled 17/frame for usb-uhci. Some kind of "frame almost exactly
filled" bandwith grant situation in combination with bit-stuffing? (the 64
byte data packets are all always identical except for the first 4 bytes
containing the (u32) current frame number when the device loads the data
into the buffer - so most packets will not need bit-stuffing - except
every now and then when the frame numbers contains at least 6
consequetive "1" bits.)

Needless to say, I'm willing to do further testing or provide more
information if it might help!

Martin


_______________________________________________
[EMAIL PROTECTED]
To unsubscribe, use the last form field at:
http://lists.sourceforge.net/lists/listinfo/linux-usb-devel

Reply via email to