diff options
Diffstat (limited to 'drivers/firewire/ohci.c')
| -rw-r--r-- | drivers/firewire/ohci.c | 109 |
1 files changed, 67 insertions, 42 deletions
diff --git a/drivers/firewire/ohci.c b/drivers/firewire/ohci.c index 9e1db6490b9..a66a3217f1d 100644 --- a/drivers/firewire/ohci.c +++ b/drivers/firewire/ohci.c @@ -235,13 +235,15 @@ struct fw_ohci { dma_addr_t next_config_rom_bus; __be32 next_header; - __le32 *self_id_cpu; + __le32 *self_id; dma_addr_t self_id_bus; struct work_struct bus_reset_work; u32 self_id_buffer[512]; }; +static struct workqueue_struct *selfid_workqueue; + static inline struct fw_ohci *fw_ohci(struct fw_card *card) { return container_of(card, struct fw_ohci, card); @@ -271,6 +273,7 @@ static inline struct fw_ohci *fw_ohci(struct fw_card *card) static char ohci_driver_name[] = KBUILD_MODNAME; +#define PCI_VENDOR_ID_PINNACLE_SYSTEMS 0x11bd #define PCI_DEVICE_ID_AGERE_FW643 0x5901 #define PCI_DEVICE_ID_CREATIVE_SB1394 0x4001 #define PCI_DEVICE_ID_JMICRON_JMB38X_FW 0x2380 @@ -278,17 +281,16 @@ static char ohci_driver_name[] = KBUILD_MODNAME; #define PCI_DEVICE_ID_TI_TSB12LV26 0x8020 #define PCI_DEVICE_ID_TI_TSB82AA2 0x8025 #define PCI_DEVICE_ID_VIA_VT630X 0x3044 -#define PCI_VENDOR_ID_PINNACLE_SYSTEMS 0x11bd #define PCI_REV_ID_VIA_VT6306 0x46 +#define PCI_DEVICE_ID_VIA_VT6315 0x3403 -#define QUIRK_CYCLE_TIMER 1 -#define QUIRK_RESET_PACKET 2 -#define QUIRK_BE_HEADERS 4 -#define QUIRK_NO_1394A 8 -#define QUIRK_NO_MSI 16 -#define QUIRK_TI_SLLZ059 32 -#define QUIRK_IR_WAKE 64 -#define QUIRK_PHY_LCTRL_TIMEOUT 128 +#define QUIRK_CYCLE_TIMER 0x1 +#define QUIRK_RESET_PACKET 0x2 +#define QUIRK_BE_HEADERS 0x4 +#define QUIRK_NO_1394A 0x8 +#define QUIRK_NO_MSI 0x10 +#define QUIRK_TI_SLLZ059 0x20 +#define QUIRK_IR_WAKE 0x40 /* In case of multiple matches in ohci_quirks[], only the first one is used. */ static const struct { @@ -301,10 +303,7 @@ static const struct { QUIRK_BE_HEADERS}, {PCI_VENDOR_ID_ATT, PCI_DEVICE_ID_AGERE_FW643, 6, - QUIRK_PHY_LCTRL_TIMEOUT | QUIRK_NO_MSI}, - - {PCI_VENDOR_ID_ATT, PCI_ANY_ID, PCI_ANY_ID, - QUIRK_PHY_LCTRL_TIMEOUT}, + QUIRK_NO_MSI}, {PCI_VENDOR_ID_CREATIVE, PCI_DEVICE_ID_CREATIVE_SB1394, PCI_ANY_ID, QUIRK_RESET_PACKET}, @@ -336,6 +335,12 @@ static const struct { {PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_VT630X, PCI_REV_ID_VIA_VT6306, QUIRK_CYCLE_TIMER | QUIRK_IR_WAKE}, + {PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_VT6315, 0, + QUIRK_CYCLE_TIMER /* FIXME: necessary? */ | QUIRK_NO_MSI}, + + {PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_VT6315, PCI_ANY_ID, + QUIRK_NO_MSI}, + {PCI_VENDOR_ID_VIA, PCI_ANY_ID, PCI_ANY_ID, QUIRK_CYCLE_TIMER | QUIRK_NO_MSI}, }; @@ -351,7 +356,6 @@ MODULE_PARM_DESC(quirks, "Chip quirks (default = 0" ", disable MSI = " __stringify(QUIRK_NO_MSI) ", TI SLLZ059 erratum = " __stringify(QUIRK_TI_SLLZ059) ", IR wake unreliable = " __stringify(QUIRK_IR_WAKE) - ", phy LCtrl timeout = " __stringify(QUIRK_PHY_LCTRL_TIMEOUT) ")"); #define OHCI_PARAM_DEBUG_AT_AR 1 @@ -368,6 +372,10 @@ MODULE_PARM_DESC(debug, "Verbose logging (default = 0" ", busReset events = " __stringify(OHCI_PARAM_DEBUG_BUSRESETS) ", or a combination, or all = -1)"); +static bool param_remote_dma; +module_param_named(remote_dma, param_remote_dma, bool, 0444); +MODULE_PARM_DESC(remote_dma, "Enable unfiltered remote DMA (default = N)"); + static void log_irqs(struct fw_ohci *ohci, u32 evt) { if (likely(!(param_debug & @@ -1929,12 +1937,12 @@ static void bus_reset_work(struct work_struct *work) return; } - generation = (cond_le32_to_cpu(ohci->self_id_cpu[0]) >> 16) & 0xff; + generation = (cond_le32_to_cpu(ohci->self_id[0]) >> 16) & 0xff; rmb(); for (i = 1, j = 0; j < self_id_count; i += 2, j++) { - u32 id = cond_le32_to_cpu(ohci->self_id_cpu[i]); - u32 id2 = cond_le32_to_cpu(ohci->self_id_cpu[i + 1]); + u32 id = cond_le32_to_cpu(ohci->self_id[i]); + u32 id2 = cond_le32_to_cpu(ohci->self_id[i + 1]); if (id != ~id2) { /* @@ -2048,10 +2056,10 @@ static void bus_reset_work(struct work_struct *work) be32_to_cpu(ohci->next_header)); } -#ifdef CONFIG_FIREWIRE_OHCI_REMOTE_DMA - reg_write(ohci, OHCI1394_PhyReqFilterHiSet, ~0); - reg_write(ohci, OHCI1394_PhyReqFilterLoSet, ~0); -#endif + if (param_remote_dma) { + reg_write(ohci, OHCI1394_PhyReqFilterHiSet, ~0); + reg_write(ohci, OHCI1394_PhyReqFilterLoSet, ~0); + } spin_unlock_irq(&ohci->lock); @@ -2087,7 +2095,7 @@ static irqreturn_t irq_handler(int irq, void *data) log_irqs(ohci, event); if (event & OHCI1394_selfIDComplete) - queue_work(fw_workqueue, &ohci->bus_reset_work); + queue_work(selfid_workqueue, &ohci->bus_reset_work); if (event & OHCI1394_RQPkt) tasklet_schedule(&ohci->ar_request_ctx.tasklet); @@ -2293,9 +2301,6 @@ static int ohci_enable(struct fw_card *card, * TI TSB82AA2 + TSB81BA3(A) cards signal LPS enabled early but * cannot actually use the phy at that time. These need tens of * millisecods pause between LPS write and first phy access too. - * - * But do not wait for 50msec on Agere/LSI cards. Their phy - * arbitration state machine may time out during such a long wait. */ reg_write(ohci, OHCI1394_HCControlSet, @@ -2303,11 +2308,8 @@ static int ohci_enable(struct fw_card *card, OHCI1394_HCControl_postedWriteEnable); flush_writes(ohci); - if (!(ohci->quirks & QUIRK_PHY_LCTRL_TIMEOUT)) + for (lps = 0, i = 0; !lps && i < 3; i++) { msleep(50); - - for (lps = 0, i = 0; !lps && i < 150; i++) { - msleep(1); lps = reg_read(ohci, OHCI1394_HCControlSet) & OHCI1394_HCControl_LPS; } @@ -2361,7 +2363,7 @@ static int ohci_enable(struct fw_card *card, reg_write(ohci, OHCI1394_FairnessControl, 0); card->priority_budget_implemented = ohci->pri_req_max != 0; - reg_write(ohci, OHCI1394_PhyUpperBound, 0x00010000); + reg_write(ohci, OHCI1394_PhyUpperBound, FW_MAX_PHYSICAL_RANGE >> 16); reg_write(ohci, OHCI1394_IntEventClear, ~0); reg_write(ohci, OHCI1394_IntMaskClear, ~0); @@ -2585,13 +2587,13 @@ static int ohci_cancel_packet(struct fw_card *card, struct fw_packet *packet) static int ohci_enable_phys_dma(struct fw_card *card, int node_id, int generation) { -#ifdef CONFIG_FIREWIRE_OHCI_REMOTE_DMA - return 0; -#else struct fw_ohci *ohci = fw_ohci(card); unsigned long flags; int n, ret = 0; + if (param_remote_dma) + return 0; + /* * FIXME: Make sure this bitmask is cleared when we clear the busReset * interrupt bit. Clear physReqResourceAllBuses on bus reset. @@ -2620,7 +2622,6 @@ static int ohci_enable_phys_dma(struct fw_card *card, spin_unlock_irqrestore(&ohci->lock, flags); return ret; -#endif /* CONFIG_FIREWIRE_OHCI_REMOTE_DMA */ } static u32 ohci_read_csr(struct fw_card *card, int csr_offset) @@ -2749,8 +2750,11 @@ static void copy_iso_headers(struct iso_context *ctx, const u32 *dma_hdr) { u32 *ctx_hdr; - if (ctx->header_length + ctx->base.header_size > PAGE_SIZE) + if (ctx->header_length + ctx->base.header_size > PAGE_SIZE) { + if (ctx->base.drop_overflow_headers) + return; flush_iso_completions(ctx); + } ctx_hdr = ctx->header + ctx->header_length; ctx->last_timestamp = (u16)le32_to_cpu((__force __le32)dma_hdr[0]); @@ -2910,8 +2914,11 @@ static int handle_it_packet(struct context *context, sync_it_packet_for_cpu(context, d); - if (ctx->header_length + 4 > PAGE_SIZE) + if (ctx->header_length + 4 > PAGE_SIZE) { + if (ctx->base.drop_overflow_headers) + return 1; flush_iso_completions(ctx); + } ctx_hdr = ctx->header + ctx->header_length; ctx->last_timestamp = le16_to_cpu(last->res_count); @@ -3498,7 +3505,7 @@ static int ohci_flush_iso_completions(struct fw_iso_context *base) } clear_bit_unlock(0, &ctx->flushing_completions); - smp_mb__after_clear_bit(); + smp_mb__after_atomic(); } tasklet_enable(&ctx->context.tasklet); @@ -3686,7 +3693,7 @@ static int pci_probe(struct pci_dev *dev, goto fail_contexts; } - ohci->self_id_cpu = ohci->misc_buffer + PAGE_SIZE/2; + ohci->self_id = ohci->misc_buffer + PAGE_SIZE/2; ohci->self_id_bus = ohci->misc_buffer_bus + PAGE_SIZE/2; bus_options = reg_read(ohci, OHCI1394_BusOptions); @@ -3712,9 +3719,11 @@ static int pci_probe(struct pci_dev *dev, version = reg_read(ohci, OHCI1394_Version) & 0x00ff00ff; ohci_notice(ohci, "added OHCI v%x.%x device as card %d, " - "%d IR + %d IT contexts, quirks 0x%x\n", + "%d IR + %d IT contexts, quirks 0x%x%s\n", version >> 16, version & 0xff, ohci->card.index, - ohci->n_ir, ohci->n_it, ohci->quirks); + ohci->n_ir, ohci->n_it, ohci->quirks, + reg_read(ohci, OHCI1394_PhyUpperBound) ? + ", physUB" : ""); return 0; @@ -3864,7 +3873,23 @@ static struct pci_driver fw_ohci_pci_driver = { #endif }; -module_pci_driver(fw_ohci_pci_driver); +static int __init fw_ohci_init(void) +{ + selfid_workqueue = alloc_workqueue(KBUILD_MODNAME, WQ_MEM_RECLAIM, 0); + if (!selfid_workqueue) + return -ENOMEM; + + return pci_register_driver(&fw_ohci_pci_driver); +} + +static void __exit fw_ohci_cleanup(void) +{ + pci_unregister_driver(&fw_ohci_pci_driver); + destroy_workqueue(selfid_workqueue); +} + +module_init(fw_ohci_init); +module_exit(fw_ohci_cleanup); MODULE_AUTHOR("Kristian Hoegsberg <krh@bitplanet.net>"); MODULE_DESCRIPTION("Driver for PCI OHCI IEEE1394 controllers"); |
