firewire: fw-ohci: TSB43AB22/A dualbuffer workaround

Isochronous reception in dualbuffer mode is reportedly broken with
TI TSB43AB22A on x86-64. Descriptor addresses above 2G have been
determined as the trigger:
https://bugzilla.redhat.com/show_bug.cgi?id=435550

Two fixes are possible:
- pci_set_consistent_dma_mask(pdev, DMA_31BIT_MASK);
at least when IR descriptors are allocated, or
- simply don't use dualbuffer.
This fix implements the latter workaround.

But we keep using dualbuffer on x86-32 which won't give us highmen (and
thus physical addresses outside the 31bit range) in coherent DMA memory
allocations. Right now we could for example also whitelist PPC32, but
DMA mapping implementation details are expected to change there.

Signed-off-by: Stefan Richter <stefanr@s5r6.in-berlin.de>
Signed-off-by: Jarod Wilson <jwilson@redhat.com>

+25 -13
+24 -13
drivers/firewire/fw-ohci.c
··· 171 171 struct fw_ohci { 172 172 struct fw_card card; 173 173 174 - u32 version; 175 174 __iomem char *registers; 176 175 dma_addr_t self_id_bus; 177 176 __le32 *self_id_cpu; ··· 179 180 int generation; 180 181 int request_generation; /* for timestamping incoming requests */ 181 182 u32 bus_seconds; 183 + 184 + bool use_dualbuffer; 182 185 bool old_uninorth; 183 186 bool bus_reset_packet_quirk; 184 187 ··· 1886 1885 } else { 1887 1886 mask = &ohci->ir_context_mask; 1888 1887 list = ohci->ir_context_list; 1889 - if (ohci->version >= OHCI_VERSION_1_1) 1888 + if (ohci->use_dualbuffer) 1890 1889 callback = handle_ir_dualbuffer_packet; 1891 1890 else 1892 1891 callback = handle_ir_packet_per_buffer; ··· 1950 1949 } else { 1951 1950 index = ctx - ohci->ir_context_list; 1952 1951 control = IR_CONTEXT_ISOCH_HEADER; 1953 - if (ohci->version >= OHCI_VERSION_1_1) 1952 + if (ohci->use_dualbuffer) 1954 1953 control |= IR_CONTEXT_DUAL_BUFFER_MODE; 1955 1954 match = (tags << 28) | (sync << 8) | ctx->base.channel; 1956 1955 if (cycle >= 0) { ··· 2280 2279 spin_lock_irqsave(&ctx->context.ohci->lock, flags); 2281 2280 if (base->type == FW_ISO_CONTEXT_TRANSMIT) 2282 2281 retval = ohci_queue_iso_transmit(base, packet, buffer, payload); 2283 - else if (ctx->context.ohci->version >= OHCI_VERSION_1_1) 2282 + else if (ctx->context.ohci->use_dualbuffer) 2284 2283 retval = ohci_queue_iso_receive_dualbuffer(base, packet, 2285 2284 buffer, payload); 2286 2285 else ··· 2342 2341 pci_probe(struct pci_dev *dev, const struct pci_device_id *ent) 2343 2342 { 2344 2343 struct fw_ohci *ohci; 2345 - u32 bus_options, max_receive, link_speed; 2344 + u32 bus_options, max_receive, link_speed, version; 2346 2345 u64 guid; 2347 2346 int err; 2348 2347 size_t size; ··· 2367 2366 pci_write_config_dword(dev, OHCI1394_PCI_HCI_Control, 0); 2368 2367 pci_set_drvdata(dev, ohci); 2369 2368 2370 - #if defined(CONFIG_PPC_PMAC) && defined(CONFIG_PPC32) 2371 - ohci->old_uninorth = dev->vendor == PCI_VENDOR_ID_APPLE && 2372 - dev->device == PCI_DEVICE_ID_APPLE_UNI_N_FW; 2373 - #endif 2374 - ohci->bus_reset_packet_quirk = dev->vendor == PCI_VENDOR_ID_TI; 2375 - 2376 2369 spin_lock_init(&ohci->lock); 2377 2370 2378 2371 tasklet_init(&ohci->bus_reset_tasklet, ··· 2384 2389 err = -ENXIO; 2385 2390 goto fail_iomem; 2386 2391 } 2392 + 2393 + version = reg_read(ohci, OHCI1394_Version) & 0x00ff00ff; 2394 + ohci->use_dualbuffer = version >= OHCI_VERSION_1_1; 2395 + 2396 + /* x86-32 currently doesn't use highmem for dma_alloc_coherent */ 2397 + #if !defined(CONFIG_X86_32) 2398 + /* dual-buffer mode is broken with descriptor addresses above 2G */ 2399 + if (dev->vendor == PCI_VENDOR_ID_TI && 2400 + dev->device == PCI_DEVICE_ID_TI_TSB43AB22) 2401 + ohci->use_dualbuffer = false; 2402 + #endif 2403 + 2404 + #if defined(CONFIG_PPC_PMAC) && defined(CONFIG_PPC32) 2405 + ohci->old_uninorth = dev->vendor == PCI_VENDOR_ID_APPLE && 2406 + dev->device == PCI_DEVICE_ID_APPLE_UNI_N_FW; 2407 + #endif 2408 + ohci->bus_reset_packet_quirk = dev->vendor == PCI_VENDOR_ID_TI; 2387 2409 2388 2410 ar_context_init(&ohci->ar_request_ctx, ohci, 2389 2411 OHCI1394_AsReqRcvContextControlSet); ··· 2453 2441 if (err < 0) 2454 2442 goto fail_self_id; 2455 2443 2456 - ohci->version = reg_read(ohci, OHCI1394_Version) & 0x00ff00ff; 2457 2444 fw_notify("Added fw-ohci device %s, OHCI version %x.%x\n", 2458 - dev->dev.bus_id, ohci->version >> 16, ohci->version & 0xff); 2445 + dev->dev.bus_id, version >> 16, version & 0xff); 2459 2446 return 0; 2460 2447 2461 2448 fail_self_id:
+1
include/linux/pci_ids.h
··· 748 748 #define PCI_VENDOR_ID_TI 0x104c 749 749 #define PCI_DEVICE_ID_TI_TVP4020 0x3d07 750 750 #define PCI_DEVICE_ID_TI_4450 0x8011 751 + #define PCI_DEVICE_ID_TI_TSB43AB22 0x8023 751 752 #define PCI_DEVICE_ID_TI_XX21_XX11 0x8031 752 753 #define PCI_DEVICE_ID_TI_XX21_XX11_FM 0x8033 753 754 #define PCI_DEVICE_ID_TI_XX21_XX11_SD 0x8034