PCI: Add 'reset_subordinate' to reset hierarchy below bridge
Subsystems (2)
Sasha Levin
maintainerPATCH 1/1 PCI: Add 'reset_subordinate' to reset hierarchy below bridge
From: Keith Busch <[email protected]>
[ Upstream commit 2fa046449a82a7d0f6d9721dd83e348816038444 ]
The "bus" and "cxl_bus" reset methods reset a device by asserting Secondary Bus Reset on the bridge leading to the device. These only work if the device is the only device below the bridge.
Add a sysfs 'reset_subordinate' attribute on bridges that can assert Secondary Bus Reset regardless of how many devices are below the bridge.
This resets all the devices below a bridge in a single command, including the locking and config space save/restore that reset methods normally do.
This may be the only way to reset devices that don't support other reset methods (ACPI, FLR, PM reset, etc).
--- Documentation/ABI/testing/sysfs-bus-pci | 11 +++++++++++ drivers/pci/pci-sysfs.c | 26 +++++++++++++++++++++++++ drivers/pci/pci.c | 2 +- drivers/pci/pci.h | 1 + 4 files changed, 39 insertions(+), 1 deletion(-)
Documentation/ABI/testing/sysfs-bus-pci +11 -0
@@ -125,6 +125,17 @@ Description: will be present in sysfs. Writing 1 to this file will perform reset. +What: /sys/bus/pci/devices/.../reset_subordinate +Date: October 2024 +Contact: [email protected] +Description: + This is visible only for bridge devices. If you want to reset + all devices attached through the subordinate bus of a specific + bridge device, writing 1 to this will try to do it. This will + affect all devices attached to the system through this bridge + similiar to writing 1 to their individual "reset" file, so use + with caution. + What: /sys/bus/pci/devices/.../vpd Date: February 2008 Contact: Ben Hutchings <[email protected]>
drivers/pci/pci-sysfs.c +26 -0
@@ -507,6 +507,31 @@ static ssize_t dev_bus_rescan_store(struct device *dev, } static DEVICE_ATTR(rescan, (S_IWUSR|S_IWGRP), NULL, dev_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,
@@ -778,6 +803,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 , };
drivers/pci/pci.c +1 -1
@@ -5295,7 +5295,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;
drivers/pci/pci.h +1 -0
@@ -36,6 +36,7 @@ int pci_mmap_fits(struct pci_dev *pdev, int resno, struct vm_area_struct *vmai,int pci_probe_reset_function (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_platform_pm_ops - Firmware PM callbacks
Signature · 1 line
2.43.0