aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/pci/quirks.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/pci/quirks.c')
-rw-r--r--drivers/pci/quirks.c91
1 files changed, 90 insertions, 1 deletions
diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c
index 7cfa7c38d318..d58b94030ef3 100644
--- a/drivers/pci/quirks.c
+++ b/drivers/pci/quirks.c
@@ -338,6 +338,23 @@ static void __devinit quirk_s3_64M(struct pci_dev *dev)
338DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_S3, PCI_DEVICE_ID_S3_868, quirk_s3_64M); 338DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_S3, PCI_DEVICE_ID_S3_868, quirk_s3_64M);
339DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_S3, PCI_DEVICE_ID_S3_968, quirk_s3_64M); 339DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_S3, PCI_DEVICE_ID_S3_968, quirk_s3_64M);
340 340
341/*
342 * Some CS5536 BIOSes (for example, the Soekris NET5501 board w/ comBIOS
343 * ver. 1.33 20070103) don't set the correct ISA PCI region header info.
344 * BAR0 should be 8 bytes; instead, it may be set to something like 8k
345 * (which conflicts w/ BAR1's memory range).
346 */
347static void __devinit quirk_cs5536_vsa(struct pci_dev *dev)
348{
349 if (pci_resource_len(dev, 0) != 8) {
350 struct resource *res = &dev->resource[0];
351 res->end = res->start + 8 - 1;
352 dev_info(&dev->dev, "CS5536 ISA bridge bug detected "
353 "(incorrect header); workaround applied.\n");
354 }
355}
356DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_CS5536_ISA, quirk_cs5536_vsa);
357
341static void __devinit quirk_io_region(struct pci_dev *dev, unsigned region, 358static void __devinit quirk_io_region(struct pci_dev *dev, unsigned region,
342 unsigned size, int nr, const char *name) 359 unsigned size, int nr, const char *name)
343{ 360{
@@ -2629,14 +2646,86 @@ static int __init pci_apply_final_quirks(void)
2629 if (!pci_cache_line_size) { 2646 if (!pci_cache_line_size) {
2630 printk(KERN_DEBUG "PCI: CLS %u bytes, default %u\n", 2647 printk(KERN_DEBUG "PCI: CLS %u bytes, default %u\n",
2631 cls << 2, pci_dfl_cache_line_size << 2); 2648 cls << 2, pci_dfl_cache_line_size << 2);
2632 pci_cache_line_size = cls; 2649 pci_cache_line_size = cls ? cls : pci_dfl_cache_line_size;
2633 } 2650 }
2634 2651
2635 return 0; 2652 return 0;
2636} 2653}
2637 2654
2638fs_initcall_sync(pci_apply_final_quirks); 2655fs_initcall_sync(pci_apply_final_quirks);
2656
2657/*
2658 * Followings are device-specific reset methods which can be used to
2659 * reset a single function if other methods (e.g. FLR, PM D0->D3) are
2660 * not available.
2661 */
2662static int reset_intel_generic_dev(struct pci_dev *dev, int probe)
2663{
2664 int pos;
2665
2666 /* only implement PCI_CLASS_SERIAL_USB at present */
2667 if (dev->class == PCI_CLASS_SERIAL_USB) {
2668 pos = pci_find_capability(dev, PCI_CAP_ID_VNDR);
2669 if (!pos)
2670 return -ENOTTY;
2671
2672 if (probe)
2673 return 0;
2674
2675 pci_write_config_byte(dev, pos + 0x4, 1);
2676 msleep(100);
2677
2678 return 0;
2679 } else {
2680 return -ENOTTY;
2681 }
2682}
2683
2684static int reset_intel_82599_sfp_virtfn(struct pci_dev *dev, int probe)
2685{
2686 int pos;
2687
2688 pos = pci_find_capability(dev, PCI_CAP_ID_EXP);
2689 if (!pos)
2690 return -ENOTTY;
2691
2692 if (probe)
2693 return 0;
2694
2695 pci_write_config_word(dev, pos + PCI_EXP_DEVCTL,
2696 PCI_EXP_DEVCTL_BCR_FLR);
2697 msleep(100);
2698
2699 return 0;
2700}
2701
2702#define PCI_DEVICE_ID_INTEL_82599_SFP_VF 0x10ed
2703
2704static const struct pci_dev_reset_methods pci_dev_reset_methods[] = {
2705 { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82599_SFP_VF,
2706 reset_intel_82599_sfp_virtfn },
2707 { PCI_VENDOR_ID_INTEL, PCI_ANY_ID,
2708 reset_intel_generic_dev },
2709 { 0 }
2710};
2711
2712int pci_dev_specific_reset(struct pci_dev *dev, int probe)
2713{
2714 const struct pci_dev_reset_methods *i;
2715
2716 for (i = pci_dev_reset_methods; i->reset; i++) {
2717 if ((i->vendor == dev->vendor ||
2718 i->vendor == (u16)PCI_ANY_ID) &&
2719 (i->device == dev->device ||
2720 i->device == (u16)PCI_ANY_ID))
2721 return i->reset(dev, probe);
2722 }
2723
2724 return -ENOTTY;
2725}
2726
2639#else 2727#else
2640void pci_fixup_device(enum pci_fixup_pass pass, struct pci_dev *dev) {} 2728void pci_fixup_device(enum pci_fixup_pass pass, struct pci_dev *dev) {}
2729int pci_dev_specific_reset(struct pci_dev *dev, int probe) { return -ENOTTY; }
2641#endif 2730#endif
2642EXPORT_SYMBOL(pci_fixup_device); 2731EXPORT_SYMBOL(pci_fixup_device);