Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 /*
0003  * module.c - module sysfs fun for drivers
0004  */
0005 #include <linux/device.h>
0006 #include <linux/module.h>
0007 #include <linux/errno.h>
0008 #include <linux/slab.h>
0009 #include <linux/string.h>
0010 #include "base.h"
0011 
0012 static char *make_driver_name(struct device_driver *drv)
0013 {
0014     char *driver_name;
0015 
0016     driver_name = kasprintf(GFP_KERNEL, "%s:%s", drv->bus->name, drv->name);
0017     if (!driver_name)
0018         return NULL;
0019 
0020     return driver_name;
0021 }
0022 
0023 static void module_create_drivers_dir(struct module_kobject *mk)
0024 {
0025     static DEFINE_MUTEX(drivers_dir_mutex);
0026 
0027     mutex_lock(&drivers_dir_mutex);
0028     if (mk && !mk->drivers_dir)
0029         mk->drivers_dir = kobject_create_and_add("drivers", &mk->kobj);
0030     mutex_unlock(&drivers_dir_mutex);
0031 }
0032 
0033 void module_add_driver(struct module *mod, struct device_driver *drv)
0034 {
0035     char *driver_name;
0036     int no_warn;
0037     struct module_kobject *mk = NULL;
0038 
0039     if (!drv)
0040         return;
0041 
0042     if (mod)
0043         mk = &mod->mkobj;
0044     else if (drv->mod_name) {
0045         struct kobject *mkobj;
0046 
0047         /* Lookup built-in module entry in /sys/modules */
0048         mkobj = kset_find_obj(module_kset, drv->mod_name);
0049         if (mkobj) {
0050             mk = container_of(mkobj, struct module_kobject, kobj);
0051             /* remember our module structure */
0052             drv->p->mkobj = mk;
0053             /* kset_find_obj took a reference */
0054             kobject_put(mkobj);
0055         }
0056     }
0057 
0058     if (!mk)
0059         return;
0060 
0061     /* Don't check return codes; these calls are idempotent */
0062     no_warn = sysfs_create_link(&drv->p->kobj, &mk->kobj, "module");
0063     driver_name = make_driver_name(drv);
0064     if (driver_name) {
0065         module_create_drivers_dir(mk);
0066         no_warn = sysfs_create_link(mk->drivers_dir, &drv->p->kobj,
0067                         driver_name);
0068         kfree(driver_name);
0069     }
0070 }
0071 
0072 void module_remove_driver(struct device_driver *drv)
0073 {
0074     struct module_kobject *mk = NULL;
0075     char *driver_name;
0076 
0077     if (!drv)
0078         return;
0079 
0080     sysfs_remove_link(&drv->p->kobj, "module");
0081 
0082     if (drv->owner)
0083         mk = &drv->owner->mkobj;
0084     else if (drv->p->mkobj)
0085         mk = drv->p->mkobj;
0086     if (mk && mk->drivers_dir) {
0087         driver_name = make_driver_name(drv);
0088         if (driver_name) {
0089             sysfs_remove_link(mk->drivers_dir, driver_name);
0090             kfree(driver_name);
0091         }
0092     }
0093 }