[Bluetooth] Add open and close callbacks for HID device
[pandora-kernel.git] / kernel / module.c
index 0f4489a..8c25b1a 100644 (file)
@@ -537,6 +537,8 @@ static int already_uses(struct module *a, struct module *b)
 static int use_module(struct module *a, struct module *b)
 {
        struct module_use *use;
+       int no_warn;
+
        if (b == NULL || already_uses(a, b)) return 1;
 
        if (!strong_try_module_get(b))
@@ -552,6 +554,7 @@ static int use_module(struct module *a, struct module *b)
 
        use->module_which_uses = a;
        list_add(&use->list, &b->modules_which_use_me);
+       no_warn = sysfs_create_link(b->holders_dir, &a->mkobj.kobj, a->name);
        return 1;
 }
 
@@ -569,6 +572,7 @@ static void module_unload_free(struct module *mod)
                                module_put(i);
                                list_del(&use->list);
                                kfree(use);
+                               sysfs_remove_link(i->holders_dir, mod->name);
                                /* There can be at most one match. */
                                break;
                        }
@@ -649,20 +653,11 @@ static void wait_for_zero_refcount(struct module *mod)
        mutex_lock(&module_mutex);
 }
 
-asmlinkage long
-sys_delete_module(const char __user *name_user, unsigned int flags)
+int delete_module(const char *name, unsigned int flags)
 {
        struct module *mod;
-       char name[MODULE_NAME_LEN];
        int ret, forced = 0;
 
-       if (!capable(CAP_SYS_MODULE))
-               return -EPERM;
-
-       if (strncpy_from_user(name, name_user, MODULE_NAME_LEN-1) < 0)
-               return -EFAULT;
-       name[MODULE_NAME_LEN-1] = '\0';
-
        if (mutex_lock_interruptible(&module_mutex) != 0)
                return -EINTR;
 
@@ -723,6 +718,21 @@ sys_delete_module(const char __user *name_user, unsigned int flags)
        return ret;
 }
 
+asmlinkage long
+sys_delete_module(const char __user *name_user, unsigned int flags)
+{
+       char name[MODULE_NAME_LEN];
+
+       if (!capable(CAP_SYS_MODULE))
+               return -EPERM;
+
+       if (strncpy_from_user(name, name_user, MODULE_NAME_LEN-1) < 0)
+               return -EFAULT;
+       name[MODULE_NAME_LEN-1] = '\0';
+
+       return delete_module(name, flags);
+}
+
 static void print_unload_info(struct seq_file *m, struct module *mod)
 {
        struct module_use *use;
@@ -1064,7 +1074,8 @@ static inline void remove_sect_attrs(struct module *mod)
 }
 #endif /* CONFIG_KALLSYMS */
 
-static int module_add_modinfo_attrs(struct module *mod)
+#ifdef CONFIG_SYSFS
+int module_add_modinfo_attrs(struct module *mod)
 {
        struct module_attribute *attr;
        struct module_attribute *temp_attr;
@@ -1090,7 +1101,7 @@ static int module_add_modinfo_attrs(struct module *mod)
        return error;
 }
 
-static void module_remove_modinfo_attrs(struct module *mod)
+void module_remove_modinfo_attrs(struct module *mod)
 {
        struct module_attribute *attr;
        int i;
@@ -1105,10 +1116,10 @@ static void module_remove_modinfo_attrs(struct module *mod)
        }
        kfree(mod->modinfo_attrs);
 }
+#endif
 
-static int mod_sysfs_setup(struct module *mod,
-                          struct kernel_param *kparam,
-                          unsigned int num_params)
+#ifdef CONFIG_SYSFS
+int mod_sysfs_init(struct module *mod)
 {
        int err;
 
@@ -1125,21 +1136,30 @@ static int mod_sysfs_setup(struct module *mod,
        kobj_set_kset_s(&mod->mkobj, module_subsys);
        mod->mkobj.mod = mod;
 
-       /* delay uevent until full sysfs population */
        kobject_init(&mod->mkobj.kobj);
+
+out:
+       return err;
+}
+
+int mod_sysfs_setup(struct module *mod,
+                          struct kernel_param *kparam,
+                          unsigned int num_params)
+{
+       int err;
+
+       /* delay uevent until full sysfs population */
        err = kobject_add(&mod->mkobj.kobj);
        if (err)
                goto out;
 
-       mod->mkobj.drivers_dir = kobject_add_dir(&mod->mkobj.kobj, "drivers");
-       if (!mod->mkobj.drivers_dir) {
-               err = -ENOMEM;
+       mod->holders_dir = kobject_add_dir(&mod->mkobj.kobj, "holders");
+       if (!mod->holders_dir)
                goto out_unreg;
-       }
 
        err = module_param_sysfs_setup(mod, kparam, num_params);
        if (err)
-               goto out_unreg_drivers;
+               goto out_unreg_holders;
 
        err = module_add_modinfo_attrs(mod);
        if (err)
@@ -1150,21 +1170,22 @@ static int mod_sysfs_setup(struct module *mod,
 
 out_unreg_param:
        module_param_sysfs_remove(mod);
-out_unreg_drivers:
-       kobject_unregister(mod->mkobj.drivers_dir);
+out_unreg_holders:
+       kobject_unregister(mod->holders_dir);
 out_unreg:
        kobject_del(&mod->mkobj.kobj);
        kobject_put(&mod->mkobj.kobj);
 out:
        return err;
 }
+#endif
 
 static void mod_kobject_remove(struct module *mod)
 {
        module_remove_modinfo_attrs(mod);
        module_param_sysfs_remove(mod);
        kobject_unregister(mod->mkobj.drivers_dir);
-
+       kobject_unregister(mod->holders_dir);
        kobject_unregister(&mod->mkobj.kobj);
 }
 
@@ -1768,6 +1789,10 @@ static struct module *load_module(void __user *umod,
        /* Now we've moved module, initialize linked lists, etc. */
        module_unload_init(mod);
 
+       /* Initialize kobject, so we can reference it. */
+       if (mod_sysfs_init(mod) != 0)
+               goto cleanup;
+
        /* Set up license info based on the info section */
        set_license(mod, get_modinfo(sechdrs, infoindex, "license"));
 
@@ -2327,6 +2352,7 @@ void print_modules(void)
        printk("\n");
 }
 
+#ifdef CONFIG_SYSFS
 static char *make_driver_name(struct device_driver *drv)
 {
        char *driver_name;
@@ -2340,6 +2366,14 @@ static char *make_driver_name(struct device_driver *drv)
        return driver_name;
 }
 
+static void module_create_drivers_dir(struct module_kobject *mk)
+{
+       if (!mk || mk->drivers_dir)
+               return;
+
+       mk->drivers_dir = kobject_add_dir(&mk->kobj, "drivers");
+}
+
 void module_add_driver(struct module *mod, struct device_driver *drv)
 {
        char *driver_name;
@@ -2367,6 +2401,7 @@ void module_add_driver(struct module *mod, struct device_driver *drv)
        no_warn = sysfs_create_link(&drv->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->kobj,
                                            driver_name);
                kfree(driver_name);
@@ -2392,6 +2427,7 @@ void module_remove_driver(struct device_driver *drv)
        }
 }
 EXPORT_SYMBOL(module_remove_driver);
+#endif
 
 #ifdef CONFIG_MODVERSIONS
 /* Generate the signature for struct module here, too, for modversions. */