Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

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>

authored by

Kurt Borja and committed by
Greg Kroah-Hartman
d487858e 0af2f6be

+18 -4
+18 -4
drivers/base/faux.c
··· 25 25 struct faux_object { 26 26 struct faux_device faux_dev; 27 27 const struct faux_device_ops *faux_ops; 28 + const struct attribute_group **groups; 28 29 }; 29 30 #define to_faux_object(dev) container_of_const(dev, struct faux_object, faux_dev.dev) 30 31 ··· 44 43 struct faux_object *faux_obj = to_faux_object(dev); 45 44 struct faux_device *faux_dev = &faux_obj->faux_dev; 46 45 const struct faux_device_ops *faux_ops = faux_obj->faux_ops; 47 - int ret = 0; 46 + int ret; 48 47 49 - if (faux_ops && faux_ops->probe) 48 + if (faux_ops && faux_ops->probe) { 50 49 ret = faux_ops->probe(faux_dev); 50 + if (ret) 51 + return ret; 52 + } 53 + 54 + /* 55 + * Add groups after the probe succeeds to ensure resources are 56 + * initialized correctly 57 + */ 58 + ret = device_add_groups(dev, faux_obj->groups); 59 + if (ret && faux_ops && faux_ops->remove) 60 + faux_ops->remove(faux_dev); 51 61 52 62 return ret; 53 63 } ··· 68 56 struct faux_object *faux_obj = to_faux_object(dev); 69 57 struct faux_device *faux_dev = &faux_obj->faux_dev; 70 58 const struct faux_device_ops *faux_ops = faux_obj->faux_ops; 59 + 60 + device_remove_groups(dev, faux_obj->groups); 71 61 72 62 if (faux_ops && faux_ops->remove) 73 63 faux_ops->remove(faux_dev); ··· 138 124 if (!faux_obj) 139 125 return NULL; 140 126 141 - /* Save off the callbacks so we can use them in the future */ 127 + /* Save off the callbacks and groups so we can use them in the future */ 142 128 faux_obj->faux_ops = faux_ops; 129 + faux_obj->groups = groups; 143 130 144 131 /* Initialize the device portion and register it with the driver core */ 145 132 faux_dev = &faux_obj->faux_dev; ··· 153 138 else 154 139 dev->parent = &faux_bus_root; 155 140 dev->bus = &faux_bus_type; 156 - dev->groups = groups; 157 141 dev_set_name(dev, "%s", name); 158 142 159 143 ret = device_add(dev);