Bug in split transactions on Raspberry Pi

Doug Anderson dianders at chromium.org
Mon Jan 25 13:23:38 PST 2016


On Mon, Jan 25, 2016 at 1:04 PM, Alan Stern <stern at rowland.harvard.edu> wrote:
> On Mon, 25 Jan 2016, Doug Anderson wrote:
>> > Okay, I checked it.  Oddly enough, even though the SPLIT packet's
>> > contents are now correct, the device still doesn't respond.
>> >
>> > Bizarrely, when I interpose a USB-1.1 hub between the RPi and the
>> > compound device, it _does_ work.  I guess this indicates the device's
>> > embedded hub isn't quite up to snuff.  But why it should work okay with
>> > a PC and not with a Raspberry Pi is beyond me.
>> I just spent a lot of time tracking down lots of problems with SPLITs
>> in the mainline driver.  No idea if there are similar problems in the
>> RPI driver.
> The strange thing is that the packets sent to the device are now
> identical (except for address numbers and checksums) between the RPi
> and the PC.  And yet the device's embedded hub ACKs the packets from
> the PC and not the packets from the RPi.
> What other differences could there be?  Timing?  Power levels?
> Something else I'm not seeing?

I suppose there's a tiny chance it could be:


I haven't seen that fix anything, but it is conceivable that it could.
It wouldn't be hard to apply that change to the RPI driver.  It's
possible that without that fix dwc2 may be sending some extra bits in
each microframe or it's possible that there may be a period of time
with no bits sent at all (I haven't looked at the wire to see what
actually happens and my analyzer doesn't tell me).


It's certainly also possible that things are just scheduled in the
wrong microframes.  As I said, I can't comment on the RPI driver but I
do know that dwc2 makes you do _everything_ in software.  Software
needs to get involved every 125us which means you need to have very
good interrupt latency and need to be able to service the dwc2
interrupts quickly.

In dwc2 you can tell the hardware about 2 uFrams MAX.  When you give a
packet to hardware you give it the "even / odd" flag.  If the
"evenness" of the packet you gave to the hardware matches the current
microframe number then it's transmitted in the current uFrame.  If the
evenness doesn't match it's transmitted in the next uFrame.

As you could maybe imagine, it can be challenging to make packets show
up at the right time, especially if you've got a slow system or bad
interrupt latency.  Before my patches the driver also never looked at
how far we were through the current microframe, so things could get
pretty mixed up if the microframe "ticked" at an unexpected time.

On my analyzer I have it capture every piece of data it can so I can
see all the SOFs and see exactly when packets were queued.

>> Note that I have one hub that I've been debugging that still has
>> problems after all my patches.  My current (unsubstantiated) guess is
>> that the hub is somehow missing a reset or a configuration packet.
>> When I plug this hub in it either works or it doesn't work and seems
>> to stay in that state until I unplug / replug the hub.  I wonder if
>> there could be something similar?
> I doubt it, because the behavior I'm seeing is completely consistent
> from one run to another.
>> ...another interesting idea would be to try to see if you could just
>> change the configuration of the Raspberry Pi kernel to switch which
>> dwc2 driver it used.  Presumably their driver was an addition on top
>> of the driver in "drivers/usb/dwc2".  In fact, doing a 'git log' on
>> drivers/usb/dwc2 in the "rpi-4.4.y" kernel on github it looks pure
>> (and Stefan is even the last commit author!)
> I'll try it.  In case it works: There have been lots of patches from
> you and John posted to linux-usb in the last couple of months; which
> ones should I apply for testing on top of d51c7d840b002?  (That was the
> top commit on the master branch at the time I shallow-cloned the
> Raspberry Pi kernel from github -- looks like it's based on 4.1.15.)

It's possible it makes more sense to switch to the 4.4 RPI kernel
first to make thing simpler?  Presumably that would have fewer patches
to try applying atop.

Personally I just take all the dwc2 patches because otherwise merging
becomes a nightmare.  I run regularly on a 3.14 kernel with dwc2
backports and there wasn't anything too hard to apply and there
weren't many out-of-dwc2 dependencies.  The recent 21-patch series
from me was what made splits (and general microframe scheduling) more
reliable, but still not perfect.


More information about the linux-rpi-kernel mailing list