From: Yu Zhao Date: Fri, 3 Apr 2009 07:18:11 +0000 (+0800) Subject: PCI: SR-IOV quirk for Intel 82576 NIC X-Git-Url: http://pilppa.com/gitweb/?a=commitdiff_plain;h=7eb93b175d4de9438a4b0af3a94a112cb5266944;p=linux-2.6-omap-h63xx.git PCI: SR-IOV quirk for Intel 82576 NIC If BIOS doesn't allocate resources for the SR-IOV BARs, zero the Flash BAR and program the SR-IOV BARs to use the old Flash Memory Space. Please refer to Intel 82576 Gigabit Ethernet Controller Datasheet section 7.9.2.14.2 for details. http://download.intel.com/design/network/datashts/82576_Datasheet.pdf Signed-off-by: Yu Zhao Signed-off-by: Jesse Barnes --- diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c index 9b2f0d96900..51011a24589 100644 --- a/drivers/pci/quirks.c +++ b/drivers/pci/quirks.c @@ -2411,6 +2411,54 @@ DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_ATI, 0x4375, #endif /* CONFIG_PCI_MSI */ +#ifdef CONFIG_PCI_IOV + +/* + * For Intel 82576 SR-IOV NIC, if BIOS doesn't allocate resources for the + * SR-IOV BARs, zero the Flash BAR and program the SR-IOV BARs to use the + * old Flash Memory Space. + */ +static void __devinit quirk_i82576_sriov(struct pci_dev *dev) +{ + int pos, flags; + u32 bar, start, size; + + if (PAGE_SIZE > 0x10000) + return; + + flags = pci_resource_flags(dev, 0); + if ((flags & PCI_BASE_ADDRESS_SPACE) != + PCI_BASE_ADDRESS_SPACE_MEMORY || + (flags & PCI_BASE_ADDRESS_MEM_TYPE_MASK) != + PCI_BASE_ADDRESS_MEM_TYPE_32) + return; + + pos = pci_find_ext_capability(dev, PCI_EXT_CAP_ID_SRIOV); + if (!pos) + return; + + pci_read_config_dword(dev, pos + PCI_SRIOV_BAR, &bar); + if (bar & PCI_BASE_ADDRESS_MEM_MASK) + return; + + start = pci_resource_start(dev, 1); + size = pci_resource_len(dev, 1); + if (!start || size != 0x400000 || start & (size - 1)) + return; + + pci_resource_flags(dev, 1) = 0; + pci_write_config_dword(dev, PCI_BASE_ADDRESS_1, 0); + pci_write_config_dword(dev, pos + PCI_SRIOV_BAR, start); + pci_write_config_dword(dev, pos + PCI_SRIOV_BAR + 12, start + size / 2); + + dev_info(&dev->dev, "use Flash Memory Space for SR-IOV BARs\n"); +} +DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x10c9, quirk_i82576_sriov); +DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x10e6, quirk_i82576_sriov); +DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x10e7, quirk_i82576_sriov); + +#endif /* CONFIG_PCI_IOV */ + static void pci_do_fixups(struct pci_dev *dev, struct pci_fixup *f, struct pci_fixup *end) {