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,
|
.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)
|
int pci_vpd_pci22_init(struct pci_dev *dev)
|
||||||
{
|
{
|
||||||
struct pci_vpd_pci22 *vpd;
|
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);
|
cap = pci_find_capability(dev, PCI_CAP_ID_VPD);
|
||||||
if (!cap)
|
if (!cap)
|
||||||
return -ENODEV;
|
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);
|
vpd = kzalloc(sizeof(*vpd), GFP_ATOMIC);
|
||||||
if (!vpd)
|
if (!vpd)
|
||||||
return -ENOMEM;
|
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,
|
DECLARE_PCI_FIXUP_CLASS_HEADER(PCI_VENDOR_ID_NETMOS, PCI_ANY_ID,
|
||||||
PCI_CLASS_COMMUNICATION_SERIAL, 8, quirk_netmos);
|
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)
|
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;
|
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;
|
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,
|
DECLARE_PCI_FIXUP_CLASS_EARLY(PCI_VENDOR_ID_INTEL, PCI_ANY_ID,
|
||||||
PCI_CLASS_NETWORK_ETHERNET, 8, quirk_f0_vpd_link);
|
PCI_CLASS_NETWORK_ETHERNET, 8, quirk_f0_vpd_link);
|
||||||
|
|
Loading…
Reference in New Issue