diff options
Diffstat (limited to 'kernel/module.c')
-rw-r--r-- | kernel/module.c | 42 |
1 files changed, 36 insertions, 6 deletions
diff --git a/kernel/module.c b/kernel/module.c index b565eaeff7e6..d0f2260a0210 100644 --- a/kernel/module.c +++ b/kernel/module.c @@ -1132,8 +1132,10 @@ static int mod_sysfs_setup(struct module *mod, goto out; mod->drivers_dir = kobject_add_dir(&mod->mkobj.kobj, "drivers"); - if (!mod->drivers_dir) + if (!mod->drivers_dir) { + err = -ENOMEM; goto out_unreg; + } err = module_param_sysfs_setup(mod, kparam, num_params); if (err) @@ -1146,10 +1148,10 @@ static int mod_sysfs_setup(struct module *mod, kobject_uevent(&mod->mkobj.kobj, KOBJ_ADD); return 0; -out_unreg_drivers: - kobject_unregister(mod->drivers_dir); out_unreg_param: module_param_sysfs_remove(mod); +out_unreg_drivers: + kobject_unregister(mod->drivers_dir); out_unreg: kobject_del(&mod->mkobj.kobj); kobject_put(&mod->mkobj.kobj); @@ -2325,8 +2327,22 @@ void print_modules(void) printk("\n"); } +static char *make_driver_name(struct device_driver *drv) +{ + char *driver_name; + + driver_name = kmalloc(strlen(drv->name) + strlen(drv->bus->name) + 2, + GFP_KERNEL); + if (!driver_name) + return NULL; + + sprintf(driver_name, "%s:%s", drv->bus->name, drv->name); + return driver_name; +} + void module_add_driver(struct module *mod, struct device_driver *drv) { + char *driver_name; int no_warn; if (!mod || !drv) @@ -2334,17 +2350,31 @@ void module_add_driver(struct module *mod, struct device_driver *drv) /* Don't check return codes; these calls are idempotent */ no_warn = sysfs_create_link(&drv->kobj, &mod->mkobj.kobj, "module"); - no_warn = sysfs_create_link(mod->drivers_dir, &drv->kobj, drv->name); + driver_name = make_driver_name(drv); + if (driver_name) { + no_warn = sysfs_create_link(mod->drivers_dir, &drv->kobj, + driver_name); + kfree(driver_name); + } } EXPORT_SYMBOL(module_add_driver); void module_remove_driver(struct device_driver *drv) { + char *driver_name; + if (!drv) return; + sysfs_remove_link(&drv->kobj, "module"); - if (drv->owner && drv->owner->drivers_dir) - sysfs_remove_link(drv->owner->drivers_dir, drv->name); + if (drv->owner && drv->owner->drivers_dir) { + driver_name = make_driver_name(drv); + if (driver_name) { + sysfs_remove_link(drv->owner->drivers_dir, + driver_name); + kfree(driver_name); + } + } } EXPORT_SYMBOL(module_remove_driver); |