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 | static char *make_driver_name(struct device_driver *drv) |
13 | { |
14 | char *driver_name; |
15 | |
16 | driver_name = kasprintf(GFP_KERNEL, fmt: "%s:%s" , drv->bus->name, drv->name); |
17 | if (!driver_name) |
18 | return NULL; |
19 | |
20 | return driver_name; |
21 | } |
22 | |
23 | static void module_create_drivers_dir(struct module_kobject *mk) |
24 | { |
25 | static DEFINE_MUTEX(drivers_dir_mutex); |
26 | |
27 | mutex_lock(lock: &drivers_dir_mutex); |
28 | if (mk && !mk->drivers_dir) |
29 | mk->drivers_dir = kobject_create_and_add(name: "drivers" , parent: &mk->kobj); |
30 | mutex_unlock(lock: &drivers_dir_mutex); |
31 | } |
32 | |
33 | 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 | if (!drv) |
40 | return; |
41 | |
42 | if (mod) |
43 | mk = &mod->mkobj; |
44 | else if (drv->mod_name) { |
45 | struct kobject *mkobj; |
46 | |
47 | /* Lookup built-in module entry in /sys/modules */ |
48 | mkobj = kset_find_obj(module_kset, drv->mod_name); |
49 | if (mkobj) { |
50 | mk = container_of(mkobj, struct module_kobject, kobj); |
51 | /* remember our module structure */ |
52 | drv->p->mkobj = mk; |
53 | /* kset_find_obj took a reference */ |
54 | kobject_put(kobj: mkobj); |
55 | } |
56 | } |
57 | |
58 | if (!mk) |
59 | return; |
60 | |
61 | /* Don't check return codes; these calls are idempotent */ |
62 | no_warn = sysfs_create_link(kobj: &drv->p->kobj, target: &mk->kobj, name: "module" ); |
63 | driver_name = make_driver_name(drv); |
64 | if (driver_name) { |
65 | module_create_drivers_dir(mk); |
66 | no_warn = sysfs_create_link(kobj: mk->drivers_dir, target: &drv->p->kobj, |
67 | name: driver_name); |
68 | kfree(objp: driver_name); |
69 | } |
70 | } |
71 | |
72 | void module_remove_driver(struct device_driver *drv) |
73 | { |
74 | struct module_kobject *mk = NULL; |
75 | char *driver_name; |
76 | |
77 | if (!drv) |
78 | return; |
79 | |
80 | sysfs_remove_link(kobj: &drv->p->kobj, name: "module" ); |
81 | |
82 | if (drv->owner) |
83 | mk = &drv->owner->mkobj; |
84 | else if (drv->p->mkobj) |
85 | mk = drv->p->mkobj; |
86 | if (mk && mk->drivers_dir) { |
87 | driver_name = make_driver_name(drv); |
88 | if (driver_name) { |
89 | sysfs_remove_link(kobj: mk->drivers_dir, name: driver_name); |
90 | kfree(objp: driver_name); |
91 | } |
92 | } |
93 | } |
94 | |