PCI: Use function 0 VPD for identical functions, regular VPD for others
932c435cab
("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:932c435cab
("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
This commit is contained in:
parent
9d9240756e
commit
da2d03ea27
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Reference in New Issue