diff options
author | Bjorn Helgaas <bhelgaas@google.com> | 2023-08-29 11:03:50 -0500 |
---|---|---|
committer | Bjorn Helgaas <bhelgaas@google.com> | 2023-08-29 11:03:50 -0500 |
commit | 3c298b840c196af2f738471ccf0ca40f7dae921a (patch) | |
tree | 3c412f6837398f112b279dd5ea94d6357cce4c21 /drivers/pci/vpd.c | |
parent | 93a3241d615eae69b09be1fb6b309ad116ca03ac (diff) | |
parent | d3fcd7360338358aa0036bec6d2cf0e37a0ca624 (diff) |
Merge branch 'pci/vpd'
- Ensure device is accessible before VPD access via sysfs (Alex Williamson)
- Ensure device doesn't go to a low-power state while we're polling for PME
(Alex Williamson)
* pci/vpd:
PCI: Fix runtime PM race with PME polling
PCI/VPD: Add runtime power management to sysfs interface
Diffstat (limited to 'drivers/pci/vpd.c')
-rw-r--r-- | drivers/pci/vpd.c | 34 |
1 files changed, 32 insertions, 2 deletions
diff --git a/drivers/pci/vpd.c b/drivers/pci/vpd.c index a4fc4d0690fe..485a642b9304 100644 --- a/drivers/pci/vpd.c +++ b/drivers/pci/vpd.c @@ -275,8 +275,23 @@ static ssize_t vpd_read(struct file *filp, struct kobject *kobj, size_t count) { struct pci_dev *dev = to_pci_dev(kobj_to_dev(kobj)); + struct pci_dev *vpd_dev = dev; + ssize_t ret; + + if (dev->dev_flags & PCI_DEV_FLAGS_VPD_REF_F0) { + vpd_dev = pci_get_func0_dev(dev); + if (!vpd_dev) + return -ENODEV; + } + + pci_config_pm_runtime_get(vpd_dev); + ret = pci_read_vpd(vpd_dev, off, count, buf); + pci_config_pm_runtime_put(vpd_dev); + + if (dev->dev_flags & PCI_DEV_FLAGS_VPD_REF_F0) + pci_dev_put(vpd_dev); - return pci_read_vpd(dev, off, count, buf); + return ret; } static ssize_t vpd_write(struct file *filp, struct kobject *kobj, @@ -284,8 +299,23 @@ static ssize_t vpd_write(struct file *filp, struct kobject *kobj, size_t count) { struct pci_dev *dev = to_pci_dev(kobj_to_dev(kobj)); + struct pci_dev *vpd_dev = dev; + ssize_t ret; + + if (dev->dev_flags & PCI_DEV_FLAGS_VPD_REF_F0) { + vpd_dev = pci_get_func0_dev(dev); + if (!vpd_dev) + return -ENODEV; + } + + pci_config_pm_runtime_get(vpd_dev); + ret = pci_write_vpd(vpd_dev, off, count, buf); + pci_config_pm_runtime_put(vpd_dev); + + if (dev->dev_flags & PCI_DEV_FLAGS_VPD_REF_F0) + pci_dev_put(vpd_dev); - return pci_write_vpd(dev, off, count, buf); + return ret; } static BIN_ATTR(vpd, 0600, vpd_read, vpd_write, 0); |