ia64/linux-2.6.18-xen.hg

changeset 839:3d4c92b97556

PCI: add a SR-IOV quirk for Intel 82576 NIC

If BIOS doesn't allocate resources for VF BARs, zero Flash BAR and
program VF 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 <yu.zhao@intel.com>
author Keir Fraser <keir.fraser@citrix.com>
date Thu Mar 19 10:20:59 2009 +0000 (2009-03-19)
parents 6a0fee3b8b7d
children 5ad6b350e4ab
files drivers/pci/quirks.c
line diff
     1.1 --- a/drivers/pci/quirks.c	Thu Mar 19 10:07:31 2009 +0000
     1.2 +++ b/drivers/pci/quirks.c	Thu Mar 19 10:20:59 2009 +0000
     1.3 @@ -1747,3 +1747,60 @@ EXPORT_SYMBOL(pcie_mch_quirk);
     1.4  #ifdef CONFIG_HOTPLUG
     1.5  EXPORT_SYMBOL(pci_fixup_device);
     1.6  #endif
     1.7 +
     1.8 +#ifdef CONFIG_PCI_IOV
     1.9 +/*
    1.10 + * If BIOS doesn't allocate resources for SR-IOV BARs, zero Flash BAR
    1.11 + * and program SR-IOV BARs to use the old Flash Memory Space.
    1.12 + * PCI subsystem may try to allocate Memory Space for Flash BAR later,
    1.13 + * that's why we don't clear Flash BAR flags.
    1.14 + */
    1.15 +static void __devinit intel_82576_quirk(struct pci_dev *dev)
    1.16 +{
    1.17 +	int i, flags;
    1.18 +	u32 bar, start, size;
    1.19 +
    1.20 +	if (PAGE_SIZE > 0x10000)
    1.21 +		return;
    1.22 +
    1.23 +	if (pci_read_config_dword(dev, 0x184, &bar))
    1.24 +		return;
    1.25 +
    1.26 +	if (bar & PCI_BASE_ADDRESS_MEM_MASK)
    1.27 +		return;
    1.28 +
    1.29 +	i = 1;
    1.30 +	flags = pci_resource_flags(dev, i);
    1.31 +	if ((flags & PCI_BASE_ADDRESS_SPACE) ==
    1.32 +			PCI_BASE_ADDRESS_SPACE_MEMORY &&
    1.33 +	    (flags & PCI_BASE_ADDRESS_MEM_TYPE_MASK) ==
    1.34 +			PCI_BASE_ADDRESS_MEM_TYPE_32)
    1.35 +		goto found;
    1.36 +
    1.37 +	i = 2;
    1.38 +	flags = pci_resource_flags(dev, i);
    1.39 +	if ((flags & PCI_BASE_ADDRESS_SPACE) ==
    1.40 +			PCI_BASE_ADDRESS_SPACE_MEMORY &&
    1.41 +	    (flags & PCI_BASE_ADDRESS_MEM_TYPE_MASK) ==
    1.42 +			PCI_BASE_ADDRESS_MEM_TYPE_64)
    1.43 +		goto found;
    1.44 +
    1.45 +	return;
    1.46 +found:
    1.47 +	start = pci_resource_start(dev, i);
    1.48 +	size = pci_resource_len(dev, i);
    1.49 +	if (!start || size != 0x400000 || start & (size - 1))
    1.50 +		return;
    1.51 +
    1.52 +	pci_write_config_dword(dev, 0x10 + i * 4, 0);
    1.53 +	pci_resource_start(dev, i) = 0;
    1.54 +	pci_resource_end(dev, i) = size - 1;
    1.55 +	pci_write_config_dword(dev, 0x184, start);
    1.56 +	pci_write_config_dword(dev, 0x190, start + size / 2);
    1.57 +
    1.58 +	dev_info(&dev->dev, "use Flash Memory Space for SR-IOV BARs\n");
    1.59 +}
    1.60 +DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x10c9, intel_82576_quirk);
    1.61 +DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x10e6, intel_82576_quirk);
    1.62 +DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x10e7, intel_82576_quirk);
    1.63 +#endif /* CONFIG_PCI_IOV */