aboutsummaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
authorKurt Borja <kuurtb@gmail.com>2025-03-27 20:19:37 -0300
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2025-04-15 14:16:08 +0200
commitd487858ebffaab9acd8945f19ef400ec6eda11f1 (patch)
treef6628cbde04a4a9ab6351cb9db80b25a9da6bb40
parentLinux 6.15-rc1 (diff)
downloadwireguard-linux-d487858ebffaab9acd8945f19ef400ec6eda11f1.tar.xz
wireguard-linux-d487858ebffaab9acd8945f19ef400ec6eda11f1.zip
driver core: faux: Add sysfs groups after probing
Manually add sysfs groups after the faux_device_ops's probe succeeds. Likewise remove these groups just before calling the faux_devices_ops's remove callback. This approach approximates the order in which the driver core adds and removes the driver's .dev_groups of a device to avoid lifetime issues. This is done specifically to avoid using the device's .groups member, which adds groups before the device is even registered to the bus. This lets consumers of this API, initialize resources on the .probe callback and then use them inside is_visible/show/store methods, through dev_get_drvdata() without races. Cc: Rafael J. Wysocki <rafael@kernel.org> Cc: Danilo Krummrich <dakr@kernel.org> Signed-off-by: Kurt Borja <kuurtb@gmail.com> Link: https://lore.kernel.org/r/20250327-faux-groups-v2-1-745a3cf0bc16@gmail.com Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-rw-r--r--drivers/base/faux.c22
1 files changed, 18 insertions, 4 deletions
diff --git a/drivers/base/faux.c b/drivers/base/faux.c
index 407c1d1aad50..9054d346bd7f 100644
--- a/drivers/base/faux.c
+++ b/drivers/base/faux.c
@@ -25,6 +25,7 @@
struct faux_object {
struct faux_device faux_dev;
const struct faux_device_ops *faux_ops;
+ const struct attribute_group **groups;
};
#define to_faux_object(dev) container_of_const(dev, struct faux_object, faux_dev.dev)
@@ -43,10 +44,21 @@ static int faux_probe(struct device *dev)
struct faux_object *faux_obj = to_faux_object(dev);
struct faux_device *faux_dev = &faux_obj->faux_dev;
const struct faux_device_ops *faux_ops = faux_obj->faux_ops;
- int ret = 0;
+ int ret;
- if (faux_ops && faux_ops->probe)
+ if (faux_ops && faux_ops->probe) {
ret = faux_ops->probe(faux_dev);
+ if (ret)
+ return ret;
+ }
+
+ /*
+ * Add groups after the probe succeeds to ensure resources are
+ * initialized correctly
+ */
+ ret = device_add_groups(dev, faux_obj->groups);
+ if (ret && faux_ops && faux_ops->remove)
+ faux_ops->remove(faux_dev);
return ret;
}
@@ -57,6 +69,8 @@ static void faux_remove(struct device *dev)
struct faux_device *faux_dev = &faux_obj->faux_dev;
const struct faux_device_ops *faux_ops = faux_obj->faux_ops;
+ device_remove_groups(dev, faux_obj->groups);
+
if (faux_ops && faux_ops->remove)
faux_ops->remove(faux_dev);
}
@@ -124,8 +138,9 @@ struct faux_device *faux_device_create_with_groups(const char *name,
if (!faux_obj)
return NULL;
- /* Save off the callbacks so we can use them in the future */
+ /* Save off the callbacks and groups so we can use them in the future */
faux_obj->faux_ops = faux_ops;
+ faux_obj->groups = groups;
/* Initialize the device portion and register it with the driver core */
faux_dev = &faux_obj->faux_dev;
@@ -138,7 +153,6 @@ struct faux_device *faux_device_create_with_groups(const char *name,
else
dev->parent = &faux_bus_root;
dev->bus = &faux_bus_type;
- dev->groups = groups;
dev_set_name(dev, "%s", name);
ret = device_add(dev);