aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorStefan Richter <stefanr@s5r6.in-berlin.de>2008-07-22 12:41:10 -0400
committerStefan Richter <stefanr@s5r6.in-berlin.de>2008-07-25 09:41:23 -0400
commit95984f62c9b0bf6d89ef4f514b1afe73623481de (patch)
tree2c46b6e7ec4a56de8e65b194c828985af5fe4414
parentf9543d0ab6392a9a5bff0034622688dc10d9d225 (diff)
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>
-rw-r--r--drivers/firewire/fw-ohci.c37
-rw-r--r--include/linux/pci_ids.h1
2 files changed, 25 insertions, 13 deletions
diff --git a/drivers/firewire/fw-ohci.c b/drivers/firewire/fw-ohci.c
index 333b12544dd1..a4eff32621b5 100644
--- a/drivers/firewire/fw-ohci.c
+++ b/drivers/firewire/fw-ohci.c
@@ -171,7 +171,6 @@ struct iso_context {
171struct fw_ohci { 171struct fw_ohci {
172 struct fw_card card; 172 struct fw_card card;
173 173
174 u32 version;
175 __iomem char *registers; 174 __iomem char *registers;
176 dma_addr_t self_id_bus; 175 dma_addr_t self_id_bus;
177 __le32 *self_id_cpu; 176 __le32 *self_id_cpu;
@@ -180,6 +179,8 @@ struct fw_ohci {
180 int generation; 179 int generation;
181 int request_generation; /* for timestamping incoming requests */ 180 int request_generation; /* for timestamping incoming requests */
182 u32 bus_seconds; 181 u32 bus_seconds;
182
183 bool use_dualbuffer;
183 bool old_uninorth; 184 bool old_uninorth;
184 bool bus_reset_packet_quirk; 185 bool bus_reset_packet_quirk;
185 186
@@ -1885,7 +1886,7 @@ ohci_allocate_iso_context(struct fw_card *card, int type, size_t header_size)
1885 } else { 1886 } else {
1886 mask = &ohci->ir_context_mask; 1887 mask = &ohci->ir_context_mask;
1887 list = ohci->ir_context_list; 1888 list = ohci->ir_context_list;
1888 if (ohci->version >= OHCI_VERSION_1_1) 1889 if (ohci->use_dualbuffer)
1889 callback = handle_ir_dualbuffer_packet; 1890 callback = handle_ir_dualbuffer_packet;
1890 else 1891 else
1891 callback = handle_ir_packet_per_buffer; 1892 callback = handle_ir_packet_per_buffer;
@@ -1949,7 +1950,7 @@ static int ohci_start_iso(struct fw_iso_context *base,
1949 } else { 1950 } else {
1950 index = ctx - ohci->ir_context_list; 1951 index = ctx - ohci->ir_context_list;
1951 control = IR_CONTEXT_ISOCH_HEADER; 1952 control = IR_CONTEXT_ISOCH_HEADER;
1952 if (ohci->version >= OHCI_VERSION_1_1) 1953 if (ohci->use_dualbuffer)
1953 control |= IR_CONTEXT_DUAL_BUFFER_MODE; 1954 control |= IR_CONTEXT_DUAL_BUFFER_MODE;
1954 match = (tags << 28) | (sync << 8) | ctx->base.channel; 1955 match = (tags << 28) | (sync << 8) | ctx->base.channel;
1955 if (cycle >= 0) { 1956 if (cycle >= 0) {
@@ -2279,7 +2280,7 @@ ohci_queue_iso(struct fw_iso_context *base,
2279 spin_lock_irqsave(&ctx->context.ohci->lock, flags); 2280 spin_lock_irqsave(&ctx->context.ohci->lock, flags);
2280 if (base->type == FW_ISO_CONTEXT_TRANSMIT) 2281 if (base->type == FW_ISO_CONTEXT_TRANSMIT)
2281 retval = ohci_queue_iso_transmit(base, packet, buffer, payload); 2282 retval = ohci_queue_iso_transmit(base, packet, buffer, payload);
2282 else if (ctx->context.ohci->version >= OHCI_VERSION_1_1) 2283 else if (ctx->context.ohci->use_dualbuffer)
2283 retval = ohci_queue_iso_receive_dualbuffer(base, packet, 2284 retval = ohci_queue_iso_receive_dualbuffer(base, packet,
2284 buffer, payload); 2285 buffer, payload);
2285 else 2286 else
@@ -2341,7 +2342,7 @@ static int __devinit
2341pci_probe(struct pci_dev *dev, const struct pci_device_id *ent) 2342pci_probe(struct pci_dev *dev, const struct pci_device_id *ent)
2342{ 2343{
2343 struct fw_ohci *ohci; 2344 struct fw_ohci *ohci;
2344 u32 bus_options, max_receive, link_speed; 2345 u32 bus_options, max_receive, link_speed, version;
2345 u64 guid; 2346 u64 guid;
2346 int err; 2347 int err;
2347 size_t size; 2348 size_t size;
@@ -2366,12 +2367,6 @@ pci_probe(struct pci_dev *dev, const struct pci_device_id *ent)
2366 pci_write_config_dword(dev, OHCI1394_PCI_HCI_Control, 0); 2367 pci_write_config_dword(dev, OHCI1394_PCI_HCI_Control, 0);
2367 pci_set_drvdata(dev, ohci); 2368 pci_set_drvdata(dev, ohci);
2368 2369
2369#if defined(CONFIG_PPC_PMAC) && defined(CONFIG_PPC32)
2370 ohci->old_uninorth = dev->vendor == PCI_VENDOR_ID_APPLE &&
2371 dev->device == PCI_DEVICE_ID_APPLE_UNI_N_FW;
2372#endif
2373 ohci->bus_reset_packet_quirk = dev->vendor == PCI_VENDOR_ID_TI;
2374
2375 spin_lock_init(&ohci->lock); 2370 spin_lock_init(&ohci->lock);
2376 2371
2377 tasklet_init(&ohci->bus_reset_tasklet, 2372 tasklet_init(&ohci->bus_reset_tasklet,
@@ -2390,6 +2385,23 @@ pci_probe(struct pci_dev *dev, const struct pci_device_id *ent)
2390 goto fail_iomem; 2385 goto fail_iomem;
2391 } 2386 }
2392 2387
2388 version = reg_read(ohci, OHCI1394_Version) & 0x00ff00ff;
2389 ohci->use_dualbuffer = version >= OHCI_VERSION_1_1;
2390
2391/* x86-32 currently doesn't use highmem for dma_alloc_coherent */
2392#if !defined(CONFIG_X86_32)
2393 /* dual-buffer mode is broken with descriptor addresses above 2G */
2394 if (dev->vendor == PCI_VENDOR_ID_TI &&
2395 dev->device == PCI_DEVICE_ID_TI_TSB43AB22)
2396 ohci->use_dualbuffer = false;
2397#endif
2398
2399#if defined(CONFIG_PPC_PMAC) && defined(CONFIG_PPC32)
2400 ohci->old_uninorth = dev->vendor == PCI_VENDOR_ID_APPLE &&
2401 dev->device == PCI_DEVICE_ID_APPLE_UNI_N_FW;
2402#endif
2403 ohci->bus_reset_packet_quirk = dev->vendor == PCI_VENDOR_ID_TI;
2404
2393 ar_context_init(&ohci->ar_request_ctx, ohci, 2405 ar_context_init(&ohci->ar_request_ctx, ohci,
2394 OHCI1394_AsReqRcvContextControlSet); 2406 OHCI1394_AsReqRcvContextControlSet);
2395 2407
@@ -2441,9 +2453,8 @@ pci_probe(struct pci_dev *dev, const struct pci_device_id *ent)
2441 if (err < 0) 2453 if (err < 0)
2442 goto fail_self_id; 2454 goto fail_self_id;
2443 2455
2444 ohci->version = reg_read(ohci, OHCI1394_Version) & 0x00ff00ff;
2445 fw_notify("Added fw-ohci device %s, OHCI version %x.%x\n", 2456 fw_notify("Added fw-ohci device %s, OHCI version %x.%x\n",
2446 dev->dev.bus_id, ohci->version >> 16, ohci->version & 0xff); 2457 dev->dev.bus_id, version >> 16, version & 0xff);
2447 return 0; 2458 return 0;
2448 2459
2449 fail_self_id: 2460 fail_self_id:
diff --git a/include/linux/pci_ids.h b/include/linux/pci_ids.h
index 65953822c9cb..720d67554106 100644
--- a/include/linux/pci_ids.h
+++ b/include/linux/pci_ids.h
@@ -748,6 +748,7 @@
748#define PCI_VENDOR_ID_TI 0x104c 748#define PCI_VENDOR_ID_TI 0x104c
749#define PCI_DEVICE_ID_TI_TVP4020 0x3d07 749#define PCI_DEVICE_ID_TI_TVP4020 0x3d07
750#define PCI_DEVICE_ID_TI_4450 0x8011 750#define PCI_DEVICE_ID_TI_4450 0x8011
751#define PCI_DEVICE_ID_TI_TSB43AB22 0x8023
751#define PCI_DEVICE_ID_TI_XX21_XX11 0x8031 752#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_FM 0x8033
753#define PCI_DEVICE_ID_TI_XX21_XX11_SD 0x8034 754#define PCI_DEVICE_ID_TI_XX21_XX11_SD 0x8034