diff options
author | Mark McLoughlin <markmc@redhat.com> | 2008-12-15 07:58:26 -0500 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@suse.de> | 2009-01-06 13:44:33 -0500 |
commit | 0aa0dc41bfd993491c2344870eee7a3b218551fb (patch) | |
tree | bf0896c7e0bb9f5b7e6253fc15c8846b6f188d08 /drivers/base | |
parent | 7232800ba8aca1c070d43a81cc49991f230b5da1 (diff) |
driver core: add root_device_register()
Add support for allocating root device objects which group
device objects under /sys/devices directories.
Also add a sysfs 'module' symlink which points to the owner
of the root device object. This symlink will be used in virtio
to allow userspace to determine which virtio bus implementation
a given device is associated with.
[Includes suggestions from Cornelia Huck]
Signed-off-by: Mark McLoughlin <markmc@redhat.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers/base')
-rw-r--r-- | drivers/base/core.c | 91 |
1 files changed, 91 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 | { |