2007-11-28 23:23:18 +03:00
/*
* module . c - module sysfs fun for drivers
*
* This file is released under the GPLv2
*
*/
# include <linux/device.h>
# include <linux/module.h>
# include <linux/errno.h>
# include <linux/string.h>
# include "base.h"
static char * make_driver_name ( struct device_driver * drv )
{
char * driver_name ;
driver_name = kmalloc ( strlen ( drv - > name ) + strlen ( drv - > bus - > name ) + 2 ,
GFP_KERNEL ) ;
if ( ! driver_name )
return NULL ;
sprintf ( driver_name , " %s:%s " , drv - > bus - > name , drv - > name ) ;
return driver_name ;
}
static void module_create_drivers_dir ( struct module_kobject * mk )
{
if ( ! mk | | mk - > drivers_dir )
return ;
mk - > drivers_dir = kobject_create_and_add ( " drivers " , & mk - > kobj ) ;
}
void module_add_driver ( struct module * mod , struct device_driver * drv )
{
char * driver_name ;
int no_warn ;
struct module_kobject * mk = NULL ;
if ( ! drv )
return ;
if ( mod )
mk = & mod - > mkobj ;
else if ( drv - > mod_name ) {
struct kobject * mkobj ;
/* Lookup built-in module entry in /sys/modules */
mkobj = kset_find_obj ( module_kset , drv - > mod_name ) ;
if ( mkobj ) {
mk = container_of ( mkobj , struct module_kobject , kobj ) ;
/* remember our module structure */
2007-11-29 02:59:15 +03:00
drv - > p - > mkobj = mk ;
2007-11-28 23:23:18 +03:00
/* kset_find_obj took a reference */
kobject_put ( mkobj ) ;
}
}
if ( ! mk )
return ;
/* Don't check return codes; these calls are idempotent */
2007-11-29 02:59:15 +03:00
no_warn = sysfs_create_link ( & drv - > p - > kobj , & mk - > kobj , " module " ) ;
2007-11-28 23:23:18 +03:00
driver_name = make_driver_name ( drv ) ;
if ( driver_name ) {
module_create_drivers_dir ( mk ) ;
2007-11-29 02:59:15 +03:00
no_warn = sysfs_create_link ( mk - > drivers_dir , & drv - > p - > kobj ,
2007-11-28 23:23:18 +03:00
driver_name ) ;
kfree ( driver_name ) ;
}
}
void module_remove_driver ( struct device_driver * drv )
{
struct module_kobject * mk = NULL ;
char * driver_name ;
if ( ! drv )
return ;
2007-11-29 02:59:15 +03:00
sysfs_remove_link ( & drv - > p - > kobj , " module " ) ;
2007-11-28 23:23:18 +03:00
if ( drv - > owner )
mk = & drv - > owner - > mkobj ;
2007-11-29 02:59:15 +03:00
else if ( drv - > p - > mkobj )
mk = drv - > p - > mkobj ;
2007-11-28 23:23:18 +03:00
if ( mk & & mk - > drivers_dir ) {
driver_name = make_driver_name ( drv ) ;
if ( driver_name ) {
sysfs_remove_link ( mk - > drivers_dir , driver_name ) ;
kfree ( driver_name ) ;
}
}
}