summaryrefslogtreecommitdiff
path: root/drivers/base/module.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/base/module.c')
-rw-r--r--drivers/base/module.c63
1 files changed, 42 insertions, 21 deletions
diff --git a/drivers/base/module.c b/drivers/base/module.c
index 46ad4d636731..218aaa096455 100644
--- a/drivers/base/module.c
+++ b/drivers/base/module.c
@@ -9,7 +9,7 @@
#include <linux/string.h>
#include "base.h"
-static char *make_driver_name(struct device_driver *drv)
+static char *make_driver_name(const struct device_driver *drv)
{
char *driver_name;
@@ -30,46 +30,67 @@ static void module_create_drivers_dir(struct module_kobject *mk)
mutex_unlock(&drivers_dir_mutex);
}
-void module_add_driver(struct module *mod, struct device_driver *drv)
+int module_add_driver(struct module *mod, const struct device_driver *drv)
{
char *driver_name;
- int no_warn;
struct module_kobject *mk = NULL;
+ int ret;
if (!drv)
- return;
+ return 0;
if (mod)
mk = &mod->mkobj;
else if (drv->mod_name) {
- struct kobject *mkobj;
-
- /* Lookup built-in module entry in /sys/modules */
- mkobj = kset_find_obj(module_kset, drv->mod_name);
- if (mkobj) {
- mk = container_of(mkobj, struct module_kobject, kobj);
+ /* Lookup or create built-in module entry in /sys/modules */
+ mk = lookup_or_create_module_kobject(drv->mod_name);
+ if (mk) {
/* remember our module structure */
drv->p->mkobj = mk;
- /* kset_find_obj took a reference */
- kobject_put(mkobj);
+ /* lookup_or_create_module_kobject took a reference */
+ kobject_put(&mk->kobj);
}
}
if (!mk)
- return;
+ return 0;
+
+ ret = sysfs_create_link(&drv->p->kobj, &mk->kobj, "module");
+ if (ret)
+ return ret;
- /* Don't check return codes; these calls are idempotent */
- no_warn = sysfs_create_link(&drv->p->kobj, &mk->kobj, "module");
driver_name = make_driver_name(drv);
- if (driver_name) {
- module_create_drivers_dir(mk);
- no_warn = sysfs_create_link(mk->drivers_dir, &drv->p->kobj,
- driver_name);
- kfree(driver_name);
+ if (!driver_name) {
+ ret = -ENOMEM;
+ goto out_remove_kobj;
}
+
+ module_create_drivers_dir(mk);
+ if (!mk->drivers_dir) {
+ ret = -EINVAL;
+ goto out_free_driver_name;
+ }
+
+ ret = sysfs_create_link(mk->drivers_dir, &drv->p->kobj, driver_name);
+ if (ret)
+ goto out_remove_drivers_dir;
+
+ kfree(driver_name);
+
+ return 0;
+
+out_remove_drivers_dir:
+ sysfs_remove_link(mk->drivers_dir, driver_name);
+
+out_free_driver_name:
+ kfree(driver_name);
+
+out_remove_kobj:
+ sysfs_remove_link(&drv->p->kobj, "module");
+ return ret;
}
-void module_remove_driver(struct device_driver *drv)
+void module_remove_driver(const struct device_driver *drv)
{
struct module_kobject *mk = NULL;
char *driver_name;