diff options
author | Andrea Bastoni <bastoni@cs.unc.edu> | 2010-05-30 19:16:45 -0400 |
---|---|---|
committer | Andrea Bastoni <bastoni@cs.unc.edu> | 2010-05-30 19:16:45 -0400 |
commit | ada47b5fe13d89735805b566185f4885f5a3f750 (patch) | |
tree | 644b88f8a71896307d71438e9b3af49126ffb22b /drivers/pci/quirks.c | |
parent | 43e98717ad40a4ae64545b5ba047c7b86aa44f4f (diff) | |
parent | 3280f21d43ee541f97f8cda5792150d2dbec20d5 (diff) |
Merge branch 'wip-2.6.34' into old-private-masterarchived-private-master
Diffstat (limited to 'drivers/pci/quirks.c')
-rw-r--r-- | drivers/pci/quirks.c | 252 |
1 files changed, 234 insertions, 18 deletions
diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c index 245d2cdb4765..27c0e6eb7136 100644 --- a/drivers/pci/quirks.c +++ b/drivers/pci/quirks.c | |||
@@ -25,14 +25,9 @@ | |||
25 | #include <linux/dmi.h> | 25 | #include <linux/dmi.h> |
26 | #include <linux/pci-aspm.h> | 26 | #include <linux/pci-aspm.h> |
27 | #include <linux/ioport.h> | 27 | #include <linux/ioport.h> |
28 | #include <asm/dma.h> /* isa_dma_bridge_buggy */ | ||
28 | #include "pci.h" | 29 | #include "pci.h" |
29 | 30 | ||
30 | int isa_dma_bridge_buggy; | ||
31 | EXPORT_SYMBOL(isa_dma_bridge_buggy); | ||
32 | int pci_pci_problems; | ||
33 | EXPORT_SYMBOL(pci_pci_problems); | ||
34 | |||
35 | #ifdef CONFIG_PCI_QUIRKS | ||
36 | /* | 31 | /* |
37 | * This quirk function disables memory decoding and releases memory resources | 32 | * This quirk function disables memory decoding and releases memory resources |
38 | * of the device specified by kernel's boot parameter 'pci=resource_alignment='. | 33 | * of the device specified by kernel's boot parameter 'pci=resource_alignment='. |
@@ -338,6 +333,23 @@ static void __devinit quirk_s3_64M(struct pci_dev *dev) | |||
338 | DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_S3, PCI_DEVICE_ID_S3_868, quirk_s3_64M); | 333 | DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_S3, PCI_DEVICE_ID_S3_868, quirk_s3_64M); |
339 | DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_S3, PCI_DEVICE_ID_S3_968, quirk_s3_64M); | 334 | DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_S3, PCI_DEVICE_ID_S3_968, quirk_s3_64M); |
340 | 335 | ||
336 | /* | ||
337 | * Some CS5536 BIOSes (for example, the Soekris NET5501 board w/ comBIOS | ||
338 | * ver. 1.33 20070103) don't set the correct ISA PCI region header info. | ||
339 | * BAR0 should be 8 bytes; instead, it may be set to something like 8k | ||
340 | * (which conflicts w/ BAR1's memory range). | ||
341 | */ | ||
342 | static void __devinit quirk_cs5536_vsa(struct pci_dev *dev) | ||
343 | { | ||
344 | if (pci_resource_len(dev, 0) != 8) { | ||
345 | struct resource *res = &dev->resource[0]; | ||
346 | res->end = res->start + 8 - 1; | ||
347 | dev_info(&dev->dev, "CS5536 ISA bridge bug detected " | ||
348 | "(incorrect header); workaround applied.\n"); | ||
349 | } | ||
350 | } | ||
351 | DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_CS5536_ISA, quirk_cs5536_vsa); | ||
352 | |||
341 | static void __devinit quirk_io_region(struct pci_dev *dev, unsigned region, | 353 | static void __devinit quirk_io_region(struct pci_dev *dev, unsigned region, |
342 | unsigned size, int nr, const char *name) | 354 | unsigned size, int nr, const char *name) |
343 | { | 355 | { |
@@ -356,8 +368,9 @@ static void __devinit quirk_io_region(struct pci_dev *dev, unsigned region, | |||
356 | bus_region.end = res->end; | 368 | bus_region.end = res->end; |
357 | pcibios_bus_to_resource(dev, res, &bus_region); | 369 | pcibios_bus_to_resource(dev, res, &bus_region); |
358 | 370 | ||
359 | pci_claim_resource(dev, nr); | 371 | if (pci_claim_resource(dev, nr) == 0) |
360 | dev_info(&dev->dev, "quirk: region %04x-%04x claimed by %s\n", region, region + size - 1, name); | 372 | dev_info(&dev->dev, "quirk: %pR claimed by %s\n", |
373 | res, name); | ||
361 | } | 374 | } |
362 | } | 375 | } |
363 | 376 | ||
@@ -1680,6 +1693,7 @@ DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_SERVERWORKS, PCI_DEVICE_ID_SERVERWORKS_ | |||
1680 | */ | 1693 | */ |
1681 | #define AMD_813X_MISC 0x40 | 1694 | #define AMD_813X_MISC 0x40 |
1682 | #define AMD_813X_NOIOAMODE (1<<0) | 1695 | #define AMD_813X_NOIOAMODE (1<<0) |
1696 | #define AMD_813X_REV_B1 0x12 | ||
1683 | #define AMD_813X_REV_B2 0x13 | 1697 | #define AMD_813X_REV_B2 0x13 |
1684 | 1698 | ||
1685 | static void quirk_disable_amd_813x_boot_interrupt(struct pci_dev *dev) | 1699 | static void quirk_disable_amd_813x_boot_interrupt(struct pci_dev *dev) |
@@ -1688,7 +1702,8 @@ static void quirk_disable_amd_813x_boot_interrupt(struct pci_dev *dev) | |||
1688 | 1702 | ||
1689 | if (noioapicquirk) | 1703 | if (noioapicquirk) |
1690 | return; | 1704 | return; |
1691 | if (dev->revision == AMD_813X_REV_B2) | 1705 | if ((dev->revision == AMD_813X_REV_B1) || |
1706 | (dev->revision == AMD_813X_REV_B2)) | ||
1692 | return; | 1707 | return; |
1693 | 1708 | ||
1694 | pci_read_config_dword(dev, AMD_813X_MISC, &pci_config_dword); | 1709 | pci_read_config_dword(dev, AMD_813X_MISC, &pci_config_dword); |
@@ -1698,8 +1713,10 @@ static void quirk_disable_amd_813x_boot_interrupt(struct pci_dev *dev) | |||
1698 | dev_info(&dev->dev, "disabled boot interrupts on device [%04x:%04x]\n", | 1713 | dev_info(&dev->dev, "disabled boot interrupts on device [%04x:%04x]\n", |
1699 | dev->vendor, dev->device); | 1714 | dev->vendor, dev->device); |
1700 | } | 1715 | } |
1701 | DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_8131_BRIDGE, quirk_disable_amd_813x_boot_interrupt); | 1716 | DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_8131_BRIDGE, quirk_disable_amd_813x_boot_interrupt); |
1702 | DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_8132_BRIDGE, quirk_disable_amd_813x_boot_interrupt); | 1717 | DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_8131_BRIDGE, quirk_disable_amd_813x_boot_interrupt); |
1718 | DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_8132_BRIDGE, quirk_disable_amd_813x_boot_interrupt); | ||
1719 | DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_8132_BRIDGE, quirk_disable_amd_813x_boot_interrupt); | ||
1703 | 1720 | ||
1704 | #define AMD_8111_PCI_IRQ_ROUTING 0x56 | 1721 | #define AMD_8111_PCI_IRQ_ROUTING 0x56 |
1705 | 1722 | ||
@@ -1961,11 +1978,25 @@ static void __devinit quirk_via_cx700_pci_parking_caching(struct pci_dev *dev) | |||
1961 | /* | 1978 | /* |
1962 | * Disable PCI Bus Parking and PCI Master read caching on CX700 | 1979 | * Disable PCI Bus Parking and PCI Master read caching on CX700 |
1963 | * which causes unspecified timing errors with a VT6212L on the PCI | 1980 | * which causes unspecified timing errors with a VT6212L on the PCI |
1964 | * bus leading to USB2.0 packet loss. The defaults are that these | 1981 | * bus leading to USB2.0 packet loss. |
1965 | * features are turned off but some BIOSes turn them on. | 1982 | * |
1983 | * This quirk is only enabled if a second (on the external PCI bus) | ||
1984 | * VT6212L is found -- the CX700 core itself also contains a USB | ||
1985 | * host controller with the same PCI ID as the VT6212L. | ||
1966 | */ | 1986 | */ |
1967 | 1987 | ||
1988 | /* Count VT6212L instances */ | ||
1989 | struct pci_dev *p = pci_get_device(PCI_VENDOR_ID_VIA, | ||
1990 | PCI_DEVICE_ID_VIA_8235_USB_2, NULL); | ||
1968 | uint8_t b; | 1991 | uint8_t b; |
1992 | |||
1993 | /* p should contain the first (internal) VT6212L -- see if we have | ||
1994 | an external one by searching again */ | ||
1995 | p = pci_get_device(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8235_USB_2, p); | ||
1996 | if (!p) | ||
1997 | return; | ||
1998 | pci_dev_put(p); | ||
1999 | |||
1969 | if (pci_read_config_byte(dev, 0x76, &b) == 0) { | 2000 | if (pci_read_config_byte(dev, 0x76, &b) == 0) { |
1970 | if (b & 0x40) { | 2001 | if (b & 0x40) { |
1971 | /* Turn off PCI Bus Parking */ | 2002 | /* Turn off PCI Bus Parking */ |
@@ -1992,7 +2023,7 @@ static void __devinit quirk_via_cx700_pci_parking_caching(struct pci_dev *dev) | |||
1992 | } | 2023 | } |
1993 | } | 2024 | } |
1994 | } | 2025 | } |
1995 | DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_VIA, 0x324e, quirk_via_cx700_pci_parking_caching); | 2026 | DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_VIA, 0x324e, quirk_via_cx700_pci_parking_caching); |
1996 | 2027 | ||
1997 | /* | 2028 | /* |
1998 | * For Broadcom 5706, 5708, 5709 rev. A nics, any read beyond the | 2029 | * For Broadcom 5706, 5708, 5709 rev. A nics, any read beyond the |
@@ -2092,6 +2123,10 @@ static void __devinit quirk_disable_msi(struct pci_dev *dev) | |||
2092 | } | 2123 | } |
2093 | } | 2124 | } |
2094 | DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_8131_BRIDGE, quirk_disable_msi); | 2125 | DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_8131_BRIDGE, quirk_disable_msi); |
2126 | DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_AMD, 0x9602, quirk_disable_msi); | ||
2127 | DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_ASUSTEK, 0x9602, quirk_disable_msi); | ||
2128 | DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_AI, 0x9602, quirk_disable_msi); | ||
2129 | DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_VIA, 0xa238, quirk_disable_msi); | ||
2095 | 2130 | ||
2096 | /* Go through the list of Hypertransport capabilities and | 2131 | /* Go through the list of Hypertransport capabilities and |
2097 | * return 1 if a HT MSI capability is found and enabled */ | 2132 | * return 1 if a HT MSI capability is found and enabled */ |
@@ -2513,9 +2548,95 @@ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x10e7, quirk_i82576_sriov); | |||
2513 | DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x10e8, quirk_i82576_sriov); | 2548 | DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x10e8, quirk_i82576_sriov); |
2514 | DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x150a, quirk_i82576_sriov); | 2549 | DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x150a, quirk_i82576_sriov); |
2515 | DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x150d, quirk_i82576_sriov); | 2550 | DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x150d, quirk_i82576_sriov); |
2551 | DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x1518, quirk_i82576_sriov); | ||
2516 | 2552 | ||
2517 | #endif /* CONFIG_PCI_IOV */ | 2553 | #endif /* CONFIG_PCI_IOV */ |
2518 | 2554 | ||
2555 | /* | ||
2556 | * This is a quirk for the Ricoh MMC controller found as a part of | ||
2557 | * some mulifunction chips. | ||
2558 | |||
2559 | * This is very similiar and based on the ricoh_mmc driver written by | ||
2560 | * Philip Langdale. Thank you for these magic sequences. | ||
2561 | * | ||
2562 | * These chips implement the four main memory card controllers (SD, MMC, MS, xD) | ||
2563 | * and one or both of cardbus or firewire. | ||
2564 | * | ||
2565 | * It happens that they implement SD and MMC | ||
2566 | * support as separate controllers (and PCI functions). The linux SDHCI | ||
2567 | * driver supports MMC cards but the chip detects MMC cards in hardware | ||
2568 | * and directs them to the MMC controller - so the SDHCI driver never sees | ||
2569 | * them. | ||
2570 | * | ||
2571 | * To get around this, we must disable the useless MMC controller. | ||
2572 | * At that point, the SDHCI controller will start seeing them | ||
2573 | * It seems to be the case that the relevant PCI registers to deactivate the | ||
2574 | * MMC controller live on PCI function 0, which might be the cardbus controller | ||
2575 | * or the firewire controller, depending on the particular chip in question | ||
2576 | * | ||
2577 | * This has to be done early, because as soon as we disable the MMC controller | ||
2578 | * other pci functions shift up one level, e.g. function #2 becomes function | ||
2579 | * #1, and this will confuse the pci core. | ||
2580 | */ | ||
2581 | |||
2582 | #ifdef CONFIG_MMC_RICOH_MMC | ||
2583 | static void ricoh_mmc_fixup_rl5c476(struct pci_dev *dev) | ||
2584 | { | ||
2585 | /* disable via cardbus interface */ | ||
2586 | u8 write_enable; | ||
2587 | u8 write_target; | ||
2588 | u8 disable; | ||
2589 | |||
2590 | /* disable must be done via function #0 */ | ||
2591 | if (PCI_FUNC(dev->devfn)) | ||
2592 | return; | ||
2593 | |||
2594 | pci_read_config_byte(dev, 0xB7, &disable); | ||
2595 | if (disable & 0x02) | ||
2596 | return; | ||
2597 | |||
2598 | pci_read_config_byte(dev, 0x8E, &write_enable); | ||
2599 | pci_write_config_byte(dev, 0x8E, 0xAA); | ||
2600 | pci_read_config_byte(dev, 0x8D, &write_target); | ||
2601 | pci_write_config_byte(dev, 0x8D, 0xB7); | ||
2602 | pci_write_config_byte(dev, 0xB7, disable | 0x02); | ||
2603 | pci_write_config_byte(dev, 0x8E, write_enable); | ||
2604 | pci_write_config_byte(dev, 0x8D, write_target); | ||
2605 | |||
2606 | dev_notice(&dev->dev, "proprietary Ricoh MMC controller disabled (via cardbus function)\n"); | ||
2607 | dev_notice(&dev->dev, "MMC cards are now supported by standard SDHCI controller\n"); | ||
2608 | } | ||
2609 | DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_RICOH, PCI_DEVICE_ID_RICOH_RL5C476, ricoh_mmc_fixup_rl5c476); | ||
2610 | DECLARE_PCI_FIXUP_RESUME_EARLY(PCI_VENDOR_ID_RICOH, PCI_DEVICE_ID_RICOH_RL5C476, ricoh_mmc_fixup_rl5c476); | ||
2611 | |||
2612 | static void ricoh_mmc_fixup_r5c832(struct pci_dev *dev) | ||
2613 | { | ||
2614 | /* disable via firewire interface */ | ||
2615 | u8 write_enable; | ||
2616 | u8 disable; | ||
2617 | |||
2618 | /* disable must be done via function #0 */ | ||
2619 | if (PCI_FUNC(dev->devfn)) | ||
2620 | return; | ||
2621 | |||
2622 | pci_read_config_byte(dev, 0xCB, &disable); | ||
2623 | |||
2624 | if (disable & 0x02) | ||
2625 | return; | ||
2626 | |||
2627 | pci_read_config_byte(dev, 0xCA, &write_enable); | ||
2628 | pci_write_config_byte(dev, 0xCA, 0x57); | ||
2629 | pci_write_config_byte(dev, 0xCB, disable | 0x02); | ||
2630 | pci_write_config_byte(dev, 0xCA, write_enable); | ||
2631 | |||
2632 | dev_notice(&dev->dev, "proprietary Ricoh MMC controller disabled (via firewire function)\n"); | ||
2633 | dev_notice(&dev->dev, "MMC cards are now supported by standard SDHCI controller\n"); | ||
2634 | } | ||
2635 | DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_RICOH, PCI_DEVICE_ID_RICOH_R5C832, ricoh_mmc_fixup_r5c832); | ||
2636 | DECLARE_PCI_FIXUP_RESUME_EARLY(PCI_VENDOR_ID_RICOH, PCI_DEVICE_ID_RICOH_R5C832, ricoh_mmc_fixup_r5c832); | ||
2637 | #endif /*CONFIG_MMC_RICOH_MMC*/ | ||
2638 | |||
2639 | |||
2519 | static void pci_do_fixups(struct pci_dev *dev, struct pci_fixup *f, | 2640 | static void pci_do_fixups(struct pci_dev *dev, struct pci_fixup *f, |
2520 | struct pci_fixup *end) | 2641 | struct pci_fixup *end) |
2521 | { | 2642 | { |
@@ -2591,20 +2712,115 @@ void pci_fixup_device(enum pci_fixup_pass pass, struct pci_dev *dev) | |||
2591 | } | 2712 | } |
2592 | pci_do_fixups(dev, start, end); | 2713 | pci_do_fixups(dev, start, end); |
2593 | } | 2714 | } |
2715 | EXPORT_SYMBOL(pci_fixup_device); | ||
2594 | 2716 | ||
2595 | static int __init pci_apply_final_quirks(void) | 2717 | static int __init pci_apply_final_quirks(void) |
2596 | { | 2718 | { |
2597 | struct pci_dev *dev = NULL; | 2719 | struct pci_dev *dev = NULL; |
2720 | u8 cls = 0; | ||
2721 | u8 tmp; | ||
2722 | |||
2723 | if (pci_cache_line_size) | ||
2724 | printk(KERN_DEBUG "PCI: CLS %u bytes\n", | ||
2725 | pci_cache_line_size << 2); | ||
2598 | 2726 | ||
2599 | while ((dev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL) { | 2727 | while ((dev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL) { |
2600 | pci_fixup_device(pci_fixup_final, dev); | 2728 | pci_fixup_device(pci_fixup_final, dev); |
2729 | /* | ||
2730 | * If arch hasn't set it explicitly yet, use the CLS | ||
2731 | * value shared by all PCI devices. If there's a | ||
2732 | * mismatch, fall back to the default value. | ||
2733 | */ | ||
2734 | if (!pci_cache_line_size) { | ||
2735 | pci_read_config_byte(dev, PCI_CACHE_LINE_SIZE, &tmp); | ||
2736 | if (!cls) | ||
2737 | cls = tmp; | ||
2738 | if (!tmp || cls == tmp) | ||
2739 | continue; | ||
2740 | |||
2741 | printk(KERN_DEBUG "PCI: CLS mismatch (%u != %u), " | ||
2742 | "using %u bytes\n", cls << 2, tmp << 2, | ||
2743 | pci_dfl_cache_line_size << 2); | ||
2744 | pci_cache_line_size = pci_dfl_cache_line_size; | ||
2745 | } | ||
2746 | } | ||
2747 | if (!pci_cache_line_size) { | ||
2748 | printk(KERN_DEBUG "PCI: CLS %u bytes, default %u\n", | ||
2749 | cls << 2, pci_dfl_cache_line_size << 2); | ||
2750 | pci_cache_line_size = cls ? cls : pci_dfl_cache_line_size; | ||
2601 | } | 2751 | } |
2602 | 2752 | ||
2603 | return 0; | 2753 | return 0; |
2604 | } | 2754 | } |
2605 | 2755 | ||
2606 | fs_initcall_sync(pci_apply_final_quirks); | 2756 | fs_initcall_sync(pci_apply_final_quirks); |
2607 | #else | 2757 | |
2608 | void pci_fixup_device(enum pci_fixup_pass pass, struct pci_dev *dev) {} | 2758 | /* |
2609 | #endif | 2759 | * Followings are device-specific reset methods which can be used to |
2610 | EXPORT_SYMBOL(pci_fixup_device); | 2760 | * reset a single function if other methods (e.g. FLR, PM D0->D3) are |
2761 | * not available. | ||
2762 | */ | ||
2763 | static int reset_intel_generic_dev(struct pci_dev *dev, int probe) | ||
2764 | { | ||
2765 | int pos; | ||
2766 | |||
2767 | /* only implement PCI_CLASS_SERIAL_USB at present */ | ||
2768 | if (dev->class == PCI_CLASS_SERIAL_USB) { | ||
2769 | pos = pci_find_capability(dev, PCI_CAP_ID_VNDR); | ||
2770 | if (!pos) | ||
2771 | return -ENOTTY; | ||
2772 | |||
2773 | if (probe) | ||
2774 | return 0; | ||
2775 | |||
2776 | pci_write_config_byte(dev, pos + 0x4, 1); | ||
2777 | msleep(100); | ||
2778 | |||
2779 | return 0; | ||
2780 | } else { | ||
2781 | return -ENOTTY; | ||
2782 | } | ||
2783 | } | ||
2784 | |||
2785 | static int reset_intel_82599_sfp_virtfn(struct pci_dev *dev, int probe) | ||
2786 | { | ||
2787 | int pos; | ||
2788 | |||
2789 | pos = pci_find_capability(dev, PCI_CAP_ID_EXP); | ||
2790 | if (!pos) | ||
2791 | return -ENOTTY; | ||
2792 | |||
2793 | if (probe) | ||
2794 | return 0; | ||
2795 | |||
2796 | pci_write_config_word(dev, pos + PCI_EXP_DEVCTL, | ||
2797 | PCI_EXP_DEVCTL_BCR_FLR); | ||
2798 | msleep(100); | ||
2799 | |||
2800 | return 0; | ||
2801 | } | ||
2802 | |||
2803 | #define PCI_DEVICE_ID_INTEL_82599_SFP_VF 0x10ed | ||
2804 | |||
2805 | static const struct pci_dev_reset_methods pci_dev_reset_methods[] = { | ||
2806 | { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82599_SFP_VF, | ||
2807 | reset_intel_82599_sfp_virtfn }, | ||
2808 | { PCI_VENDOR_ID_INTEL, PCI_ANY_ID, | ||
2809 | reset_intel_generic_dev }, | ||
2810 | { 0 } | ||
2811 | }; | ||
2812 | |||
2813 | int pci_dev_specific_reset(struct pci_dev *dev, int probe) | ||
2814 | { | ||
2815 | const struct pci_dev_reset_methods *i; | ||
2816 | |||
2817 | for (i = pci_dev_reset_methods; i->reset; i++) { | ||
2818 | if ((i->vendor == dev->vendor || | ||
2819 | i->vendor == (u16)PCI_ANY_ID) && | ||
2820 | (i->device == dev->device || | ||
2821 | i->device == (u16)PCI_ANY_ID)) | ||
2822 | return i->reset(dev, probe); | ||
2823 | } | ||
2824 | |||
2825 | return -ENOTTY; | ||
2826 | } | ||