Skip to content

Commit

Permalink
PCI: Use function 0 VPD for identical functions, regular VPD for others
Browse files Browse the repository at this point in the history
932c435 ("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: 932c435 ("PCI: Add dev_flags bit to access VPD through function 0")
Signed-off-by: Alex Williamson <alex.williamson@redhat.com>
Signed-off-by: Bjorn Helgaas <helgaas@kernel.org>
Acked-by: Myron Stowe <myron.stowe@redhat.com>
Acked-by: Mark Rustad <mark.d.rustad@intel.com>
CC: stable@vger.kernel.org
  • Loading branch information
Alex Williamson authored and Bjorn Helgaas committed Sep 24, 2015
1 parent 9d92407 commit da2d03e
Show file tree
Hide file tree
Showing 2 changed files with 18 additions and 24 deletions.
22 changes: 0 additions & 22 deletions drivers/pci/access.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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;
Expand Down
20 changes: 18 additions & 2 deletions drivers/pci/quirks.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
dev->dev_flags |= PCI_DEV_FLAGS_VPD_REF_F0;

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);
Expand Down

0 comments on commit da2d03e

Please sign in to comment.