X-Git-Url: https://git.karo-electronics.de/?a=blobdiff_plain;f=kernel%2Fmodule.c;h=d0f2260a02105902fba2217e51451349777ca21d;hb=e7b3ca08549caccf5d6e1cf066780bf4f0ae77a7;hp=d9eae45d0145a077d6b32d2b29156f9d3b18bfdd;hpb=4522d58275f124105819723e24e912c8e5bf3cdd;p=mv-sheeva.git diff --git a/kernel/module.c b/kernel/module.c index d9eae45d014..d0f2260a021 100644 --- a/kernel/module.c +++ b/kernel/module.c @@ -824,9 +824,34 @@ static inline void module_unload_init(struct module *mod) } #endif /* CONFIG_MODULE_UNLOAD */ +static ssize_t show_initstate(struct module_attribute *mattr, + struct module *mod, char *buffer) +{ + const char *state = "unknown"; + + switch (mod->state) { + case MODULE_STATE_LIVE: + state = "live"; + break; + case MODULE_STATE_COMING: + state = "coming"; + break; + case MODULE_STATE_GOING: + state = "going"; + break; + } + return sprintf(buffer, "%s\n", state); +} + +static struct module_attribute initstate = { + .attr = { .name = "initstate", .mode = 0444, .owner = THIS_MODULE }, + .show = show_initstate, +}; + static struct module_attribute *modinfo_attrs[] = { &modinfo_version, &modinfo_srcversion, + &initstate, #ifdef CONFIG_MODULE_UNLOAD &refcnt, #endif @@ -1107,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) @@ -1121,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); @@ -2300,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) @@ -2309,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);