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 struct fw_ohci { 172 struct fw_card card; 173 174 - u32 version; 175 __iomem char *registers; 176 dma_addr_t self_id_bus; 177 __le32 *self_id_cpu; ··· 179 int generation; 180 int request_generation; /* for timestamping incoming requests */ 181 u32 bus_seconds; 182 bool old_uninorth; 183 bool bus_reset_packet_quirk; 184 ··· 1886 } else { 1887 mask = &ohci->ir_context_mask; 1888 list = ohci->ir_context_list; 1889 - if (ohci->version >= OHCI_VERSION_1_1) 1890 callback = handle_ir_dualbuffer_packet; 1891 else 1892 callback = handle_ir_packet_per_buffer; ··· 1950 } else { 1951 index = ctx - ohci->ir_context_list; 1952 control = IR_CONTEXT_ISOCH_HEADER; 1953 - if (ohci->version >= OHCI_VERSION_1_1) 1954 control |= IR_CONTEXT_DUAL_BUFFER_MODE; 1955 match = (tags << 28) | (sync << 8) | ctx->base.channel; 1956 if (cycle >= 0) { ··· 2280 spin_lock_irqsave(&ctx->context.ohci->lock, flags); 2281 if (base->type == FW_ISO_CONTEXT_TRANSMIT) 2282 retval = ohci_queue_iso_transmit(base, packet, buffer, payload); 2283 - else if (ctx->context.ohci->version >= OHCI_VERSION_1_1) 2284 retval = ohci_queue_iso_receive_dualbuffer(base, packet, 2285 buffer, payload); 2286 else ··· 2342 pci_probe(struct pci_dev *dev, const struct pci_device_id *ent) 2343 { 2344 struct fw_ohci *ohci; 2345 - u32 bus_options, max_receive, link_speed; 2346 u64 guid; 2347 int err; 2348 size_t size; ··· 2367 pci_write_config_dword(dev, OHCI1394_PCI_HCI_Control, 0); 2368 pci_set_drvdata(dev, ohci); 2369 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 spin_lock_init(&ohci->lock); 2377 2378 tasklet_init(&ohci->bus_reset_tasklet, ··· 2384 err = -ENXIO; 2385 goto fail_iomem; 2386 } 2387 2388 ar_context_init(&ohci->ar_request_ctx, ohci, 2389 OHCI1394_AsReqRcvContextControlSet); ··· 2453 if (err < 0) 2454 goto fail_self_id; 2455 2456 - ohci->version = reg_read(ohci, OHCI1394_Version) & 0x00ff00ff; 2457 fw_notify("Added fw-ohci device %s, OHCI version %x.%x\n", 2458 - dev->dev.bus_id, ohci->version >> 16, ohci->version & 0xff); 2459 return 0; 2460 2461 fail_self_id:
··· 171 struct fw_ohci { 172 struct fw_card card; 173 174 __iomem char *registers; 175 dma_addr_t self_id_bus; 176 __le32 *self_id_cpu; ··· 180 int generation; 181 int request_generation; /* for timestamping incoming requests */ 182 u32 bus_seconds; 183 + 184 + bool use_dualbuffer; 185 bool old_uninorth; 186 bool bus_reset_packet_quirk; 187 ··· 1885 } else { 1886 mask = &ohci->ir_context_mask; 1887 list = ohci->ir_context_list; 1888 + if (ohci->use_dualbuffer) 1889 callback = handle_ir_dualbuffer_packet; 1890 else 1891 callback = handle_ir_packet_per_buffer; ··· 1949 } else { 1950 index = ctx - ohci->ir_context_list; 1951 control = IR_CONTEXT_ISOCH_HEADER; 1952 + if (ohci->use_dualbuffer) 1953 control |= IR_CONTEXT_DUAL_BUFFER_MODE; 1954 match = (tags << 28) | (sync << 8) | ctx->base.channel; 1955 if (cycle >= 0) { ··· 2279 spin_lock_irqsave(&ctx->context.ohci->lock, flags); 2280 if (base->type == FW_ISO_CONTEXT_TRANSMIT) 2281 retval = ohci_queue_iso_transmit(base, packet, buffer, payload); 2282 + else if (ctx->context.ohci->use_dualbuffer) 2283 retval = ohci_queue_iso_receive_dualbuffer(base, packet, 2284 buffer, payload); 2285 else ··· 2341 pci_probe(struct pci_dev *dev, const struct pci_device_id *ent) 2342 { 2343 struct fw_ohci *ohci; 2344 + u32 bus_options, max_receive, link_speed, version; 2345 u64 guid; 2346 int err; 2347 size_t size; ··· 2366 pci_write_config_dword(dev, OHCI1394_PCI_HCI_Control, 0); 2367 pci_set_drvdata(dev, ohci); 2368 2369 spin_lock_init(&ohci->lock); 2370 2371 tasklet_init(&ohci->bus_reset_tasklet, ··· 2389 err = -ENXIO; 2390 goto fail_iomem; 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; 2409 2410 ar_context_init(&ohci->ar_request_ctx, ohci, 2411 OHCI1394_AsReqRcvContextControlSet); ··· 2441 if (err < 0) 2442 goto fail_self_id; 2443 2444 fw_notify("Added fw-ohci device %s, OHCI version %x.%x\n", 2445 + dev->dev.bus_id, version >> 16, version & 0xff); 2446 return 0; 2447 2448 fail_self_id:
+1
include/linux/pci_ids.h
··· 748 #define PCI_VENDOR_ID_TI 0x104c 749 #define PCI_DEVICE_ID_TI_TVP4020 0x3d07 750 #define PCI_DEVICE_ID_TI_4450 0x8011 751 #define PCI_DEVICE_ID_TI_XX21_XX11 0x8031 752 #define PCI_DEVICE_ID_TI_XX21_XX11_FM 0x8033 753 #define PCI_DEVICE_ID_TI_XX21_XX11_SD 0x8034
··· 748 #define PCI_VENDOR_ID_TI 0x104c 749 #define PCI_DEVICE_ID_TI_TVP4020 0x3d07 750 #define PCI_DEVICE_ID_TI_4450 0x8011 751 + #define PCI_DEVICE_ID_TI_TSB43AB22 0x8023 752 #define PCI_DEVICE_ID_TI_XX21_XX11 0x8031 753 #define PCI_DEVICE_ID_TI_XX21_XX11_FM 0x8033 754 #define PCI_DEVICE_ID_TI_XX21_XX11_SD 0x8034