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 | */ |
