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.c62
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 */
45static void __devinit quirk_resource_alignment(struct pci_dev *dev) 45static 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 */
2425static 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}
2460DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x10c9, quirk_i82576_sriov);
2461DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x10e6, quirk_i82576_sriov);
2462DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x10e7, quirk_i82576_sriov);
2463
2464#endif /* CONFIG_PCI_IOV */
2465
2414static void pci_do_fixups(struct pci_dev *dev, struct pci_fixup *f, 2466static void pci_do_fixups(struct pci_dev *dev, struct pci_fixup *f,
2415 struct pci_fixup *end) 2467 struct pci_fixup *end)
2416{ 2468{