diff mbox series

[03/20] PCI: Convert dynamic "reset" sysfs object into static

Message ID 20210416205856.3234481-4-kw@linux.com
State New
Headers show
Series PCI: Convert dynamic sysfs objects into static | expand

Commit Message

Krzysztof Wilczyński April 16, 2021, 8:58 p.m. UTC
The "reset" sysfs object, which is a write-only attribute, resides at
the "/sys/bus/pci/devices/.../reset" path and allows for resetting the
PCI function of a device if the device supports resetting a single
function.

At the moment, the static "reset" sysfs object is dynamically created
when the pci_create_capabilities_sysfs() function executes that is part
of the PCI sysfs objects initialisation and when a device is added:

  late_initcall()
    pci_sysfs_init()
      pci_create_sysfs_dev_files()
        pci_create_capabilities_sysfs()
          device_create_file()

  pci_bus_add_devices()
    pci_bus_add_device()
      pci_create_sysfs_dev_files()
        ...

And dynamically removed when the pci_remove_capabilities_sysfs()
function executes when the PCI device is stopped and removed:

  pci_stop_bus_device()
    pci_stop_dev()
      pci_remove_sysfs_dev_files()
        pci_remove_capabilities_sysfs()
          device_remove_file()

This attribute does not need to be created dynamically and removed
dynamically, and thus there is no need to also manage its create and
remove life cycle manually as the PCI driver core can do it when the
device is either added or removed.

Convert the "reset" sysfs object created dynamically to static and use
the .is_visible callback to check whether the device has a reset
function capability and to decide if the sysfs object should be made
available.

Then, add a newly created attribute group to the existing group called
"pci_dev_groups" to ensure that the "reset" sysfs object would be
automatically included when the PCI driver initialises.

Move to disable the "reset_fn" flag, and thus disabling the reset
function capability of a device, to the pci_stop_dev() function from the
pci_remove_capabilities_sysfs() function, as it makes more sense to
disable the flag when the device is about to be stopped, rather than
where sysfs objects are removed.

Suggested-by: Oliver O'Halloran <oohall@gmail.com>
Suggested-by: Bjorn Helgaas <bhelgaas@google.com>
Signed-off-by: Krzysztof Wilczyński <kw@linux.com>
---
 drivers/pci/pci-sysfs.c | 51 +++++++++++++++++++----------------------
 drivers/pci/remove.c    |  2 ++
 2 files changed, 26 insertions(+), 27 deletions(-)
diff mbox series

Patch

diff --git a/drivers/pci/pci-sysfs.c b/drivers/pci/pci-sysfs.c
index fa8373685140..c469d9cad0a8 100644
--- a/drivers/pci/pci-sysfs.c
+++ b/drivers/pci/pci-sysfs.c
@@ -1355,25 +1355,33 @@  static ssize_t reset_store(struct device *dev, struct device_attribute *attr,
 
 	return count;
 }
+static DEVICE_ATTR_WO(reset);
 
-static DEVICE_ATTR(reset, 0200, NULL, reset_store);
+static struct attribute *pci_dev_reset_attrs[] = {
+	&dev_attr_reset.attr,
+	NULL,
+};
 
-static int pci_create_capabilities_sysfs(struct pci_dev *dev)
+static umode_t pci_dev_reset_attr_is_visible(struct kobject *kobj,
+					     struct attribute *a, int n)
 {
-	int retval;
+	struct pci_dev *pdev = to_pci_dev(kobj_to_dev(kobj));
 
-	pcie_vpd_create_sysfs_dev_files(dev);
+	if (!pdev->reset_fn)
+		return 0;
 
-	if (dev->reset_fn) {
-		retval = device_create_file(&dev->dev, &dev_attr_reset);
-		if (retval)
-			goto error;
-	}
-	return 0;
+	return a->mode;
+}
 
-error:
-	pcie_vpd_remove_sysfs_dev_files(dev);
-	return retval;
+static const struct attribute_group pci_dev_reset_attr_group = {
+	.attrs = pci_dev_reset_attrs,
+	.is_visible = pci_dev_reset_attr_is_visible,
+};
+
+
+static void pci_create_capabilities_sysfs(struct pci_dev *dev)
+{
+	pcie_vpd_create_sysfs_dev_files(dev);
 }
 
 int __must_check pci_create_sysfs_dev_files(struct pci_dev *pdev)
@@ -1385,30 +1393,18 @@  int __must_check pci_create_sysfs_dev_files(struct pci_dev *pdev)
 
 	retval = pci_create_resource_files(pdev);
 	if (retval)
-		goto err;
+		return retval;
 
 	/* add sysfs entries for various capabilities */
-	retval = pci_create_capabilities_sysfs(pdev);
-	if (retval)
-		goto err_resource_files;
-
+	pci_create_capabilities_sysfs(pdev);
 	pci_create_firmware_label_files(pdev);
 
 	return 0;
-
-err_resource_files:
-	pci_remove_resource_files(pdev);
-err:
-	return retval;
 }
 
 static void pci_remove_capabilities_sysfs(struct pci_dev *dev)
 {
 	pcie_vpd_remove_sysfs_dev_files(dev);
-	if (dev->reset_fn) {
-		device_remove_file(&dev->dev, &dev_attr_reset);
-		dev->reset_fn = 0;
-	}
 }
 
 /**
@@ -1517,6 +1513,7 @@  const struct attribute_group *pci_dev_groups[] = {
 	&pci_dev_group,
 	&pci_dev_config_attr_group,
 	&pci_dev_rom_attr_group,
+	&pci_dev_reset_attr_group,
 	NULL,
 };
 
diff --git a/drivers/pci/remove.c b/drivers/pci/remove.c
index 95dec03d9f2a..dd12c2fcc7dc 100644
--- a/drivers/pci/remove.c
+++ b/drivers/pci/remove.c
@@ -19,6 +19,8 @@  static void pci_stop_dev(struct pci_dev *dev)
 	pci_pme_active(dev, false);
 
 	if (pci_dev_is_added(dev)) {
+		dev->reset_fn = 0;
+
 		device_release_driver(&dev->dev);
 		pci_proc_detach_device(dev);
 		pci_remove_sysfs_dev_files(dev);