File Index
Files and directories
Sign in
FILE

module.c

File preview with syntax highlighting.

linux-6.19.14/drivers/base/module.c C
  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
 12static char *make_driver_name(const struct device_driver *drv)
 13{
 14	char *driver_name;
 15
 16	driver_name = kasprintf(GFP_KERNEL, "%s:%s", drv->bus->name, drv->name);
 17	if (!driver_name)
 18		return NULL;
 19
 20	return driver_name;
 21}
 22
 23static void module_create_drivers_dir(struct module_kobject *mk)
 24{
 25	static DEFINE_MUTEX(drivers_dir_mutex);
 26
 27	mutex_lock(&drivers_dir_mutex);
 28	if (mk && !mk->drivers_dir)
 29		mk->drivers_dir = kobject_create_and_add("drivers", &mk->kobj);
 30	mutex_unlock(&drivers_dir_mutex);
 31}
 32
 33int module_add_driver(struct module *mod, const struct device_driver *drv)
 34{
 35	char *driver_name;
 36	struct module_kobject *mk = NULL;
 37	int ret;
 38
 39	if (!drv)
 40		return 0;
 41
 42	if (mod)
 43		mk = &mod->mkobj;
 44	else if (drv->mod_name) {
 45		/* Lookup or create built-in module entry in /sys/modules */
 46		mk = lookup_or_create_module_kobject(drv->mod_name);
 47		if (mk) {
 48			/* remember our module structure */
 49			drv->p->mkobj = mk;
 50			/* lookup_or_create_module_kobject took a reference */
 51			kobject_put(&mk->kobj);
 52		}
 53	}
 54
 55	if (!mk)
 56		return 0;
 57
 58	ret = sysfs_create_link(&drv->p->kobj, &mk->kobj, "module");
 59	if (ret)
 60		return ret;
 61
 62	driver_name = make_driver_name(drv);
 63	if (!driver_name) {
 64		ret = -ENOMEM;
 65		goto out_remove_kobj;
 66	}
 67
 68	module_create_drivers_dir(mk);
 69	if (!mk->drivers_dir) {
 70		ret = -EINVAL;
 71		goto out_free_driver_name;
 72	}
 73
 74	ret = sysfs_create_link(mk->drivers_dir, &drv->p->kobj, driver_name);
 75	if (ret)
 76		goto out_remove_drivers_dir;
 77
 78	kfree(driver_name);
 79
 80	return 0;
 81
 82out_remove_drivers_dir:
 83	sysfs_remove_link(mk->drivers_dir, driver_name);
 84
 85out_free_driver_name:
 86	kfree(driver_name);
 87
 88out_remove_kobj:
 89	sysfs_remove_link(&drv->p->kobj, "module");
 90	return ret;
 91}
 92
 93void module_remove_driver(const struct device_driver *drv)
 94{
 95	struct module_kobject *mk = NULL;
 96	char *driver_name;
 97
 98	if (!drv)
 99		return;
100
101	sysfs_remove_link(&drv->p->kobj, "module");
102
103	if (drv->owner)
104		mk = &drv->owner->mkobj;
105	else if (drv->p->mkobj)
106		mk = drv->p->mkobj;
107	if (mk && mk->drivers_dir) {
108		driver_name = make_driver_name(drv);
109		if (driver_name) {
110			sysfs_remove_link(mk->drivers_dir, driver_name);
111			kfree(driver_name);
112		}
113	}
114}
~/ Read-only file preview.