driver core: bus: add bus_get_dev_root() function
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Thu, 9 Feb 2023 09:35:56 +0000 (10:35 +0100)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Fri, 10 Feb 2023 09:16:42 +0000 (10:16 +0100)
Instead of poking around in the struct bus_type directly for the
dev_root pointer, provide a function to return it properly reference
counted, if it is present in the bus.  This will be needed to move the
pointer out of struct bus_type in the future.

Use the function in the driver core code at the same time it is
introduced to verify that it works properly.

Cc: "Rafael J. Wysocki" <rafael@kernel.org>
Link: https://lore.kernel.org/r/20230209093556.19132-1-gregkh@linuxfoundation.org
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
drivers/base/bus.c
drivers/base/core.c
drivers/base/cpu.c
include/linux/device/bus.h

index 301b9c6ece8649d1ee195efe6505507f71b983c2..def1e009ad9d585bcaeb8d83ba7d3114213f02d7 100644 (file)
@@ -1334,6 +1334,26 @@ bool bus_is_registered(const struct bus_type *bus)
        return is_initialized;
 }
 
+/**
+ * bus_get_dev_root - return a pointer to the "device root" of a bus
+ * @bus: bus to return the device root of.
+ *
+ * If a bus has a "device root" structure, return it, WITH THE REFERENCE
+ * COUNT INCREMENTED.
+ *
+ * Note, when finished with the device, a call to put_device() is required.
+ *
+ * If the device root is not present (or bus is not a valid pointer), NULL
+ * will be returned.
+ */
+struct device *bus_get_dev_root(const struct bus_type *bus)
+{
+       if (bus)
+               return get_device(bus->dev_root);
+       return NULL;
+}
+EXPORT_SYMBOL_GPL(bus_get_dev_root);
+
 int __init buses_init(void)
 {
        bus_kset = kset_create_and_add("bus", &bus_uevent_ops, NULL);
index 2712a1a1e9590c7ea78776d0349e4a2f7a888c00..f9297c68214ae47db140860222f4bcf5e709d85f 100644 (file)
@@ -3173,8 +3173,9 @@ static DEFINE_MUTEX(gdp_mutex);
 static struct kobject *get_device_parent(struct device *dev,
                                         struct device *parent)
 {
+       struct kobject *kobj = NULL;
+
        if (dev->class) {
-               struct kobject *kobj = NULL;
                struct kobject *parent_kobj;
                struct kobject *k;
 
@@ -3222,8 +3223,15 @@ static struct kobject *get_device_parent(struct device *dev,
        }
 
        /* subsystems can specify a default root directory for their devices */
-       if (!parent && dev->bus && dev->bus->dev_root)
-               return &dev->bus->dev_root->kobj;
+       if (!parent && dev->bus) {
+               struct device *dev_root = bus_get_dev_root(dev->bus);
+
+               if (dev_root) {
+                       kobj = &dev_root->kobj;
+                       put_device(dev_root);
+                       return kobj;
+               }
+       }
 
        if (parent)
                return &parent->kobj;
index 441eb5bdec7d89da35956919a3d0885bb59adea1..8bb623039bb2f0ed61b491b2ba5c39ac72f90aaf 100644 (file)
@@ -610,9 +610,13 @@ static const struct attribute_group cpu_root_vulnerabilities_group = {
 
 static void __init cpu_register_vulnerabilities(void)
 {
-       if (sysfs_create_group(&cpu_subsys.dev_root->kobj,
-                              &cpu_root_vulnerabilities_group))
-               pr_err("Unable to register CPU vulnerabilities\n");
+       struct device *dev = bus_get_dev_root(&cpu_subsys);
+
+       if (dev) {
+               if (sysfs_create_group(&dev->kobj, &cpu_root_vulnerabilities_group))
+                       pr_err("Unable to register CPU vulnerabilities\n");
+               put_device(dev);
+       }
 }
 
 #else
index 31be18608f83f02cdd824f51eec5eb87154a2525..6ce32ef4b8fd49a8416129b194fbdbe6a04dd908 100644 (file)
@@ -282,5 +282,6 @@ enum bus_notifier_event {
 };
 
 extern struct kset *bus_get_kset(const struct bus_type *bus);
+struct device *bus_get_dev_root(const struct bus_type *bus);
 
 #endif