aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorStefan Richter <stefanr@s5r6.in-berlin.de>2008-04-12 16:31:25 -0400
committerStefan Richter <stefanr@s5r6.in-berlin.de>2008-04-18 11:55:35 -0400
commitd34316a4bdcd4fef050da584401c7f4ed22482f2 (patch)
tree4b6650cc815be1364ba4d9952b18818c5b602047
parent08ddb2f4c270b5dff063f7dbcd7e9248a52e7c65 (diff)
firewire: fw-ohci: work around generation bug in TI controllers (fix AV/C and more)
Unlike the ohci1394 driver, fw-ohci uses the selfIDGeneration field of bus reset packets to determine the generation of incoming requests as per OHCI 1.1 clause 8.4.2.3. This is more precise --- provided that the controller inserts the correct generation. Texas Instruments chips often don't. This prevented the transmission of response packets, which for example broke AV/C transactions as used when communicating with miniDV cameras and any other AV/C devices. There is apparently no way to detect and adjust incorrect generations. Therefore we ignore the generation of bus reset packets from TI chips and use the generation of the self ID buffer instead. Alas this is received at a slightly wrong time. In rare cases, this could cause us to not respond to legitimate requests or to respond to expired requests. (The latter is less likely because the bus reset packet AR event is typically handled before the self ID complete event.) Bug reported by Mladen Kuntner, who was extraordinarily patient while dealing with the driver maintainers. Fix confirmed to be required and effective for TSB82AA2 and a TSB43AB22 or TSB43AB22A. https://bugzilla.redhat.com/show_bug.cgi?id=243081 Signed-off-by: Stefan Richter <stefanr@s5r6.in-berlin.de> Signed-off-by: Jarod Wilson <jwilson@redhat.com>
-rw-r--r--drivers/firewire/fw-ohci.c21
1 files changed, 16 insertions, 5 deletions
diff --git a/drivers/firewire/fw-ohci.c b/drivers/firewire/fw-ohci.c
index b98d81967f70..d5d8177da6d9 100644
--- a/drivers/firewire/fw-ohci.c
+++ b/drivers/firewire/fw-ohci.c
@@ -181,6 +181,7 @@ struct fw_ohci {
181 int request_generation; 181 int request_generation;
182 u32 bus_seconds; 182 u32 bus_seconds;
183 bool old_uninorth; 183 bool old_uninorth;
184 bool bus_reset_packet_quirk;
184 185
185 /* 186 /*
186 * Spinlock for accessing fw_ohci data. Never call out of 187 * Spinlock for accessing fw_ohci data. Never call out of
@@ -571,14 +572,19 @@ static __le32 *handle_ar_packet(struct ar_context *ctx, __le32 *buffer)
571 * generation. We only need this for requests; for responses 572 * generation. We only need this for requests; for responses
572 * we use the unique tlabel for finding the matching 573 * we use the unique tlabel for finding the matching
573 * request. 574 * request.
575 *
576 * Alas some chips sometimes emit bus reset packets with a
577 * wrong generation. We set the correct generation for these
578 * at a slightly incorrect time (in bus_reset_tasklet).
574 */ 579 */
575 580 if (evt == OHCI1394_evt_bus_reset) {
576 if (evt == OHCI1394_evt_bus_reset) 581 if (!ohci->bus_reset_packet_quirk)
577 ohci->request_generation = (p.header[2] >> 16) & 0xff; 582 ohci->request_generation = (p.header[2] >> 16) & 0xff;
578 else if (ctx == &ohci->ar_request_ctx) 583 } else if (ctx == &ohci->ar_request_ctx) {
579 fw_core_handle_request(&ohci->card, &p); 584 fw_core_handle_request(&ohci->card, &p);
580 else 585 } else {
581 fw_core_handle_response(&ohci->card, &p); 586 fw_core_handle_response(&ohci->card, &p);
587 }
582 588
583 return buffer + length + 1; 589 return buffer + length + 1;
584} 590}
@@ -1285,6 +1291,9 @@ static void bus_reset_tasklet(unsigned long data)
1285 context_stop(&ohci->at_response_ctx); 1291 context_stop(&ohci->at_response_ctx);
1286 reg_write(ohci, OHCI1394_IntEventClear, OHCI1394_busReset); 1292 reg_write(ohci, OHCI1394_IntEventClear, OHCI1394_busReset);
1287 1293
1294 if (ohci->bus_reset_packet_quirk)
1295 ohci->request_generation = generation;
1296
1288 /* 1297 /*
1289 * This next bit is unrelated to the AT context stuff but we 1298 * This next bit is unrelated to the AT context stuff but we
1290 * have to do it under the spinlock also. If a new config rom 1299 * have to do it under the spinlock also. If a new config rom
@@ -2360,6 +2369,8 @@ pci_probe(struct pci_dev *dev, const struct pci_device_id *ent)
2360 ohci->old_uninorth = dev->vendor == PCI_VENDOR_ID_APPLE && 2369 ohci->old_uninorth = dev->vendor == PCI_VENDOR_ID_APPLE &&
2361 dev->device == PCI_DEVICE_ID_APPLE_UNI_N_FW; 2370 dev->device == PCI_DEVICE_ID_APPLE_UNI_N_FW;
2362#endif 2371#endif
2372 ohci->bus_reset_packet_quirk = dev->vendor == PCI_VENDOR_ID_TI;
2373
2363 spin_lock_init(&ohci->lock); 2374 spin_lock_init(&ohci->lock);
2364 2375
2365 tasklet_init(&ohci->bus_reset_tasklet, 2376 tasklet_init(&ohci->bus_reset_tasklet,