[PATCH 3.2 02/52] PCI: Use function 0 VPD for identical functions, regular VPD for others

From: Ben Hutchings
Date: Tue Nov 24 2015 - 17:47:37 EST


3.2.74-rc1 review patch. If anyone has any objections, please let me know.

------------------

From: Alex Williamson <alex.williamson@xxxxxxxxxx>

commit da2d03ea27f6ed9d2005a67b20dd021ddacf1e4d upstream.

932c435caba8 ("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
functions.

[bhelgaas: changelog, stable tag]
Fixes: 932c435caba8 ("PCI: Add dev_flags bit to access VPD through function 0")
Signed-off-by: Alex Williamson <alex.williamson@xxxxxxxxxx>
Signed-off-by: Bjorn Helgaas <helgaas@xxxxxxxxxx>
Acked-by: Myron Stowe <myron.stowe@xxxxxxxxxx>
Acked-by: Mark Rustad <mark.d.rustad@xxxxxxxxx>
[bwh: Backported to 3.2: adjust context]
Signed-off-by: Ben Hutchings <ben@xxxxxxxxxxxxxxx>
---
drivers/pci/access.c | 22 ----------------------
drivers/pci/quirks.c | 20 ++++++++++++++++++--
2 files changed, 18 insertions(+), 24 deletions(-)

--- a/drivers/pci/access.c
+++ b/drivers/pci/access.c
@@ -391,23 +391,6 @@ static const struct pci_vpd_ops pci_vpd_
.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;
-
- pci_dev_put(tdev);
- return ret;
-}
-
int pci_vpd_pci22_init(struct pci_dev *dev)
{
struct pci_vpd_pci22 *vpd;
@@ -416,12 +399,7 @@ int pci_vpd_pci22_init(struct pci_dev *d
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;
--- a/drivers/pci/quirks.c
+++ b/drivers/pci/quirks.c
@@ -1941,12 +1941,28 @@ static void __devinit quirk_netmos(struc
}
DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_NETMOS, PCI_ANY_ID, quirk_netmos);

+/*
+ * 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)
{
+ struct pci_dev *f0;
+
if ((dev->class >> 8) != PCI_CLASS_NETWORK_ETHERNET ||
- !dev->multifunction || !PCI_FUNC(dev->devfn))
+ !PCI_FUNC(dev->devfn))
+ return;
+
+ f0 = pci_get_slot(dev->bus, PCI_DEVFN(PCI_SLOT(dev->devfn), 0));
+ if (!f0)
return;
- dev->dev_flags |= PCI_DEV_FLAGS_VPD_REF_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_dev_put(f0);
}
DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_INTEL, PCI_ANY_ID, quirk_f0_vpd_link);


--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/