Skip to content

Commit 1af824f

Browse files
committed
Merge branch 'bind_unbind' into driver-core-next
This merges the bind_unbind driver core feature into the driver-core-next branch. bind_unbind is a branch so that others can pull and work off of it safely. Signed-off-by: Greg Kroah-Hartman <[email protected]>
2 parents d8bcf4d + 072a785 commit 1af824f

File tree

9 files changed

+176
-44
lines changed

9 files changed

+176
-44
lines changed

drivers/base/base.h

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -126,11 +126,6 @@ extern int driver_add_groups(struct device_driver *drv,
126126
extern void driver_remove_groups(struct device_driver *drv,
127127
const struct attribute_group **groups);
128128

129-
extern int device_add_groups(struct device *dev,
130-
const struct attribute_group **groups);
131-
extern void device_remove_groups(struct device *dev,
132-
const struct attribute_group **groups);
133-
134129
extern char *make_class_name(const char *name, struct kobject *kobj);
135130

136131
extern int devres_release_all(struct device *dev);

drivers/base/core.c

Lines changed: 132 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1023,12 +1023,144 @@ int device_add_groups(struct device *dev, const struct attribute_group **groups)
10231023
{
10241024
return sysfs_create_groups(&dev->kobj, groups);
10251025
}
1026+
EXPORT_SYMBOL_GPL(device_add_groups);
10261027

10271028
void device_remove_groups(struct device *dev,
10281029
const struct attribute_group **groups)
10291030
{
10301031
sysfs_remove_groups(&dev->kobj, groups);
10311032
}
1033+
EXPORT_SYMBOL_GPL(device_remove_groups);
1034+
1035+
union device_attr_group_devres {
1036+
const struct attribute_group *group;
1037+
const struct attribute_group **groups;
1038+
};
1039+
1040+
static int devm_attr_group_match(struct device *dev, void *res, void *data)
1041+
{
1042+
return ((union device_attr_group_devres *)res)->group == data;
1043+
}
1044+
1045+
static void devm_attr_group_remove(struct device *dev, void *res)
1046+
{
1047+
union device_attr_group_devres *devres = res;
1048+
const struct attribute_group *group = devres->group;
1049+
1050+
dev_dbg(dev, "%s: removing group %p\n", __func__, group);
1051+
sysfs_remove_group(&dev->kobj, group);
1052+
}
1053+
1054+
static void devm_attr_groups_remove(struct device *dev, void *res)
1055+
{
1056+
union device_attr_group_devres *devres = res;
1057+
const struct attribute_group **groups = devres->groups;
1058+
1059+
dev_dbg(dev, "%s: removing groups %p\n", __func__, groups);
1060+
sysfs_remove_groups(&dev->kobj, groups);
1061+
}
1062+
1063+
/**
1064+
* devm_device_add_group - given a device, create a managed attribute group
1065+
* @dev: The device to create the group for
1066+
* @grp: The attribute group to create
1067+
*
1068+
* This function creates a group for the first time. It will explicitly
1069+
* warn and error if any of the attribute files being created already exist.
1070+
*
1071+
* Returns 0 on success or error code on failure.
1072+
*/
1073+
int devm_device_add_group(struct device *dev, const struct attribute_group *grp)
1074+
{
1075+
union device_attr_group_devres *devres;
1076+
int error;
1077+
1078+
devres = devres_alloc(devm_attr_group_remove,
1079+
sizeof(*devres), GFP_KERNEL);
1080+
if (!devres)
1081+
return -ENOMEM;
1082+
1083+
error = sysfs_create_group(&dev->kobj, grp);
1084+
if (error) {
1085+
devres_free(devres);
1086+
return error;
1087+
}
1088+
1089+
devres->group = grp;
1090+
devres_add(dev, devres);
1091+
return 0;
1092+
}
1093+
EXPORT_SYMBOL_GPL(devm_device_add_group);
1094+
1095+
/**
1096+
* devm_device_remove_group: remove a managed group from a device
1097+
* @dev: device to remove the group from
1098+
* @grp: group to remove
1099+
*
1100+
* This function removes a group of attributes from a device. The attributes
1101+
* previously have to have been created for this group, otherwise it will fail.
1102+
*/
1103+
void devm_device_remove_group(struct device *dev,
1104+
const struct attribute_group *grp)
1105+
{
1106+
WARN_ON(devres_release(dev, devm_attr_group_remove,
1107+
devm_attr_group_match,
1108+
/* cast away const */ (void *)grp));
1109+
}
1110+
EXPORT_SYMBOL_GPL(devm_device_remove_group);
1111+
1112+
/**
1113+
* devm_device_add_groups - create a bunch of managed attribute groups
1114+
* @dev: The device to create the group for
1115+
* @groups: The attribute groups to create, NULL terminated
1116+
*
1117+
* This function creates a bunch of managed attribute groups. If an error
1118+
* occurs when creating a group, all previously created groups will be
1119+
* removed, unwinding everything back to the original state when this
1120+
* function was called. It will explicitly warn and error if any of the
1121+
* attribute files being created already exist.
1122+
*
1123+
* Returns 0 on success or error code from sysfs_create_group on failure.
1124+
*/
1125+
int devm_device_add_groups(struct device *dev,
1126+
const struct attribute_group **groups)
1127+
{
1128+
union device_attr_group_devres *devres;
1129+
int error;
1130+
1131+
devres = devres_alloc(devm_attr_groups_remove,
1132+
sizeof(*devres), GFP_KERNEL);
1133+
if (!devres)
1134+
return -ENOMEM;
1135+
1136+
error = sysfs_create_groups(&dev->kobj, groups);
1137+
if (error) {
1138+
devres_free(devres);
1139+
return error;
1140+
}
1141+
1142+
devres->groups = groups;
1143+
devres_add(dev, devres);
1144+
return 0;
1145+
}
1146+
EXPORT_SYMBOL_GPL(devm_device_add_groups);
1147+
1148+
/**
1149+
* devm_device_remove_groups - remove a list of managed groups
1150+
*
1151+
* @dev: The device for the groups to be removed from
1152+
* @groups: NULL terminated list of groups to be removed
1153+
*
1154+
* If groups is not NULL, remove the specified groups from the device.
1155+
*/
1156+
void devm_device_remove_groups(struct device *dev,
1157+
const struct attribute_group **groups)
1158+
{
1159+
WARN_ON(devres_release(dev, devm_attr_groups_remove,
1160+
devm_attr_group_match,
1161+
/* cast away const */ (void *)groups));
1162+
}
1163+
EXPORT_SYMBOL_GPL(devm_device_remove_groups);
10321164

10331165
static int device_add_attrs(struct device *dev)
10341166
{

drivers/base/dd.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -259,6 +259,8 @@ static void driver_bound(struct device *dev)
259259
if (dev->bus)
260260
blocking_notifier_call_chain(&dev->bus->p->bus_notifier,
261261
BUS_NOTIFY_BOUND_DRIVER, dev);
262+
263+
kobject_uevent(&dev->kobj, KOBJ_BIND);
262264
}
263265

264266
static int driver_sysfs_add(struct device *dev)
@@ -848,6 +850,8 @@ static void __device_release_driver(struct device *dev, struct device *parent)
848850
blocking_notifier_call_chain(&dev->bus->p->bus_notifier,
849851
BUS_NOTIFY_UNBOUND_DRIVER,
850852
dev);
853+
854+
kobject_uevent(&dev->kobj, KOBJ_UNBIND);
851855
}
852856
}
853857

drivers/input/keyboard/gpio_keys.c

Lines changed: 2 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -827,7 +827,7 @@ static int gpio_keys_probe(struct platform_device *pdev)
827827

828828
fwnode_handle_put(child);
829829

830-
error = sysfs_create_group(&dev->kobj, &gpio_keys_attr_group);
830+
error = devm_device_add_group(dev, &gpio_keys_attr_group);
831831
if (error) {
832832
dev_err(dev, "Unable to export keys/switches, error: %d\n",
833833
error);
@@ -838,22 +838,11 @@ static int gpio_keys_probe(struct platform_device *pdev)
838838
if (error) {
839839
dev_err(dev, "Unable to register input device, error: %d\n",
840840
error);
841-
goto err_remove_group;
841+
return error;
842842
}
843843

844844
device_init_wakeup(dev, wakeup);
845845

846-
return 0;
847-
848-
err_remove_group:
849-
sysfs_remove_group(&dev->kobj, &gpio_keys_attr_group);
850-
return error;
851-
}
852-
853-
static int gpio_keys_remove(struct platform_device *pdev)
854-
{
855-
sysfs_remove_group(&pdev->dev.kobj, &gpio_keys_attr_group);
856-
857846
return 0;
858847
}
859848

@@ -912,7 +901,6 @@ static SIMPLE_DEV_PM_OPS(gpio_keys_pm_ops, gpio_keys_suspend, gpio_keys_resume);
912901

913902
static struct platform_driver gpio_keys_device_driver = {
914903
.probe = gpio_keys_probe,
915-
.remove = gpio_keys_remove,
916904
.driver = {
917905
.name = "gpio-keys",
918906
.pm = &gpio_keys_pm_ops,

drivers/input/misc/axp20x-pek.c

Lines changed: 1 addition & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -182,13 +182,6 @@ static irqreturn_t axp20x_pek_irq(int irq, void *pwr)
182182
return IRQ_HANDLED;
183183
}
184184

185-
static void axp20x_remove_sysfs_group(void *_data)
186-
{
187-
struct device *dev = _data;
188-
189-
sysfs_remove_group(&dev->kobj, &axp20x_attribute_group);
190-
}
191-
192185
static int axp20x_pek_probe_input_device(struct axp20x_pek *axp20x_pek,
193186
struct platform_device *pdev)
194187
{
@@ -313,22 +306,13 @@ static int axp20x_pek_probe(struct platform_device *pdev)
313306
return error;
314307
}
315308

316-
error = sysfs_create_group(&pdev->dev.kobj, &axp20x_attribute_group);
309+
error = devm_device_add_group(&pdev->dev, &axp20x_attribute_group);
317310
if (error) {
318311
dev_err(&pdev->dev, "Failed to create sysfs attributes: %d\n",
319312
error);
320313
return error;
321314
}
322315

323-
error = devm_add_action(&pdev->dev,
324-
axp20x_remove_sysfs_group, &pdev->dev);
325-
if (error) {
326-
axp20x_remove_sysfs_group(&pdev->dev);
327-
dev_err(&pdev->dev, "Failed to add sysfs cleanup action: %d\n",
328-
error);
329-
return error;
330-
}
331-
332316
platform_set_drvdata(pdev, axp20x_pek);
333317

334318
return 0;

drivers/input/rmi4/rmi_f01.c

Lines changed: 3 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -570,18 +570,14 @@ static int rmi_f01_probe(struct rmi_function *fn)
570570

571571
dev_set_drvdata(&fn->dev, f01);
572572

573-
error = sysfs_create_group(&fn->rmi_dev->dev.kobj, &rmi_f01_attr_group);
573+
error = devm_device_add_group(&fn->rmi_dev->dev, &rmi_f01_attr_group);
574574
if (error)
575-
dev_warn(&fn->dev, "Failed to create sysfs group: %d\n", error);
575+
dev_warn(&fn->dev,
576+
"Failed to create attribute group: %d\n", error);
576577

577578
return 0;
578579
}
579580

580-
static void rmi_f01_remove(struct rmi_function *fn)
581-
{
582-
sysfs_remove_group(&fn->rmi_dev->dev.kobj, &rmi_f01_attr_group);
583-
}
584-
585581
static int rmi_f01_config(struct rmi_function *fn)
586582
{
587583
struct f01_data *f01 = dev_get_drvdata(&fn->dev);
@@ -721,7 +717,6 @@ struct rmi_function_handler rmi_f01_handler = {
721717
},
722718
.func = 0x01,
723719
.probe = rmi_f01_probe,
724-
.remove = rmi_f01_remove,
725720
.config = rmi_f01_config,
726721
.attention = rmi_f01_attention,
727722
.suspend = rmi_f01_suspend,

include/linux/device.h

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1200,6 +1200,36 @@ struct device *device_create_with_groups(struct class *cls,
12001200
const char *fmt, ...);
12011201
extern void device_destroy(struct class *cls, dev_t devt);
12021202

1203+
extern int __must_check device_add_groups(struct device *dev,
1204+
const struct attribute_group **groups);
1205+
extern void device_remove_groups(struct device *dev,
1206+
const struct attribute_group **groups);
1207+
1208+
static inline int __must_check device_add_group(struct device *dev,
1209+
const struct attribute_group *grp)
1210+
{
1211+
const struct attribute_group *groups[] = { grp, NULL };
1212+
1213+
return device_add_groups(dev, groups);
1214+
}
1215+
1216+
static inline void device_remove_group(struct device *dev,
1217+
const struct attribute_group *grp)
1218+
{
1219+
const struct attribute_group *groups[] = { grp, NULL };
1220+
1221+
return device_remove_groups(dev, groups);
1222+
}
1223+
1224+
extern int __must_check devm_device_add_groups(struct device *dev,
1225+
const struct attribute_group **groups);
1226+
extern void devm_device_remove_groups(struct device *dev,
1227+
const struct attribute_group **groups);
1228+
extern int __must_check devm_device_add_group(struct device *dev,
1229+
const struct attribute_group *grp);
1230+
extern void devm_device_remove_group(struct device *dev,
1231+
const struct attribute_group *grp);
1232+
12031233
/*
12041234
* Platform "fixup" functions - allow the platform to have their say
12051235
* about devices and actions that the general device layer doesn't

include/linux/kobject.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,8 @@ enum kobject_action {
5757
KOBJ_MOVE,
5858
KOBJ_ONLINE,
5959
KOBJ_OFFLINE,
60+
KOBJ_BIND,
61+
KOBJ_UNBIND,
6062
KOBJ_MAX
6163
};
6264

lib/kobject_uevent.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,8 @@ static const char *kobject_actions[] = {
5252
[KOBJ_MOVE] = "move",
5353
[KOBJ_ONLINE] = "online",
5454
[KOBJ_OFFLINE] = "offline",
55+
[KOBJ_BIND] = "bind",
56+
[KOBJ_UNBIND] = "unbind",
5557
};
5658

5759
static int kobject_action_type(const char *buf, size_t count,

0 commit comments

Comments
 (0)