aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>2017-07-22 06:00:15 -0400
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2017-07-22 06:00:15 -0400
commit1af824f085e813e06548212b18bbc788b16f60e6 (patch)
tree7e4bea76e0780330e27d660633ba514dc02e2fbf
parentd8bcf4db9244e2b85597c680f4e1c3a837b067fe (diff)
parent072a7852338af900c302490474939e089f4bd4c4 (diff)
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 <gregkh@linuxfoundation.org>
-rw-r--r--drivers/base/base.h5
-rw-r--r--drivers/base/core.c132
-rw-r--r--drivers/base/dd.c4
-rw-r--r--drivers/input/keyboard/gpio_keys.c16
-rw-r--r--drivers/input/misc/axp20x-pek.c18
-rw-r--r--drivers/input/rmi4/rmi_f01.c11
-rw-r--r--include/linux/device.h30
-rw-r--r--include/linux/kobject.h2
-rw-r--r--lib/kobject_uevent.c2
9 files changed, 176 insertions, 44 deletions
diff --git a/drivers/base/base.h b/drivers/base/base.h
index e19b1008e5fb..539432a14b5c 100644
--- a/drivers/base/base.h
+++ b/drivers/base/base.h
@@ -126,11 +126,6 @@ extern int driver_add_groups(struct device_driver *drv,
126extern void driver_remove_groups(struct device_driver *drv, 126extern void driver_remove_groups(struct device_driver *drv,
127 const struct attribute_group **groups); 127 const struct attribute_group **groups);
128 128
129extern int device_add_groups(struct device *dev,
130 const struct attribute_group **groups);
131extern void device_remove_groups(struct device *dev,
132 const struct attribute_group **groups);
133
134extern char *make_class_name(const char *name, struct kobject *kobj); 129extern char *make_class_name(const char *name, struct kobject *kobj);
135 130
136extern int devres_release_all(struct device *dev); 131extern int devres_release_all(struct device *dev);
diff --git a/drivers/base/core.c b/drivers/base/core.c
index 755451f684bc..cb4b5b1f1b09 100644
--- a/drivers/base/core.c
+++ b/drivers/base/core.c
@@ -1023,12 +1023,144 @@ int device_add_groups(struct device *dev, const struct attribute_group **groups)
1023{ 1023{
1024 return sysfs_create_groups(&dev->kobj, groups); 1024 return sysfs_create_groups(&dev->kobj, groups);
1025} 1025}
1026EXPORT_SYMBOL_GPL(device_add_groups);
1026 1027
1027void device_remove_groups(struct device *dev, 1028void device_remove_groups(struct device *dev,
1028 const struct attribute_group **groups) 1029 const struct attribute_group **groups)
1029{ 1030{
1030 sysfs_remove_groups(&dev->kobj, groups); 1031 sysfs_remove_groups(&dev->kobj, groups);
1031} 1032}
1033EXPORT_SYMBOL_GPL(device_remove_groups);
1034
1035union device_attr_group_devres {
1036 const struct attribute_group *group;
1037 const struct attribute_group **groups;
1038};
1039
1040static 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
1045static 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
1054static 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 */
1073int 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}
1093EXPORT_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 */
1103void 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}
1110EXPORT_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 */
1125int 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}
1146EXPORT_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 */
1156void 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}
1163EXPORT_SYMBOL_GPL(devm_device_remove_groups);
1032 1164
1033static int device_add_attrs(struct device *dev) 1165static int device_add_attrs(struct device *dev)
1034{ 1166{
diff --git a/drivers/base/dd.c b/drivers/base/dd.c
index 4882f06d12df..c17fefc77345 100644
--- a/drivers/base/dd.c
+++ b/drivers/base/dd.c
@@ -259,6 +259,8 @@ static void driver_bound(struct device *dev)
259 if (dev->bus) 259 if (dev->bus)
260 blocking_notifier_call_chain(&dev->bus->p->bus_notifier, 260 blocking_notifier_call_chain(&dev->bus->p->bus_notifier,
261 BUS_NOTIFY_BOUND_DRIVER, dev); 261 BUS_NOTIFY_BOUND_DRIVER, dev);
262
263 kobject_uevent(&dev->kobj, KOBJ_BIND);
262} 264}
263 265
264static int driver_sysfs_add(struct device *dev) 266static int driver_sysfs_add(struct device *dev)
@@ -848,6 +850,8 @@ static void __device_release_driver(struct device *dev, struct device *parent)
848 blocking_notifier_call_chain(&dev->bus->p->bus_notifier, 850 blocking_notifier_call_chain(&dev->bus->p->bus_notifier,
849 BUS_NOTIFY_UNBOUND_DRIVER, 851 BUS_NOTIFY_UNBOUND_DRIVER,
850 dev); 852 dev);
853
854 kobject_uevent(&dev->kobj, KOBJ_UNBIND);
851 } 855 }
852} 856}
853 857
diff --git a/drivers/input/keyboard/gpio_keys.c b/drivers/input/keyboard/gpio_keys.c
index a047b9af8369..0b10d4b356db 100644
--- a/drivers/input/keyboard/gpio_keys.c
+++ b/drivers/input/keyboard/gpio_keys.c
@@ -827,7 +827,7 @@ static int gpio_keys_probe(struct platform_device *pdev)
827 827
828 fwnode_handle_put(child); 828 fwnode_handle_put(child);
829 829
830 error = sysfs_create_group(&dev->kobj, &gpio_keys_attr_group); 830 error = devm_device_add_group(dev, &gpio_keys_attr_group);
831 if (error) { 831 if (error) {
832 dev_err(dev, "Unable to export keys/switches, error: %d\n", 832 dev_err(dev, "Unable to export keys/switches, error: %d\n",
833 error); 833 error);
@@ -838,23 +838,12 @@ static int gpio_keys_probe(struct platform_device *pdev)
838 if (error) { 838 if (error) {
839 dev_err(dev, "Unable to register input device, error: %d\n", 839 dev_err(dev, "Unable to register input device, error: %d\n",
840 error); 840 error);
841 goto err_remove_group; 841 return error;
842 } 842 }
843 843
844 device_init_wakeup(dev, wakeup); 844 device_init_wakeup(dev, wakeup);
845 845
846 return 0; 846 return 0;
847
848err_remove_group:
849 sysfs_remove_group(&dev->kobj, &gpio_keys_attr_group);
850 return error;
851}
852
853static int gpio_keys_remove(struct platform_device *pdev)
854{
855 sysfs_remove_group(&pdev->dev.kobj, &gpio_keys_attr_group);
856
857 return 0;
858} 847}
859 848
860static int __maybe_unused gpio_keys_suspend(struct device *dev) 849static int __maybe_unused gpio_keys_suspend(struct device *dev)
@@ -912,7 +901,6 @@ static SIMPLE_DEV_PM_OPS(gpio_keys_pm_ops, gpio_keys_suspend, gpio_keys_resume);
912 901
913static struct platform_driver gpio_keys_device_driver = { 902static struct platform_driver gpio_keys_device_driver = {
914 .probe = gpio_keys_probe, 903 .probe = gpio_keys_probe,
915 .remove = gpio_keys_remove,
916 .driver = { 904 .driver = {
917 .name = "gpio-keys", 905 .name = "gpio-keys",
918 .pm = &gpio_keys_pm_ops, 906 .pm = &gpio_keys_pm_ops,
diff --git a/drivers/input/misc/axp20x-pek.c b/drivers/input/misc/axp20x-pek.c
index 38c79ebff033..cfeb0e943de6 100644
--- a/drivers/input/misc/axp20x-pek.c
+++ b/drivers/input/misc/axp20x-pek.c
@@ -182,13 +182,6 @@ static irqreturn_t axp20x_pek_irq(int irq, void *pwr)
182 return IRQ_HANDLED; 182 return IRQ_HANDLED;
183} 183}
184 184
185static 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
192static int axp20x_pek_probe_input_device(struct axp20x_pek *axp20x_pek, 185static int axp20x_pek_probe_input_device(struct axp20x_pek *axp20x_pek,
193 struct platform_device *pdev) 186 struct platform_device *pdev)
194{ 187{
@@ -313,22 +306,13 @@ static int axp20x_pek_probe(struct platform_device *pdev)
313 return error; 306 return error;
314 } 307 }
315 308
316 error = sysfs_create_group(&pdev->dev.kobj, &axp20x_attribute_group); 309 error = devm_device_add_group(&pdev->dev, &axp20x_attribute_group);
317 if (error) { 310 if (error) {
318 dev_err(&pdev->dev, "Failed to create sysfs attributes: %d\n", 311 dev_err(&pdev->dev, "Failed to create sysfs attributes: %d\n",
319 error); 312 error);
320 return error; 313 return error;
321 } 314 }
322 315
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
332 platform_set_drvdata(pdev, axp20x_pek); 316 platform_set_drvdata(pdev, axp20x_pek);
333 317
334 return 0; 318 return 0;
diff --git a/drivers/input/rmi4/rmi_f01.c b/drivers/input/rmi4/rmi_f01.c
index 7f7e9176f7ea..6dca3c0fbb4a 100644
--- a/drivers/input/rmi4/rmi_f01.c
+++ b/drivers/input/rmi4/rmi_f01.c
@@ -570,18 +570,14 @@ static int rmi_f01_probe(struct rmi_function *fn)
570 570
571 dev_set_drvdata(&fn->dev, f01); 571 dev_set_drvdata(&fn->dev, f01);
572 572
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);
574 if (error) 574 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);
576 577
577 return 0; 578 return 0;
578} 579}
579 580
580static void rmi_f01_remove(struct rmi_function *fn)
581{
582 sysfs_remove_group(&fn->rmi_dev->dev.kobj, &rmi_f01_attr_group);
583}
584
585static int rmi_f01_config(struct rmi_function *fn) 581static int rmi_f01_config(struct rmi_function *fn)
586{ 582{
587 struct f01_data *f01 = dev_get_drvdata(&fn->dev); 583 struct f01_data *f01 = dev_get_drvdata(&fn->dev);
@@ -721,7 +717,6 @@ struct rmi_function_handler rmi_f01_handler = {
721 }, 717 },
722 .func = 0x01, 718 .func = 0x01,
723 .probe = rmi_f01_probe, 719 .probe = rmi_f01_probe,
724 .remove = rmi_f01_remove,
725 .config = rmi_f01_config, 720 .config = rmi_f01_config,
726 .attention = rmi_f01_attention, 721 .attention = rmi_f01_attention,
727 .suspend = rmi_f01_suspend, 722 .suspend = rmi_f01_suspend,
diff --git a/include/linux/device.h b/include/linux/device.h
index 723cd54b94da..c29dd5ec7f6a 100644
--- a/include/linux/device.h
+++ b/include/linux/device.h
@@ -1200,6 +1200,36 @@ struct device *device_create_with_groups(struct class *cls,
1200 const char *fmt, ...); 1200 const char *fmt, ...);
1201extern void device_destroy(struct class *cls, dev_t devt); 1201extern void device_destroy(struct class *cls, dev_t devt);
1202 1202
1203extern int __must_check device_add_groups(struct device *dev,
1204 const struct attribute_group **groups);
1205extern void device_remove_groups(struct device *dev,
1206 const struct attribute_group **groups);
1207
1208static 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
1216static 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
1224extern int __must_check devm_device_add_groups(struct device *dev,
1225 const struct attribute_group **groups);
1226extern void devm_device_remove_groups(struct device *dev,
1227 const struct attribute_group **groups);
1228extern int __must_check devm_device_add_group(struct device *dev,
1229 const struct attribute_group *grp);
1230extern void devm_device_remove_group(struct device *dev,
1231 const struct attribute_group *grp);
1232
1203/* 1233/*
1204 * Platform "fixup" functions - allow the platform to have their say 1234 * Platform "fixup" functions - allow the platform to have their say
1205 * about devices and actions that the general device layer doesn't 1235 * about devices and actions that the general device layer doesn't
diff --git a/include/linux/kobject.h b/include/linux/kobject.h
index eeab34b0f589..9e05c8b2c287 100644
--- a/include/linux/kobject.h
+++ b/include/linux/kobject.h
@@ -57,6 +57,8 @@ enum kobject_action {
57 KOBJ_MOVE, 57 KOBJ_MOVE,
58 KOBJ_ONLINE, 58 KOBJ_ONLINE,
59 KOBJ_OFFLINE, 59 KOBJ_OFFLINE,
60 KOBJ_BIND,
61 KOBJ_UNBIND,
60 KOBJ_MAX 62 KOBJ_MAX
61}; 63};
62 64
diff --git a/lib/kobject_uevent.c b/lib/kobject_uevent.c
index 719c155fce20..e590523ea476 100644
--- a/lib/kobject_uevent.c
+++ b/lib/kobject_uevent.c
@@ -52,6 +52,8 @@ static const char *kobject_actions[] = {
52 [KOBJ_MOVE] = "move", 52 [KOBJ_MOVE] = "move",
53 [KOBJ_ONLINE] = "online", 53 [KOBJ_ONLINE] = "online",
54 [KOBJ_OFFLINE] = "offline", 54 [KOBJ_OFFLINE] = "offline",
55 [KOBJ_BIND] = "bind",
56 [KOBJ_UNBIND] = "unbind",
55}; 57};
56 58
57static int kobject_action_type(const char *buf, size_t count, 59static int kobject_action_type(const char *buf, size_t count,