diff options
author | Jesse Barnes <jbarnes@virtuousgeek.org> | 2005-10-25 13:28:42 -0400 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@suse.de> | 2005-10-28 18:37:02 -0400 |
commit | f8977d0a9b7ac84cfe700278a2ca64cb33c93a13 (patch) | |
tree | 13af729851215bdbc2291b752f2000a94dff6abb /arch/i386/pci/fixup.c | |
parent | 2f028234f2c7f31dc0ff0784e20f14be11f7035c (diff) |
[PATCH] PCI fixup for Toshiba laptops and ohci1394
This is a fix for a bug I see on my Toshiba laptop, where the ohci1394
controller gets initialized improperly. The patch adds two PCI fixups
to arch/i386/pci/fixup.c, one that happens early on to cache the value
of the PCI_CACHE_LINE_SIZE config register, and another that later
restores the value, along with a valid IRQ number and some BAR values.
I've tested it on my laptop, and it prevents me from running into what I
consider to be a major bug: IRQ 11 is disabled by the IRQ debug code,
causing my wireless to break.
Thanks to Rob for the original patch to ohci1394.c and Stefan for lots
of proofreading (and a last minute bug caught in review!) and additional
information collection. I think the DMI system list is correct, but we
may need to add some more PCI IDs to the PCI_FIXUP macros over time.
Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'arch/i386/pci/fixup.c')
-rw-r--r-- | arch/i386/pci/fixup.c | 59 |
1 files changed, 59 insertions, 0 deletions
diff --git a/arch/i386/pci/fixup.c b/arch/i386/pci/fixup.c index 8e8e895e1b5a..330fd2b68075 100644 --- a/arch/i386/pci/fixup.c +++ b/arch/i386/pci/fixup.c | |||
@@ -2,6 +2,8 @@ | |||
2 | * Exceptions for specific devices. Usually work-arounds for fatal design flaws. | 2 | * Exceptions for specific devices. Usually work-arounds for fatal design flaws. |
3 | */ | 3 | */ |
4 | 4 | ||
5 | #include <linux/delay.h> | ||
6 | #include <linux/dmi.h> | ||
5 | #include <linux/pci.h> | 7 | #include <linux/pci.h> |
6 | #include <linux/init.h> | 8 | #include <linux/init.h> |
7 | #include "pci.h" | 9 | #include "pci.h" |
@@ -384,3 +386,60 @@ static void __devinit pci_fixup_video(struct pci_dev *pdev) | |||
384 | } | 386 | } |
385 | } | 387 | } |
386 | DECLARE_PCI_FIXUP_HEADER(PCI_ANY_ID, PCI_ANY_ID, pci_fixup_video); | 388 | DECLARE_PCI_FIXUP_HEADER(PCI_ANY_ID, PCI_ANY_ID, pci_fixup_video); |
389 | |||
390 | /* | ||
391 | * Some Toshiba laptops need extra code to enable their TI TSB43AB22/A. | ||
392 | * | ||
393 | * We pretend to bring them out of full D3 state, and restore the proper | ||
394 | * IRQ, PCI cache line size, and BARs, otherwise the device won't function | ||
395 | * properly. In some cases, the device will generate an interrupt on | ||
396 | * the wrong IRQ line, causing any devices sharing the the line it's | ||
397 | * *supposed* to use to be disabled by the kernel's IRQ debug code. | ||
398 | */ | ||
399 | static u16 toshiba_line_size; | ||
400 | |||
401 | static struct dmi_system_id __devinit toshiba_ohci1394_dmi_table[] = { | ||
402 | { | ||
403 | .ident = "Toshiba PS5 based laptop", | ||
404 | .matches = { | ||
405 | DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"), | ||
406 | DMI_MATCH(DMI_PRODUCT_VERSION, "PS5"), | ||
407 | }, | ||
408 | }, | ||
409 | { | ||
410 | .ident = "Toshiba PSM4 based laptop", | ||
411 | .matches = { | ||
412 | DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"), | ||
413 | DMI_MATCH(DMI_PRODUCT_VERSION, "PSM4"), | ||
414 | }, | ||
415 | }, | ||
416 | { } | ||
417 | }; | ||
418 | |||
419 | static void __devinit pci_pre_fixup_toshiba_ohci1394(struct pci_dev *dev) | ||
420 | { | ||
421 | if (!dmi_check_system(toshiba_ohci1394_dmi_table)) | ||
422 | return; /* only applies to certain Toshibas (so far) */ | ||
423 | |||
424 | dev->current_state = PCI_D3cold; | ||
425 | pci_read_config_word(dev, PCI_CACHE_LINE_SIZE, &toshiba_line_size); | ||
426 | } | ||
427 | DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_TI, 0x8032, | ||
428 | pci_pre_fixup_toshiba_ohci1394); | ||
429 | |||
430 | static void __devinit pci_post_fixup_toshiba_ohci1394(struct pci_dev *dev) | ||
431 | { | ||
432 | if (!dmi_check_system(toshiba_ohci1394_dmi_table)) | ||
433 | return; /* only applies to certain Toshibas (so far) */ | ||
434 | |||
435 | /* Restore config space on Toshiba laptops */ | ||
436 | mdelay(10); | ||
437 | pci_write_config_word(dev, PCI_CACHE_LINE_SIZE, toshiba_line_size); | ||
438 | pci_write_config_word(dev, PCI_INTERRUPT_LINE, dev->irq); | ||
439 | pci_write_config_dword(dev, PCI_BASE_ADDRESS_0, | ||
440 | pci_resource_start(dev, 0)); | ||
441 | pci_write_config_dword(dev, PCI_BASE_ADDRESS_1, | ||
442 | pci_resource_start(dev, 1)); | ||
443 | } | ||
444 | DECLARE_PCI_FIXUP_ENABLE(PCI_VENDOR_ID_TI, 0x8032, | ||
445 | pci_post_fixup_toshiba_ohci1394); | ||