diff options
Diffstat (limited to 'drivers/firewire/ohci.c')
-rw-r--r-- | drivers/firewire/ohci.c | 306 |
1 files changed, 277 insertions, 29 deletions
diff --git a/drivers/firewire/ohci.c b/drivers/firewire/ohci.c index 271fc51..0a0225a 100644 --- a/drivers/firewire/ohci.c +++ b/drivers/firewire/ohci.c @@ -42,6 +42,7 @@ #include <linux/string.h> #include <linux/time.h> #include <linux/vmalloc.h> +#include <linux/workqueue.h> #include <asm/byteorder.h> #include <asm/page.h> @@ -125,6 +126,7 @@ struct context { struct fw_ohci *ohci; u32 regs; int total_allocation; + u32 current_bus; bool running; bool flushing; @@ -226,7 +228,7 @@ struct fw_ohci { __le32 *self_id_cpu; dma_addr_t self_id_bus; - struct tasklet_struct bus_reset_tasklet; + struct work_struct bus_reset_work; u32 self_id_buffer[512]; }; @@ -253,7 +255,6 @@ static inline struct fw_ohci *fw_ohci(struct fw_card *card) #define OHCI1394_MAX_PHYS_RESP_RETRIES 0x8 #define OHCI1394_REGISTER_SIZE 0x800 -#define OHCI_LOOP_COUNT 500 #define OHCI1394_PCI_HCI_Control 0x40 #define SELF_ID_BUF_SIZE 0x800 #define OHCI_TCODE_PHY_PACKET 0x0e @@ -265,6 +266,8 @@ static char ohci_driver_name[] = KBUILD_MODNAME; #define PCI_DEVICE_ID_CREATIVE_SB1394 0x4001 #define PCI_DEVICE_ID_JMICRON_JMB38X_FW 0x2380 #define PCI_DEVICE_ID_TI_TSB12LV22 0x8009 +#define PCI_DEVICE_ID_TI_TSB12LV26 0x8020 +#define PCI_DEVICE_ID_TI_TSB82AA2 0x8025 #define PCI_VENDOR_ID_PINNACLE_SYSTEMS 0x11bd #define QUIRK_CYCLE_TIMER 1 @@ -272,6 +275,7 @@ static char ohci_driver_name[] = KBUILD_MODNAME; #define QUIRK_BE_HEADERS 4 #define QUIRK_NO_1394A 8 #define QUIRK_NO_MSI 16 +#define QUIRK_TI_SLLZ059 32 /* In case of multiple matches in ohci_quirks[], only the first one is used. */ static const struct { @@ -304,6 +308,12 @@ static const struct { {PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_TSB12LV22, PCI_ANY_ID, QUIRK_CYCLE_TIMER | QUIRK_RESET_PACKET | QUIRK_NO_1394A}, + {PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_TSB12LV26, PCI_ANY_ID, + QUIRK_RESET_PACKET | QUIRK_TI_SLLZ059}, + + {PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_TSB82AA2, PCI_ANY_ID, + QUIRK_RESET_PACKET | QUIRK_TI_SLLZ059}, + {PCI_VENDOR_ID_TI, PCI_ANY_ID, PCI_ANY_ID, QUIRK_RESET_PACKET}, @@ -320,6 +330,7 @@ MODULE_PARM_DESC(quirks, "Chip quirks (default = 0" ", AR/selfID endianess = " __stringify(QUIRK_BE_HEADERS) ", no 1394a enhancements = " __stringify(QUIRK_NO_1394A) ", disable MSI = " __stringify(QUIRK_NO_MSI) + ", TI SLLZ059 erratum = " __stringify(QUIRK_TI_SLLZ059) ")"); #define OHCI_PARAM_DEBUG_AT_AR 1 @@ -521,6 +532,12 @@ static inline void flush_writes(const struct fw_ohci *ohci) reg_read(ohci, OHCI1394_Version); } +/* + * Beware! read_phy_reg(), write_phy_reg(), update_phy_reg(), and + * read_paged_phy_reg() require the caller to hold ohci->phy_reg_mutex. + * In other words, only use ohci_read_phy_reg() and ohci_update_phy_reg() + * directly. Exceptions are intrinsically serialized contexts like pci_probe. + */ static int read_phy_reg(struct fw_ohci *ohci, int addr) { u32 val; @@ -529,6 +546,9 @@ static int read_phy_reg(struct fw_ohci *ohci, int addr) reg_write(ohci, OHCI1394_PhyControl, OHCI1394_PhyControl_Read(addr)); for (i = 0; i < 3 + 100; i++) { val = reg_read(ohci, OHCI1394_PhyControl); + if (!~val) + return -ENODEV; /* Card was ejected. */ + if (val & OHCI1394_PhyControl_ReadDone) return OHCI1394_PhyControl_ReadData(val); @@ -552,6 +572,9 @@ static int write_phy_reg(const struct fw_ohci *ohci, int addr, u32 val) OHCI1394_PhyControl_Write(addr, val)); for (i = 0; i < 3 + 100; i++) { val = reg_read(ohci, OHCI1394_PhyControl); + if (!~val) + return -ENODEV; /* Card was ejected. */ + if (!(val & OHCI1394_PhyControl_WritePending)) return 0; @@ -637,7 +660,6 @@ static void ar_context_link_page(struct ar_context *ctx, unsigned int index) ctx->last_buffer_index = index; reg_write(ctx->ohci, CONTROL_SET(ctx->regs), CONTEXT_WAKE); - flush_writes(ctx->ohci); } static void ar_context_release(struct ar_context *ctx) @@ -853,7 +875,7 @@ static __le32 *handle_ar_packet(struct ar_context *ctx, __le32 *buffer) * * Alas some chips sometimes emit bus reset packets with a * wrong generation. We set the correct generation for these - * at a slightly incorrect time (in bus_reset_tasklet). + * at a slightly incorrect time (in bus_reset_work). */ if (evt == OHCI1394_evt_bus_reset) { if (!(ohci->quirks & QUIRK_RESET_PACKET)) @@ -1009,7 +1031,6 @@ static void ar_context_run(struct ar_context *ctx) reg_write(ctx->ohci, COMMAND_PTR(ctx->regs), ctx->descriptors_bus | 1); reg_write(ctx->ohci, CONTROL_SET(ctx->regs), CONTEXT_RUN); - flush_writes(ctx->ohci); } static struct descriptor *find_branch_descriptor(struct descriptor *d, int z) @@ -1041,6 +1062,7 @@ static void context_tasklet(unsigned long data) address = le32_to_cpu(last->branch_address); z = address & 0xf; address &= ~0xf; + ctx->current_bus = address; /* If the branch address points to a buffer outside of the * current buffer, advance to the next buffer. */ @@ -1209,14 +1231,14 @@ static void context_stop(struct context *ctx) reg_write(ctx->ohci, CONTROL_CLEAR(ctx->regs), CONTEXT_RUN); ctx->running = false; - flush_writes(ctx->ohci); - for (i = 0; i < 10; i++) { + for (i = 0; i < 1000; i++) { reg = reg_read(ctx->ohci, CONTROL_SET(ctx->regs)); if ((reg & CONTEXT_ACTIVE) == 0) return; - mdelay(1); + if (i) + udelay(10); } fw_error("Error: DMA context still active (0x%08x)\n", reg); } @@ -1353,12 +1375,10 @@ static int at_context_queue_packet(struct context *ctx, context_append(ctx, d, z, 4 - z); - if (ctx->running) { + if (ctx->running) reg_write(ohci, CONTROL_SET(ctx->regs), CONTEXT_WAKE); - flush_writes(ohci); - } else { + else context_run(ctx, 0); - } return 0; } @@ -1710,9 +1730,94 @@ static u32 update_bus_time(struct fw_ohci *ohci) return ohci->bus_time | cycle_time_seconds; } -static void bus_reset_tasklet(unsigned long data) +static int get_status_for_port(struct fw_ohci *ohci, int port_index) +{ + int reg; + + mutex_lock(&ohci->phy_reg_mutex); + reg = write_phy_reg(ohci, 7, port_index); + if (reg >= 0) + reg = read_phy_reg(ohci, 8); + mutex_unlock(&ohci->phy_reg_mutex); + if (reg < 0) + return reg; + + switch (reg & 0x0f) { + case 0x06: + return 2; /* is child node (connected to parent node) */ + case 0x0e: + return 3; /* is parent node (connected to child node) */ + } + return 1; /* not connected */ +} + +static int get_self_id_pos(struct fw_ohci *ohci, u32 self_id, + int self_id_count) +{ + int i; + u32 entry; + + for (i = 0; i < self_id_count; i++) { + entry = ohci->self_id_buffer[i]; + if ((self_id & 0xff000000) == (entry & 0xff000000)) + return -1; + if ((self_id & 0xff000000) < (entry & 0xff000000)) + return i; + } + return i; +} + +/* + * TI TSB82AA2B and TSB12LV26 do not receive the selfID of a locally + * attached TSB41BA3D phy; see http://www.ti.com/litv/pdf/sllz059. + * Construct the selfID from phy register contents. + * FIXME: How to determine the selfID.i flag? + */ +static int find_and_insert_self_id(struct fw_ohci *ohci, int self_id_count) { - struct fw_ohci *ohci = (struct fw_ohci *)data; + int reg, i, pos, status; + /* link active 1, speed 3, bridge 0, contender 1, more packets 0 */ + u32 self_id = 0x8040c800; + + reg = reg_read(ohci, OHCI1394_NodeID); + if (!(reg & OHCI1394_NodeID_idValid)) { + fw_notify("node ID not valid, new bus reset in progress\n"); + return -EBUSY; + } + self_id |= ((reg & 0x3f) << 24); /* phy ID */ + + reg = ohci_read_phy_reg(&ohci->card, 4); + if (reg < 0) + return reg; + self_id |= ((reg & 0x07) << 8); /* power class */ + + reg = ohci_read_phy_reg(&ohci->card, 1); + if (reg < 0) + return reg; + self_id |= ((reg & 0x3f) << 16); /* gap count */ + + for (i = 0; i < 3; i++) { + status = get_status_for_port(ohci, i); + if (status < 0) + return status; + self_id |= ((status & 0x3) << (6 - (i * 2))); + } + + pos = get_self_id_pos(ohci, self_id, self_id_count); + if (pos >= 0) { + memmove(&(ohci->self_id_buffer[pos+1]), + &(ohci->self_id_buffer[pos]), + (self_id_count - pos) * sizeof(*ohci->self_id_buffer)); + ohci->self_id_buffer[pos] = self_id; + self_id_count++; + } + return self_id_count; +} + +static void bus_reset_work(struct work_struct *work) +{ + struct fw_ohci *ohci = + container_of(work, struct fw_ohci, bus_reset_work); int self_id_count, i, j, reg; int generation, new_generation; unsigned long flags; @@ -1750,21 +1855,50 @@ static void bus_reset_tasklet(unsigned long data) * bit extra to get the actual number of self IDs. */ self_id_count = (reg >> 3) & 0xff; - if (self_id_count == 0 || self_id_count > 252) { + + if (self_id_count > 252) { fw_notify("inconsistent self IDs\n"); return; } + generation = (cond_le32_to_cpu(ohci->self_id_cpu[0]) >> 16) & 0xff; rmb(); for (i = 1, j = 0; j < self_id_count; i += 2, j++) { if (ohci->self_id_cpu[i] != ~ohci->self_id_cpu[i + 1]) { - fw_notify("inconsistent self IDs\n"); - return; + /* + * If the invalid data looks like a cycle start packet, + * it's likely to be the result of the cycle master + * having a wrong gap count. In this case, the self IDs + * so far are valid and should be processed so that the + * bus manager can then correct the gap count. + */ + if (cond_le32_to_cpu(ohci->self_id_cpu[i]) + == 0xffff008f) { + fw_notify("ignoring spurious self IDs\n"); + self_id_count = j; + break; + } else { + fw_notify("inconsistent self IDs\n"); + return; + } } ohci->self_id_buffer[j] = cond_le32_to_cpu(ohci->self_id_cpu[i]); } + + if (ohci->quirks & QUIRK_TI_SLLZ059) { + self_id_count = find_and_insert_self_id(ohci, self_id_count); + if (self_id_count < 0) { + fw_notify("could not construct local self ID\n"); + return; + } + } + + if (self_id_count == 0) { + fw_notify("inconsistent self IDs\n"); + return; + } rmb(); /* @@ -1884,7 +2018,7 @@ static irqreturn_t irq_handler(int irq, void *data) log_irqs(event); if (event & OHCI1394_selfIDComplete) - tasklet_schedule(&ohci->bus_reset_tasklet); + queue_work(fw_workqueue, &ohci->bus_reset_work); if (event & OHCI1394_RQPkt) tasklet_schedule(&ohci->ar_request_ctx.tasklet); @@ -1931,7 +2065,8 @@ static irqreturn_t irq_handler(int irq, void *data) reg_read(ohci, OHCI1394_PostedWriteAddressLo); reg_write(ohci, OHCI1394_IntEventClear, OHCI1394_postedWriteErr); - fw_error("PCI posted write error\n"); + if (printk_ratelimit()) + fw_error("PCI posted write error\n"); } if (unlikely(event & OHCI1394_cycleTooLong)) { @@ -1967,14 +2102,18 @@ static irqreturn_t irq_handler(int irq, void *data) static int software_reset(struct fw_ohci *ohci) { + u32 val; int i; reg_write(ohci, OHCI1394_HCControlSet, OHCI1394_HCControl_softReset); + for (i = 0; i < 500; i++) { + val = reg_read(ohci, OHCI1394_HCControlSet); + if (!~val) + return -ENODEV; /* Card was ejected. */ - for (i = 0; i < OHCI_LOOP_COUNT; i++) { - if ((reg_read(ohci, OHCI1394_HCControlSet) & - OHCI1394_HCControl_softReset) == 0) + if (!(val & OHCI1394_HCControl_softReset)) return 0; + msleep(1); } @@ -2041,6 +2180,28 @@ static int configure_1394a_enhancements(struct fw_ohci *ohci) return 0; } +static int probe_tsb41ba3d(struct fw_ohci *ohci) +{ + /* TI vendor ID = 0x080028, TSB41BA3D product ID = 0x833005 (sic) */ + static const u8 id[] = { 0x08, 0x00, 0x28, 0x83, 0x30, 0x05, }; + int reg, i; + + reg = read_phy_reg(ohci, 2); + if (reg < 0) + return reg; + if ((reg & PHY_EXTENDED_REGISTERS) != PHY_EXTENDED_REGISTERS) + return 0; + + for (i = ARRAY_SIZE(id) - 1; i >= 0; i--) { + reg = read_paged_phy_reg(ohci, 1, i + 10); + if (reg < 0) + return reg; + if (reg != id[i]) + return 0; + } + return 1; +} + static int ohci_enable(struct fw_card *card, const __be32 *config_rom, size_t length) { @@ -2078,6 +2239,16 @@ static int ohci_enable(struct fw_card *card, return -EIO; } + if (ohci->quirks & QUIRK_TI_SLLZ059) { + ret = probe_tsb41ba3d(ohci); + if (ret < 0) + return ret; + if (ret) + fw_notify("local TSB41BA3D phy\n"); + else + ohci->quirks &= ~QUIRK_TI_SLLZ059; + } + reg_write(ohci, OHCI1394_HCControlClear, OHCI1394_HCControl_noByteSwapData); @@ -2175,8 +2346,13 @@ static int ohci_enable(struct fw_card *card, ohci_driver_name, ohci)) { fw_error("Failed to allocate interrupt %d.\n", dev->irq); pci_disable_msi(dev); - dma_free_coherent(ohci->card.device, CONFIG_ROM_SIZE, - ohci->config_rom, ohci->config_rom_bus); + + if (config_rom) { + dma_free_coherent(ohci->card.device, CONFIG_ROM_SIZE, + ohci->next_config_rom, + ohci->next_config_rom_bus); + ohci->next_config_rom = NULL; + } return -EIO; } @@ -2204,7 +2380,9 @@ static int ohci_enable(struct fw_card *card, OHCI1394_LinkControl_rcvPhyPkt); ar_context_run(&ohci->ar_request_ctx); - ar_context_run(&ohci->ar_response_ctx); /* also flushes writes */ + ar_context_run(&ohci->ar_response_ctx); + + flush_writes(ohci); /* We are ready to go, reset bus to finish initialization. */ fw_schedule_bus_reset(&ohci->card, false, true); @@ -2246,7 +2424,7 @@ static int ohci_set_config_rom(struct fw_card *card, * then set up the real values for the two registers. * * We use ohci->lock to avoid racing with the code that sets - * ohci->next_config_rom to NULL (see bus_reset_tasklet). + * ohci->next_config_rom to NULL (see bus_reset_work). */ next_config_rom = @@ -2525,6 +2703,7 @@ static int handle_ir_packet_per_buffer(struct context *context, struct iso_context *ctx = container_of(context, struct iso_context, context); struct descriptor *pd; + u32 buffer_dma; __le32 *ir_header; void *p; @@ -2535,6 +2714,16 @@ static int handle_ir_packet_per_buffer(struct context *context, /* Descriptor(s) not done yet, stop iteration */ return 0; + while (!(d->control & cpu_to_le16(DESCRIPTOR_BRANCH_ALWAYS))) { + d++; + buffer_dma = le32_to_cpu(d->data_address); + dma_sync_single_range_for_cpu(context->ohci->card.device, + buffer_dma & PAGE_MASK, + buffer_dma & ~PAGE_MASK, + le16_to_cpu(d->req_count), + DMA_FROM_DEVICE); + } + p = last + 1; copy_iso_headers(ctx, p); @@ -2557,11 +2746,19 @@ static int handle_ir_buffer_fill(struct context *context, { struct iso_context *ctx = container_of(context, struct iso_context, context); + u32 buffer_dma; if (last->res_count != 0) /* Descriptor(s) not done yet, stop iteration */ return 0; + buffer_dma = le32_to_cpu(last->data_address); + dma_sync_single_range_for_cpu(context->ohci->card.device, + buffer_dma & PAGE_MASK, + buffer_dma & ~PAGE_MASK, + le16_to_cpu(last->req_count), + DMA_FROM_DEVICE); + if (le16_to_cpu(last->control) & DESCRIPTOR_IRQ_ALWAYS) ctx->base.callback.mc(&ctx->base, le32_to_cpu(last->data_address) + @@ -2571,6 +2768,43 @@ static int handle_ir_buffer_fill(struct context *context, return 1; } +static inline void sync_it_packet_for_cpu(struct context *context, + struct descriptor *pd) +{ + __le16 control; + u32 buffer_dma; + + /* only packets beginning with OUTPUT_MORE* have data buffers */ + if (pd->control & cpu_to_le16(DESCRIPTOR_BRANCH_ALWAYS)) + return; + + /* skip over the OUTPUT_MORE_IMMEDIATE descriptor */ + pd += 2; + + /* + * If the packet has a header, the first OUTPUT_MORE/LAST descriptor's + * data buffer is in the context program's coherent page and must not + * be synced. + */ + if ((le32_to_cpu(pd->data_address) & PAGE_MASK) == + (context->current_bus & PAGE_MASK)) { + if (pd->control & cpu_to_le16(DESCRIPTOR_BRANCH_ALWAYS)) + return; + pd++; + } + + do { + buffer_dma = le32_to_cpu(pd->data_address); + dma_sync_single_range_for_cpu(context->ohci->card.device, + buffer_dma & PAGE_MASK, + buffer_dma & ~PAGE_MASK, + le16_to_cpu(pd->req_count), + DMA_TO_DEVICE); + control = pd->control; + pd++; + } while (!(control & cpu_to_le16(DESCRIPTOR_BRANCH_ALWAYS))); +} + static int handle_it_packet(struct context *context, struct descriptor *d, struct descriptor *last) @@ -2587,6 +2821,8 @@ static int handle_it_packet(struct context *context, /* Descriptor(s) not done yet, stop iteration */ return 0; + sync_it_packet_for_cpu(context, d); + i = ctx->header_length; if (i + 4 < PAGE_SIZE) { /* Present this value as big-endian to match the receive code */ @@ -2956,6 +3192,10 @@ static int queue_iso_transmit(struct iso_context *ctx, page_bus = page_private(buffer->pages[page]); pd[i].data_address = cpu_to_le32(page_bus + offset); + dma_sync_single_range_for_device(ctx->context.ohci->card.device, + page_bus, offset, length, + DMA_TO_DEVICE); + payload_index += length; } @@ -2980,6 +3220,7 @@ static int queue_iso_packet_per_buffer(struct iso_context *ctx, struct fw_iso_buffer *buffer, unsigned long payload) { + struct device *device = ctx->context.ohci->card.device; struct descriptor *d, *pd; dma_addr_t d_bus, page_bus; u32 z, header_z, rest; @@ -3034,6 +3275,10 @@ static int queue_iso_packet_per_buffer(struct iso_context *ctx, page_bus = page_private(buffer->pages[page]); pd->data_address = cpu_to_le32(page_bus + offset); + dma_sync_single_range_for_device(device, page_bus, + offset, length, + DMA_FROM_DEVICE); + offset = (offset + length) & ~PAGE_MASK; rest -= length; if (offset == 0) @@ -3093,6 +3338,10 @@ static int queue_iso_buffer_fill(struct iso_context *ctx, page_bus = page_private(buffer->pages[page]); d->data_address = cpu_to_le32(page_bus + offset); + dma_sync_single_range_for_device(ctx->context.ohci->card.device, + page_bus, offset, length, + DMA_FROM_DEVICE); + rest -= length; offset = 0; page++; @@ -3135,7 +3384,6 @@ static void ohci_flush_queue_iso(struct fw_iso_context *base) &container_of(base, struct iso_context, base)->context; reg_write(ctx->ohci, CONTROL_SET(ctx->regs), CONTEXT_WAKE); - flush_writes(ctx->ohci); } static const struct fw_card_driver ohci_driver = { @@ -3225,8 +3473,7 @@ static int __devinit pci_probe(struct pci_dev *dev, spin_lock_init(&ohci->lock); mutex_init(&ohci->phy_reg_mutex); - tasklet_init(&ohci->bus_reset_tasklet, - bus_reset_tasklet, (unsigned long)ohci); + INIT_WORK(&ohci->bus_reset_work, bus_reset_work); err = pci_request_region(dev, 0, ohci_driver_name); if (err) { @@ -3368,6 +3615,7 @@ static void pci_remove(struct pci_dev *dev) ohci = pci_get_drvdata(dev); reg_write(ohci, OHCI1394_IntMaskClear, ~0); flush_writes(ohci); + cancel_work_sync(&ohci->bus_reset_work); fw_core_remove_card(&ohci->card); /* |