diff options
author | Bjorn Helgaas <bhelgaas@google.com> | 2024-11-25 13:40:54 -0600 |
---|---|---|
committer | Bjorn Helgaas <bhelgaas@google.com> | 2024-11-25 13:40:54 -0600 |
commit | d985e2beb9cac53ff190883f2b7ae3085f0586f6 (patch) | |
tree | cc673180fb8f8b66f99ff457cd45a734f4aac736 /drivers | |
parent | ce1deca962e3f67442dba834c8e1ba3629db6159 (diff) | |
parent | a3151e6daaec171b7d46ac79170ec420ad874cae (diff) | |
download | lwn-d985e2beb9cac53ff190883f2b7ae3085f0586f6.tar.gz lwn-d985e2beb9cac53ff190883f2b7ae3085f0586f6.zip |
Merge branch 'pci/reset'
- Add sysfs 'reset_subordinate' to reset hierarchy below bridge (Keith
Busch)
- Warn if we reset a running device where driver didn't register
pci_error_handlers notification callbacks (Keith Busch)
* pci/reset:
PCI: Warn if a running device is unaware of reset
PCI: Add 'reset_subordinate' to reset hierarchy below bridge
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/pci/pci-sysfs.c | 26 | ||||
-rw-r--r-- | drivers/pci/pci.c | 6 | ||||
-rw-r--r-- | drivers/pci/pci.h | 1 |
3 files changed, 32 insertions, 1 deletions
diff --git a/drivers/pci/pci-sysfs.c b/drivers/pci/pci-sysfs.c index 5d0f4db1cab7..3e5a117f5b5d 100644 --- a/drivers/pci/pci-sysfs.c +++ b/drivers/pci/pci-sysfs.c @@ -521,6 +521,31 @@ static ssize_t bus_rescan_store(struct device *dev, static struct device_attribute dev_attr_bus_rescan = __ATTR(rescan, 0200, NULL, bus_rescan_store); +static ssize_t reset_subordinate_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + struct pci_dev *pdev = to_pci_dev(dev); + struct pci_bus *bus = pdev->subordinate; + unsigned long val; + + if (!capable(CAP_SYS_ADMIN)) + return -EPERM; + + if (kstrtoul(buf, 0, &val) < 0) + return -EINVAL; + + if (val) { + int ret = __pci_reset_bus(bus); + + if (ret) + return ret; + } + + return count; +} +static DEVICE_ATTR_WO(reset_subordinate); + #if defined(CONFIG_PM) && defined(CONFIG_ACPI) static ssize_t d3cold_allowed_store(struct device *dev, struct device_attribute *attr, @@ -625,6 +650,7 @@ static struct attribute *pci_dev_attrs[] = { static struct attribute *pci_bridge_attrs[] = { &dev_attr_subordinate_bus_number.attr, &dev_attr_secondary_bus_number.attr, + &dev_attr_reset_subordinate.attr, NULL, }; diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c index f85f380cdb9b..a16d74beaf58 100644 --- a/drivers/pci/pci.c +++ b/drivers/pci/pci.c @@ -5158,6 +5158,8 @@ static void pci_dev_save_and_disable(struct pci_dev *dev) */ if (err_handler && err_handler->reset_prepare) err_handler->reset_prepare(dev); + else if (dev->driver) + pci_warn(dev, "resetting"); /* * Wake-up device prior to save. PM registers default to D0 after @@ -5191,6 +5193,8 @@ static void pci_dev_restore(struct pci_dev *dev) */ if (err_handler && err_handler->reset_done) err_handler->reset_done(dev); + else if (dev->driver) + pci_warn(dev, "reset done"); } /* dev->reset_methods[] is a 0-terminated list of indices into this array */ @@ -5880,7 +5884,7 @@ EXPORT_SYMBOL_GPL(pci_probe_reset_bus); * * Same as above except return -EAGAIN if the bus cannot be locked */ -static int __pci_reset_bus(struct pci_bus *bus) +int __pci_reset_bus(struct pci_bus *bus) { int rc; diff --git a/drivers/pci/pci.h b/drivers/pci/pci.h index ed35b8366b78..7531e4b005c6 100644 --- a/drivers/pci/pci.h +++ b/drivers/pci/pci.h @@ -104,6 +104,7 @@ bool pci_reset_supported(struct pci_dev *dev); void pci_init_reset_methods(struct pci_dev *dev); int pci_bridge_secondary_bus_reset(struct pci_dev *dev); int pci_bus_error_reset(struct pci_dev *dev); +int __pci_reset_bus(struct pci_bus *bus); struct pci_cap_saved_data { u16 cap_nr; |