linux/drivers/firewire
Clemens Ladisch 32eaeae177 firewire: ohci: work around selfID junk due to wrong gap count
If a device's firmware initiates a bus reset by setting the IBR bit in
PHY register 1 without resetting the gap count field to 63 (and without
having sent a PHY configuration packet beforehand), the gap count of
this node will remain at the old value after the bus reset and thus be
inconsistent with the gap count on all other nodes.

The bus manager is supposed to detect the inconsistent gap count values
in the self ID packets and correct them by issuing another bus reset.

However, if the buggy device happens to be the cycle master, and if it
sends a cycle start packet immediately after the bus reset (which is
likely after a long bus reset), then the time between the end of the
selfID phase and the start of the cycle start packet will be based on
the too-small gap count value, so this gap will be too short to be
detected as a subaction gap by the other nodes.  This means that the
cycle start packet will be assumed to be self ID data, and will be
stored after the actual self ID quadlets in the self ID buffer.

This garbage in the self ID buffer made firewire-core ignore all of the
self ID data, and thus prevented the Linux bus manager from correcting
the problem.  Furthermore, because the bus reset handling was aborted
completely, asynchronous transfers would be no longer handled correctly,
and fw_run_transaction() would hang until the next bus reset.

To fix this, make the detection of inconsistent self IDs more
discriminating:  If the invalid data in the self ID buffer looks like
a cycle start packet, we can assume that the previous data in the buffer
is correctly received self ID information, and process it normally.

(We inspect only the first quadlet of the cycle start packet, because
this value is different enough from any valid self ID quadlet, and many
controllers do not store the cycle start packet in five quadlets because
they expect self ID data to have an even number of quadlets.)

This bug has been observed when a bus-powered DesktopKonnekt6 is
switched off with its power button.

Signed-off-by: Clemens Ladisch <clemens@ladisch.de>
Signed-off-by: Stefan Richter <stefanr@s5r6.in-berlin.de>
2011-10-18 12:32:39 +02:00
..
Kconfig Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/ieee1394/linux1394-2.6 2011-03-21 10:05:22 -07:00
Makefile ieee1394: move init_ohci1394_dma to drivers/firewire/ 2010-10-11 14:48:03 +02:00
core-card.c atomic: use <linux/atomic.h> 2011-07-26 16:49:47 -07:00
core-cdev.c firewire: cdev: fix 32 bit userland on 64 bit kernel compat corner cases 2011-08-12 15:30:08 +02:00
core-device.c Merge branch 'fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/ieee1394/linux1394-2.6 2011-08-21 18:13:19 -07:00
core-iso.c firewire: optimize iso queueing by setting wake only after the last packet 2011-05-10 22:53:45 +02:00
core-topology.c atomic: use <linux/atomic.h> 2011-07-26 16:49:47 -07:00
core-transaction.c firewire: use clamp and min3 macros 2011-10-09 17:00:18 +02:00
core.h atomic: use <linux/atomic.h> 2011-07-26 16:49:47 -07:00
init_ohci1394_dma.c ieee1394: move init_ohci1394_dma to drivers/firewire/ 2010-10-11 14:48:03 +02:00
net.c firewire: net: Use posted writes 2011-10-09 17:00:18 +02:00
nosy-user.h firewire: nosy: endianess fixes and annotations 2010-07-27 11:04:11 +02:00
nosy.c atomic: use <linux/atomic.h> 2011-07-26 16:49:47 -07:00
nosy.h firewire: nosy: misc cleanups 2010-07-27 11:04:10 +02:00
ohci.c firewire: ohci: work around selfID junk due to wrong gap count 2011-10-18 12:32:39 +02:00
ohci.h firewire: ohci: fix TI TSB82AA2 regression since 2.6.35 2010-10-17 14:09:12 +02:00
sbp2.c firewire: use clamp and min3 macros 2011-10-09 17:00:18 +02:00