diff options
author | Clemens Ladisch <clemens@ladisch.de> | 2010-06-05 06:31:25 -0400 |
---|---|---|
committer | Stefan Richter <stefanr@s5r6.in-berlin.de> | 2010-06-09 13:42:18 -0400 |
commit | 262444eecce40950af19ea4d75a3dc03b3c07283 (patch) | |
tree | 87b465d2bdc2cc600807910d372e68ba668bda8a /drivers/firewire/ohci.c | |
parent | 148c7866c31d93f8c79366189075f5a26ad4556c (diff) |
firewire: ohci: add MSI support
This patch adds support for message-signaled interrupts.
Any native PCI-Express OHCI controller should support MSI, but most are
just PCI cores behind a PCI-E/PCI bridge. The only chips that are known
to claim to support MSI are the Lucent/Agere/LSI FW643 and the VIA
VT6315, none of which I have been able to test.
Due to the high level of trust I have in the competence of these and any
future chip makers, I thought it a good idea to add a disable-MSI quirk.
Signed-off-by: Clemens Ladisch <clemens@ladisch.de>
Tested Agere FW643 rev 07 [11c1:5901] and JMicron JMB381 [197b:2380].
Added a quirks list entry for JMB38X since it kept its count of MSI
events consistently at zero.
Signed-off-by: Stefan Richter <stefanr@s5r6.in-berlin.de>
Diffstat (limited to 'drivers/firewire/ohci.c')
-rw-r--r-- | drivers/firewire/ohci.c | 15 |
1 files changed, 12 insertions, 3 deletions
diff --git a/drivers/firewire/ohci.c b/drivers/firewire/ohci.c index 9743a405e69c..de5ff376231c 100644 --- a/drivers/firewire/ohci.c +++ b/drivers/firewire/ohci.c | |||
@@ -231,12 +231,14 @@ static inline struct fw_ohci *fw_ohci(struct fw_card *card) | |||
231 | 231 | ||
232 | static char ohci_driver_name[] = KBUILD_MODNAME; | 232 | static char ohci_driver_name[] = KBUILD_MODNAME; |
233 | 233 | ||
234 | #define PCI_DEVICE_ID_JMICRON_JMB38X_FW 0x2380 | ||
234 | #define PCI_DEVICE_ID_TI_TSB12LV22 0x8009 | 235 | #define PCI_DEVICE_ID_TI_TSB12LV22 0x8009 |
235 | 236 | ||
236 | #define QUIRK_CYCLE_TIMER 1 | 237 | #define QUIRK_CYCLE_TIMER 1 |
237 | #define QUIRK_RESET_PACKET 2 | 238 | #define QUIRK_RESET_PACKET 2 |
238 | #define QUIRK_BE_HEADERS 4 | 239 | #define QUIRK_BE_HEADERS 4 |
239 | #define QUIRK_NO_1394A 8 | 240 | #define QUIRK_NO_1394A 8 |
241 | #define QUIRK_NO_MSI 16 | ||
240 | 242 | ||
241 | /* In case of multiple matches in ohci_quirks[], only the first one is used. */ | 243 | /* In case of multiple matches in ohci_quirks[], only the first one is used. */ |
242 | static const struct { | 244 | static const struct { |
@@ -247,6 +249,7 @@ static const struct { | |||
247 | QUIRK_NO_1394A}, | 249 | QUIRK_NO_1394A}, |
248 | {PCI_VENDOR_ID_TI, PCI_ANY_ID, QUIRK_RESET_PACKET}, | 250 | {PCI_VENDOR_ID_TI, PCI_ANY_ID, QUIRK_RESET_PACKET}, |
249 | {PCI_VENDOR_ID_AL, PCI_ANY_ID, QUIRK_CYCLE_TIMER}, | 251 | {PCI_VENDOR_ID_AL, PCI_ANY_ID, QUIRK_CYCLE_TIMER}, |
252 | {PCI_VENDOR_ID_JMICRON, PCI_DEVICE_ID_JMICRON_JMB38X_FW, QUIRK_NO_MSI}, | ||
250 | {PCI_VENDOR_ID_NEC, PCI_ANY_ID, QUIRK_CYCLE_TIMER}, | 253 | {PCI_VENDOR_ID_NEC, PCI_ANY_ID, QUIRK_CYCLE_TIMER}, |
251 | {PCI_VENDOR_ID_VIA, PCI_ANY_ID, QUIRK_CYCLE_TIMER}, | 254 | {PCI_VENDOR_ID_VIA, PCI_ANY_ID, QUIRK_CYCLE_TIMER}, |
252 | {PCI_VENDOR_ID_APPLE, PCI_DEVICE_ID_APPLE_UNI_N_FW, QUIRK_BE_HEADERS}, | 255 | {PCI_VENDOR_ID_APPLE, PCI_DEVICE_ID_APPLE_UNI_N_FW, QUIRK_BE_HEADERS}, |
@@ -260,6 +263,7 @@ MODULE_PARM_DESC(quirks, "Chip quirks (default = 0" | |||
260 | ", reset packet generation = " __stringify(QUIRK_RESET_PACKET) | 263 | ", reset packet generation = " __stringify(QUIRK_RESET_PACKET) |
261 | ", AR/selfID endianess = " __stringify(QUIRK_BE_HEADERS) | 264 | ", AR/selfID endianess = " __stringify(QUIRK_BE_HEADERS) |
262 | ", no 1394a enhancements = " __stringify(QUIRK_NO_1394A) | 265 | ", no 1394a enhancements = " __stringify(QUIRK_NO_1394A) |
266 | ", disable MSI = " __stringify(QUIRK_NO_MSI) | ||
263 | ")"); | 267 | ")"); |
264 | 268 | ||
265 | #define OHCI_PARAM_DEBUG_AT_AR 1 | 269 | #define OHCI_PARAM_DEBUG_AT_AR 1 |
@@ -1704,10 +1708,13 @@ static int ohci_enable(struct fw_card *card, | |||
1704 | 1708 | ||
1705 | reg_write(ohci, OHCI1394_AsReqFilterHiSet, 0x80000000); | 1709 | reg_write(ohci, OHCI1394_AsReqFilterHiSet, 0x80000000); |
1706 | 1710 | ||
1711 | if (!(ohci->quirks & QUIRK_NO_MSI)) | ||
1712 | pci_enable_msi(dev); | ||
1707 | if (request_irq(dev->irq, irq_handler, | 1713 | if (request_irq(dev->irq, irq_handler, |
1708 | IRQF_SHARED, ohci_driver_name, ohci)) { | 1714 | pci_dev_msi_enabled(dev) ? 0 : IRQF_SHARED, |
1709 | fw_error("Failed to allocate shared interrupt %d.\n", | 1715 | ohci_driver_name, ohci)) { |
1710 | dev->irq); | 1716 | fw_error("Failed to allocate interrupt %d.\n", dev->irq); |
1717 | pci_disable_msi(dev); | ||
1711 | dma_free_coherent(ohci->card.device, CONFIG_ROM_SIZE, | 1718 | dma_free_coherent(ohci->card.device, CONFIG_ROM_SIZE, |
1712 | ohci->config_rom, ohci->config_rom_bus); | 1719 | ohci->config_rom, ohci->config_rom_bus); |
1713 | return -EIO; | 1720 | return -EIO; |
@@ -2622,6 +2629,7 @@ static void pci_remove(struct pci_dev *dev) | |||
2622 | context_release(&ohci->at_response_ctx); | 2629 | context_release(&ohci->at_response_ctx); |
2623 | kfree(ohci->it_context_list); | 2630 | kfree(ohci->it_context_list); |
2624 | kfree(ohci->ir_context_list); | 2631 | kfree(ohci->ir_context_list); |
2632 | pci_disable_msi(dev); | ||
2625 | pci_iounmap(dev, ohci->registers); | 2633 | pci_iounmap(dev, ohci->registers); |
2626 | pci_release_region(dev, 0); | 2634 | pci_release_region(dev, 0); |
2627 | pci_disable_device(dev); | 2635 | pci_disable_device(dev); |
@@ -2639,6 +2647,7 @@ static int pci_suspend(struct pci_dev *dev, pm_message_t state) | |||
2639 | 2647 | ||
2640 | software_reset(ohci); | 2648 | software_reset(ohci); |
2641 | free_irq(dev->irq, ohci); | 2649 | free_irq(dev->irq, ohci); |
2650 | pci_disable_msi(dev); | ||
2642 | err = pci_save_state(dev); | 2651 | err = pci_save_state(dev); |
2643 | if (err) { | 2652 | if (err) { |
2644 | fw_error("pci_save_state failed\n"); | 2653 | fw_error("pci_save_state failed\n"); |