Branch data Line data Source code
1 : : // SPDX-License-Identifier: GPL-2.0 2 : : /* 3 : : * module.c - module sysfs fun for drivers 4 : : */ 5 : : #include <linux/device.h> 6 : : #include <linux/module.h> 7 : : #include <linux/errno.h> 8 : : #include <linux/slab.h> 9 : : #include <linux/string.h> 10 : : #include "base.h" 11 : : 12 : 3 : static char *make_driver_name(struct device_driver *drv) 13 : : { 14 : : char *driver_name; 15 : : 16 : 3 : driver_name = kasprintf(GFP_KERNEL, "%s:%s", drv->bus->name, drv->name); 17 : 3 : if (!driver_name) 18 : : return NULL; 19 : : 20 : 3 : return driver_name; 21 : : } 22 : : 23 : 3 : static void module_create_drivers_dir(struct module_kobject *mk) 24 : : { 25 : : static DEFINE_MUTEX(drivers_dir_mutex); 26 : : 27 : 3 : mutex_lock(&drivers_dir_mutex); 28 : 3 : if (mk && !mk->drivers_dir) 29 : 3 : mk->drivers_dir = kobject_create_and_add("drivers", &mk->kobj); 30 : 3 : mutex_unlock(&drivers_dir_mutex); 31 : 3 : } 32 : : 33 : 3 : void module_add_driver(struct module *mod, struct device_driver *drv) 34 : : { 35 : : char *driver_name; 36 : : int no_warn; 37 : : struct module_kobject *mk = NULL; 38 : : 39 : 3 : if (!drv) 40 : : return; 41 : : 42 : 3 : if (mod) 43 : 3 : mk = &mod->mkobj; 44 : 3 : else if (drv->mod_name) { 45 : : struct kobject *mkobj; 46 : : 47 : : /* Lookup built-in module entry in /sys/modules */ 48 : 3 : mkobj = kset_find_obj(module_kset, drv->mod_name); 49 : 3 : if (mkobj) { 50 : : mk = container_of(mkobj, struct module_kobject, kobj); 51 : : /* remember our module structure */ 52 : 3 : drv->p->mkobj = mk; 53 : : /* kset_find_obj took a reference */ 54 : 3 : kobject_put(mkobj); 55 : : } 56 : : } 57 : : 58 : 3 : if (!mk) 59 : : return; 60 : : 61 : : /* Don't check return codes; these calls are idempotent */ 62 : 3 : no_warn = sysfs_create_link(&drv->p->kobj, &mk->kobj, "module"); 63 : 3 : driver_name = make_driver_name(drv); 64 : 3 : if (driver_name) { 65 : 3 : module_create_drivers_dir(mk); 66 : 3 : no_warn = sysfs_create_link(mk->drivers_dir, &drv->p->kobj, 67 : : driver_name); 68 : 3 : kfree(driver_name); 69 : : } 70 : : } 71 : : 72 : 0 : void module_remove_driver(struct device_driver *drv) 73 : : { 74 : : struct module_kobject *mk = NULL; 75 : : char *driver_name; 76 : : 77 : 0 : if (!drv) 78 : 0 : return; 79 : : 80 : 0 : sysfs_remove_link(&drv->p->kobj, "module"); 81 : : 82 : 0 : if (drv->owner) 83 : 0 : mk = &drv->owner->mkobj; 84 : 0 : else if (drv->p->mkobj) 85 : : mk = drv->p->mkobj; 86 : 0 : if (mk && mk->drivers_dir) { 87 : 0 : driver_name = make_driver_name(drv); 88 : 0 : if (driver_name) { 89 : 0 : sysfs_remove_link(mk->drivers_dir, driver_name); 90 : 0 : kfree(driver_name); 91 : : } 92 : : } 93 : : }