Commit da2d03ea authored by Alex Williamson's avatar Alex Williamson Committed by Bjorn Helgaas

PCI: Use function 0 VPD for identical functions, regular VPD for others

932c435c ("PCI: Add dev_flags bit to access VPD through function 0")
added PCI_DEV_FLAGS_VPD_REF_F0.  Previously, we set the flag on every
non-zero function of quirked devices.  If a function turned out to be
different from function 0, i.e., it had a different class, vendor ID, or
device ID, the flag remained set but we didn't make VPD accessible at all.

Flip this around so we only set PCI_DEV_FLAGS_VPD_REF_F0 for functions that
are identical to function 0, and allow regular VPD access for any other

[bhelgaas: changelog, stable tag]
Fixes: 932c435c ("PCI: Add dev_flags bit to access VPD through function 0")
Signed-off-by: 's avatarAlex Williamson <>
Signed-off-by: 's avatarBjorn Helgaas <>
Acked-by: 's avatarMyron Stowe <>
Acked-by: 's avatarMark Rustad <>
parent 9d924075
......@@ -475,23 +475,6 @@ static const struct pci_vpd_ops pci_vpd_f0_ops = {
.release = pci_vpd_pci22_release,
static int pci_vpd_f0_dev_check(struct pci_dev *dev)
struct pci_dev *tdev = pci_get_slot(dev->bus,
PCI_DEVFN(PCI_SLOT(dev->devfn), 0));
int ret = 0;
if (!tdev)
return -ENODEV;
if (!tdev->vpd || !tdev->multifunction ||
dev->class != tdev->class || dev->vendor != tdev->vendor ||
dev->device != tdev->device)
ret = -ENODEV;
return ret;
int pci_vpd_pci22_init(struct pci_dev *dev)
struct pci_vpd_pci22 *vpd;
......@@ -500,12 +483,7 @@ int pci_vpd_pci22_init(struct pci_dev *dev)
cap = pci_find_capability(dev, PCI_CAP_ID_VPD);
if (!cap)
return -ENODEV;
if (dev->dev_flags & PCI_DEV_FLAGS_VPD_REF_F0) {
int ret = pci_vpd_f0_dev_check(dev);
if (ret)
return ret;
vpd = kzalloc(sizeof(*vpd), GFP_ATOMIC);
if (!vpd)
return -ENOMEM;
......@@ -1907,11 +1907,27 @@ static void quirk_netmos(struct pci_dev *dev)
* Quirk non-zero PCI functions to route VPD access through function 0 for
* devices that share VPD resources between functions. The functions are
* expected to be identical devices.
static void quirk_f0_vpd_link(struct pci_dev *dev)
if (!dev->multifunction || !PCI_FUNC(dev->devfn))
struct pci_dev *f0;
if (!PCI_FUNC(dev->devfn))
dev->dev_flags |= PCI_DEV_FLAGS_VPD_REF_F0;
f0 = pci_get_slot(dev->bus, PCI_DEVFN(PCI_SLOT(dev->devfn), 0));
if (!f0)
if (f0->vpd && dev->class == f0->class &&
dev->vendor == f0->vendor && dev->device == f0->device)
dev->dev_flags |= PCI_DEV_FLAGS_VPD_REF_F0;
PCI_CLASS_NETWORK_ETHERNET, 8, quirk_f0_vpd_link);
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment