Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

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

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
functions.

[bhelgaas: changelog, stable tag]
Fixes: 932c435c ("PCI: Add dev_flags bit to access VPD through function 0")
Signed-off-by: default avatarAlex Williamson <alex.williamson@redhat.com>
Signed-off-by: default avatarBjorn Helgaas <helgaas@kernel.org>
Acked-by: default avatarMyron Stowe <myron.stowe@redhat.com>
Acked-by: default avatarMark Rustad <mark.d.rustad@intel.com>
CC: stable@vger.kernel.org
parent 9d924075
Loading
Loading
Loading
Loading
+0 −22
Original line number Diff line number Diff line
@@ -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;

	pci_dev_put(tdev);
	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;
+18 −2
Original line number Diff line number Diff line
@@ -1907,11 +1907,27 @@ static void quirk_netmos(struct pci_dev *dev)
DECLARE_PCI_FIXUP_CLASS_HEADER(PCI_VENDOR_ID_NETMOS, PCI_ANY_ID,
			 PCI_CLASS_COMMUNICATION_SERIAL, 8, 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)
{
	if (!dev->multifunction || !PCI_FUNC(dev->devfn))
	struct pci_dev *f0;

	if (!PCI_FUNC(dev->devfn))
		return;

	f0 = pci_get_slot(dev->bus, PCI_DEVFN(PCI_SLOT(dev->devfn), 0));
	if (!f0)
		return;

	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_CLASS_EARLY(PCI_VENDOR_ID_INTEL, PCI_ANY_ID,
			      PCI_CLASS_NETWORK_ETHERNET, 8, quirk_f0_vpd_link);