diff options
-rw-r--r-- | drivers/base/core.c | 91 | ||||
-rw-r--r-- | include/linux/device.h | 11 |
2 files changed, 102 insertions, 0 deletions
diff --git a/drivers/base/core.c b/drivers/base/core.c index ee555d7d5c3f..61df508fa62b 100644 --- a/drivers/base/core.c +++ b/drivers/base/core.c | |||
@@ -1217,6 +1217,97 @@ EXPORT_SYMBOL_GPL(put_device); | |||
1217 | EXPORT_SYMBOL_GPL(device_create_file); | 1217 | EXPORT_SYMBOL_GPL(device_create_file); |
1218 | EXPORT_SYMBOL_GPL(device_remove_file); | 1218 | EXPORT_SYMBOL_GPL(device_remove_file); |
1219 | 1219 | ||
1220 | struct root_device | ||
1221 | { | ||
1222 | struct device dev; | ||
1223 | struct module *owner; | ||
1224 | }; | ||
1225 | |||
1226 | #define to_root_device(dev) container_of(dev, struct root_device, dev) | ||
1227 | |||
1228 | static void root_device_release(struct device *dev) | ||
1229 | { | ||
1230 | kfree(to_root_device(dev)); | ||
1231 | } | ||
1232 | |||
1233 | /** | ||
1234 | * __root_device_register - allocate and register a root device | ||
1235 | * @name: root device name | ||
1236 | * @owner: owner module of the root device, usually THIS_MODULE | ||
1237 | * | ||
1238 | * This function allocates a root device and registers it | ||
1239 | * using device_register(). In order to free the returned | ||
1240 | * device, use root_device_unregister(). | ||
1241 | * | ||
1242 | * Root devices are dummy devices which allow other devices | ||
1243 | * to be grouped under /sys/devices. Use this function to | ||
1244 | * allocate a root device and then use it as the parent of | ||
1245 | * any device which should appear under /sys/devices/{name} | ||
1246 | * | ||
1247 | * The /sys/devices/{name} directory will also contain a | ||
1248 | * 'module' symlink which points to the @owner directory | ||
1249 | * in sysfs. | ||
1250 | * | ||
1251 | * Note: You probably want to use root_device_register(). | ||
1252 | */ | ||
1253 | struct device *__root_device_register(const char *name, struct module *owner) | ||
1254 | { | ||
1255 | struct root_device *root; | ||
1256 | int err = -ENOMEM; | ||
1257 | |||
1258 | root = kzalloc(sizeof(struct root_device), GFP_KERNEL); | ||
1259 | if (!root) | ||
1260 | return ERR_PTR(err); | ||
1261 | |||
1262 | err = dev_set_name(&root->dev, name); | ||
1263 | if (err) { | ||
1264 | kfree(root); | ||
1265 | return ERR_PTR(err); | ||
1266 | } | ||
1267 | |||
1268 | root->dev.release = root_device_release; | ||
1269 | |||
1270 | err = device_register(&root->dev); | ||
1271 | if (err) { | ||
1272 | put_device(&root->dev); | ||
1273 | return ERR_PTR(err); | ||
1274 | } | ||
1275 | |||
1276 | #ifdef CONFIG_MODULE /* gotta find a "cleaner" way to do this */ | ||
1277 | if (owner) { | ||
1278 | struct module_kobject *mk = &owner->mkobj; | ||
1279 | |||
1280 | err = sysfs_create_link(&root->dev.kobj, &mk->kobj, "module"); | ||
1281 | if (err) { | ||
1282 | device_unregister(&root->dev); | ||
1283 | return ERR_PTR(err); | ||
1284 | } | ||
1285 | root->owner = owner; | ||
1286 | } | ||
1287 | #endif | ||
1288 | |||
1289 | return &root->dev; | ||
1290 | } | ||
1291 | EXPORT_SYMBOL_GPL(__root_device_register); | ||
1292 | |||
1293 | /** | ||
1294 | * root_device_unregister - unregister and free a root device | ||
1295 | * @root: device going away. | ||
1296 | * | ||
1297 | * This function unregisters and cleans up a device that was created by | ||
1298 | * root_device_register(). | ||
1299 | */ | ||
1300 | void root_device_unregister(struct device *dev) | ||
1301 | { | ||
1302 | struct root_device *root = to_root_device(dev); | ||
1303 | |||
1304 | if (root->owner) | ||
1305 | sysfs_remove_link(&root->dev.kobj, "module"); | ||
1306 | |||
1307 | device_unregister(dev); | ||
1308 | } | ||
1309 | EXPORT_SYMBOL_GPL(root_device_unregister); | ||
1310 | |||
1220 | 1311 | ||
1221 | static void device_create_release(struct device *dev) | 1312 | static void device_create_release(struct device *dev) |
1222 | { | 1313 | { |
diff --git a/include/linux/device.h b/include/linux/device.h index b97a0cf1eb05..7d9da4b4993f 100644 --- a/include/linux/device.h +++ b/include/linux/device.h | |||
@@ -483,6 +483,17 @@ extern int device_rename(struct device *dev, char *new_name); | |||
483 | extern int device_move(struct device *dev, struct device *new_parent); | 483 | extern int device_move(struct device *dev, struct device *new_parent); |
484 | 484 | ||
485 | /* | 485 | /* |
486 | * Root device objects for grouping under /sys/devices | ||
487 | */ | ||
488 | extern struct device *__root_device_register(const char *name, | ||
489 | struct module *owner); | ||
490 | static inline struct device *root_device_register(const char *name) | ||
491 | { | ||
492 | return __root_device_register(name, THIS_MODULE); | ||
493 | } | ||
494 | extern void root_device_unregister(struct device *root); | ||
495 | |||
496 | /* | ||
486 | * Manual binding of a device to driver. See drivers/base/bus.c | 497 | * Manual binding of a device to driver. See drivers/base/bus.c |
487 | * for information on use. | 498 | * for information on use. |
488 | */ | 499 | */ |