diff options
Diffstat (limited to 'drivers/pci/quirks.c')
-rw-r--r-- | drivers/pci/quirks.c | 62 |
1 files changed, 57 insertions, 5 deletions
diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c index 9b2f0d96900d..0254741bece0 100644 --- a/drivers/pci/quirks.c +++ b/drivers/pci/quirks.c | |||
@@ -36,17 +36,18 @@ EXPORT_SYMBOL(pcie_mch_quirk); | |||
36 | 36 | ||
37 | #ifdef CONFIG_PCI_QUIRKS | 37 | #ifdef CONFIG_PCI_QUIRKS |
38 | /* | 38 | /* |
39 | * This quirk function disables the device and releases resources | 39 | * This quirk function disables memory decoding and releases memory resources |
40 | * which is specified by kernel's boot parameter 'pci=resource_alignment='. | 40 | * of the device specified by kernel's boot parameter 'pci=resource_alignment='. |
41 | * It also rounds up size to specified alignment. | 41 | * It also rounds up size to specified alignment. |
42 | * Later on, the kernel will assign page-aligned memory resource back | 42 | * Later on, the kernel will assign page-aligned memory resource back |
43 | * to that device. | 43 | * to the device. |
44 | */ | 44 | */ |
45 | static void __devinit quirk_resource_alignment(struct pci_dev *dev) | 45 | static void __devinit quirk_resource_alignment(struct pci_dev *dev) |
46 | { | 46 | { |
47 | int i; | 47 | int i; |
48 | struct resource *r; | 48 | struct resource *r; |
49 | resource_size_t align, size; | 49 | resource_size_t align, size; |
50 | u16 command; | ||
50 | 51 | ||
51 | if (!pci_is_reassigndev(dev)) | 52 | if (!pci_is_reassigndev(dev)) |
52 | return; | 53 | return; |
@@ -58,8 +59,11 @@ static void __devinit quirk_resource_alignment(struct pci_dev *dev) | |||
58 | return; | 59 | return; |
59 | } | 60 | } |
60 | 61 | ||
61 | dev_info(&dev->dev, "Disabling device and release resources.\n"); | 62 | dev_info(&dev->dev, |
62 | pci_disable_device(dev); | 63 | "Disabling memory decoding and releasing memory resources.\n"); |
64 | pci_read_config_word(dev, PCI_COMMAND, &command); | ||
65 | command &= ~PCI_COMMAND_MEMORY; | ||
66 | pci_write_config_word(dev, PCI_COMMAND, command); | ||
63 | 67 | ||
64 | align = pci_specified_resource_alignment(dev); | 68 | align = pci_specified_resource_alignment(dev); |
65 | for (i=0; i < PCI_BRIDGE_RESOURCES; i++) { | 69 | for (i=0; i < PCI_BRIDGE_RESOURCES; i++) { |
@@ -2411,6 +2415,54 @@ DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_ATI, 0x4375, | |||
2411 | 2415 | ||
2412 | #endif /* CONFIG_PCI_MSI */ | 2416 | #endif /* CONFIG_PCI_MSI */ |
2413 | 2417 | ||
2418 | #ifdef CONFIG_PCI_IOV | ||
2419 | |||
2420 | /* | ||
2421 | * For Intel 82576 SR-IOV NIC, if BIOS doesn't allocate resources for the | ||
2422 | * SR-IOV BARs, zero the Flash BAR and program the SR-IOV BARs to use the | ||
2423 | * old Flash Memory Space. | ||
2424 | */ | ||
2425 | static void __devinit quirk_i82576_sriov(struct pci_dev *dev) | ||
2426 | { | ||
2427 | int pos, flags; | ||
2428 | u32 bar, start, size; | ||
2429 | |||
2430 | if (PAGE_SIZE > 0x10000) | ||
2431 | return; | ||
2432 | |||
2433 | flags = pci_resource_flags(dev, 0); | ||
2434 | if ((flags & PCI_BASE_ADDRESS_SPACE) != | ||
2435 | PCI_BASE_ADDRESS_SPACE_MEMORY || | ||
2436 | (flags & PCI_BASE_ADDRESS_MEM_TYPE_MASK) != | ||
2437 | PCI_BASE_ADDRESS_MEM_TYPE_32) | ||
2438 | return; | ||
2439 | |||
2440 | pos = pci_find_ext_capability(dev, PCI_EXT_CAP_ID_SRIOV); | ||
2441 | if (!pos) | ||
2442 | return; | ||
2443 | |||
2444 | pci_read_config_dword(dev, pos + PCI_SRIOV_BAR, &bar); | ||
2445 | if (bar & PCI_BASE_ADDRESS_MEM_MASK) | ||
2446 | return; | ||
2447 | |||
2448 | start = pci_resource_start(dev, 1); | ||
2449 | size = pci_resource_len(dev, 1); | ||
2450 | if (!start || size != 0x400000 || start & (size - 1)) | ||
2451 | return; | ||
2452 | |||
2453 | pci_resource_flags(dev, 1) = 0; | ||
2454 | pci_write_config_dword(dev, PCI_BASE_ADDRESS_1, 0); | ||
2455 | pci_write_config_dword(dev, pos + PCI_SRIOV_BAR, start); | ||
2456 | pci_write_config_dword(dev, pos + PCI_SRIOV_BAR + 12, start + size / 2); | ||
2457 | |||
2458 | dev_info(&dev->dev, "use Flash Memory Space for SR-IOV BARs\n"); | ||
2459 | } | ||
2460 | DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x10c9, quirk_i82576_sriov); | ||
2461 | DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x10e6, quirk_i82576_sriov); | ||
2462 | DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x10e7, quirk_i82576_sriov); | ||
2463 | |||
2464 | #endif /* CONFIG_PCI_IOV */ | ||
2465 | |||
2414 | static void pci_do_fixups(struct pci_dev *dev, struct pci_fixup *f, | 2466 | static void pci_do_fixups(struct pci_dev *dev, struct pci_fixup *f, |
2415 | struct pci_fixup *end) | 2467 | struct pci_fixup *end) |
2416 | { | 2468 | { |