Skip to content

Commit d487858

Browse files
kuu-rtgregkh
authored andcommitted
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 <[email protected]> Cc: Danilo Krummrich <[email protected]> Signed-off-by: Kurt Borja <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Greg Kroah-Hartman <[email protected]>
1 parent 0af2f6b commit d487858

File tree

1 file changed

+18
-4
lines changed

1 file changed

+18
-4
lines changed

drivers/base/faux.c

Lines changed: 18 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
struct faux_object {
2626
struct faux_device faux_dev;
2727
const struct faux_device_ops *faux_ops;
28+
const struct attribute_group **groups;
2829
};
2930
#define to_faux_object(dev) container_of_const(dev, struct faux_object, faux_dev.dev)
3031

@@ -43,10 +44,21 @@ static int faux_probe(struct device *dev)
4344
struct faux_object *faux_obj = to_faux_object(dev);
4445
struct faux_device *faux_dev = &faux_obj->faux_dev;
4546
const struct faux_device_ops *faux_ops = faux_obj->faux_ops;
46-
int ret = 0;
47+
int ret;
4748

48-
if (faux_ops && faux_ops->probe)
49+
if (faux_ops && faux_ops->probe) {
4950
ret = faux_ops->probe(faux_dev);
51+
if (ret)
52+
return ret;
53+
}
54+
55+
/*
56+
* Add groups after the probe succeeds to ensure resources are
57+
* initialized correctly
58+
*/
59+
ret = device_add_groups(dev, faux_obj->groups);
60+
if (ret && faux_ops && faux_ops->remove)
61+
faux_ops->remove(faux_dev);
5062

5163
return ret;
5264
}
@@ -57,6 +69,8 @@ static void faux_remove(struct device *dev)
5769
struct faux_device *faux_dev = &faux_obj->faux_dev;
5870
const struct faux_device_ops *faux_ops = faux_obj->faux_ops;
5971

72+
device_remove_groups(dev, faux_obj->groups);
73+
6074
if (faux_ops && faux_ops->remove)
6175
faux_ops->remove(faux_dev);
6276
}
@@ -124,8 +138,9 @@ struct faux_device *faux_device_create_with_groups(const char *name,
124138
if (!faux_obj)
125139
return NULL;
126140

127-
/* Save off the callbacks so we can use them in the future */
141+
/* Save off the callbacks and groups so we can use them in the future */
128142
faux_obj->faux_ops = faux_ops;
143+
faux_obj->groups = groups;
129144

130145
/* Initialize the device portion and register it with the driver core */
131146
faux_dev = &faux_obj->faux_dev;
@@ -138,7 +153,6 @@ struct faux_device *faux_device_create_with_groups(const char *name,
138153
else
139154
dev->parent = &faux_bus_root;
140155
dev->bus = &faux_bus_type;
141-
dev->groups = groups;
142156
dev_set_name(dev, "%s", name);
143157

144158
ret = device_add(dev);

0 commit comments

Comments
 (0)