2005-04-17 02:20:36 +04:00
/*
* driver . c - centralized device driver management
*
* Copyright ( c ) 2002 - 3 Patrick Mochel
* Copyright ( c ) 2002 - 3 Open Source Development Labs
2007-11-29 02:59:15 +03:00
* Copyright ( c ) 2007 Greg Kroah - Hartman < gregkh @ suse . de >
* Copyright ( c ) 2007 Novell Inc .
2005-04-17 02:20:36 +04:00
*
* 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"
2008-01-25 09:50:12 +03:00
static struct device * next_device ( struct klist_iter * i )
2005-03-21 23:25:36 +03:00
{
2008-01-25 09:50:12 +03:00
struct klist_node * n = klist_next ( i ) ;
2008-12-16 23:25:49 +03:00
struct device * dev = NULL ;
struct device_private * dev_prv ;
if ( n ) {
dev_prv = to_device_private_driver ( n ) ;
dev = dev_prv - > device ;
}
return dev ;
2005-03-21 23:25:36 +03:00
}
2005-03-21 21:59:56 +03:00
/**
2008-01-25 09:50:12 +03:00
* driver_for_each_device - Iterator for devices bound to a driver .
* @ drv : Driver we ' re iterating .
* @ start : Device to begin with
* @ data : Data to pass to the callback .
* @ fn : Function to call for each device .
2005-03-21 21:59:56 +03:00
*
2008-01-25 09:50:12 +03:00
* Iterate over the @ drv ' s list of devices calling @ fn for each one .
2005-03-21 21:59:56 +03:00
*/
2008-01-25 09:50:12 +03:00
int driver_for_each_device ( struct device_driver * drv , struct device * start ,
void * data , int ( * fn ) ( struct device * , void * ) )
2005-03-21 21:59:56 +03:00
{
2005-03-21 23:25:36 +03:00
struct klist_iter i ;
2008-01-25 09:50:12 +03:00
struct device * dev ;
2005-03-21 21:59:56 +03:00
int error = 0 ;
2005-03-21 23:25:36 +03:00
if ( ! drv )
return - EINVAL ;
2007-11-29 02:59:15 +03:00
klist_iter_init_node ( & drv - > p - > klist_devices , & i ,
2008-12-16 23:25:49 +03:00
start ? & start - > p - > knode_driver : NULL ) ;
2005-03-21 23:25:36 +03:00
while ( ( dev = next_device ( & i ) ) & & ! error )
2005-03-21 21:59:56 +03:00
error = fn ( dev , data ) ;
2005-03-21 23:25:36 +03:00
klist_iter_exit ( & i ) ;
2005-03-21 21:59:56 +03:00
return error ;
}
2005-03-22 23:17:13 +03:00
EXPORT_SYMBOL_GPL ( driver_for_each_device ) ;
2005-03-21 21:59:56 +03:00
2005-06-22 18:59:51 +04:00
/**
* driver_find_device - device iterator for locating a particular device .
2005-10-23 22:59:14 +04:00
* @ drv : The device ' s driver
2005-06-22 18:59:51 +04:00
* @ start : Device to begin with
* @ data : Data to pass to match function
* @ match : Callback function to check device
*
* This is similar to the driver_for_each_device ( ) function above , but
* it returns a reference to a device that is ' found ' for later use , as
* determined by the @ match callback .
*
* The callback should return 0 if the device doesn ' t match and non - zero
* if it does . If the callback returns non - zero , this function will
* return to the caller and not iterate over any more devices .
*/
2008-01-25 09:50:12 +03:00
struct device * driver_find_device ( struct device_driver * drv ,
struct device * start , void * data ,
int ( * match ) ( struct device * dev , void * data ) )
2005-06-22 18:59:51 +04:00
{
struct klist_iter i ;
struct device * dev ;
if ( ! drv )
return NULL ;
2007-11-29 02:59:15 +03:00
klist_iter_init_node ( & drv - > p - > klist_devices , & i ,
2008-12-16 23:25:49 +03:00
( start ? & start - > p - > knode_driver : NULL ) ) ;
2005-06-22 18:59:51 +04:00
while ( ( dev = next_device ( & i ) ) )
if ( match ( dev , data ) & & get_device ( dev ) )
break ;
klist_iter_exit ( & i ) ;
return dev ;
}
EXPORT_SYMBOL_GPL ( driver_find_device ) ;
2005-04-17 02:20:36 +04:00
/**
2008-01-25 09:50:12 +03:00
* driver_create_file - create sysfs file for driver .
* @ drv : driver .
* @ attr : driver attribute descriptor .
2005-04-17 02:20:36 +04:00
*/
2008-01-25 09:50:12 +03:00
int driver_create_file ( struct device_driver * drv ,
struct driver_attribute * attr )
2005-04-17 02:20:36 +04:00
{
int error ;
2008-01-31 12:39:38 +03:00
if ( drv )
2007-11-29 02:59:15 +03:00
error = sysfs_create_file ( & drv - > p - > kobj , & attr - > attr ) ;
2008-01-31 12:39:38 +03:00
else
2005-04-17 02:20:36 +04:00
error = - EINVAL ;
return error ;
}
2008-01-25 09:50:12 +03:00
EXPORT_SYMBOL_GPL ( driver_create_file ) ;
2005-04-17 02:20:36 +04:00
/**
2008-01-25 09:50:12 +03:00
* driver_remove_file - remove sysfs file for driver .
* @ drv : driver .
* @ attr : driver attribute descriptor .
2005-04-17 02:20:36 +04:00
*/
2008-01-25 09:50:12 +03:00
void driver_remove_file ( struct device_driver * drv ,
struct driver_attribute * attr )
2005-04-17 02:20:36 +04:00
{
2008-01-31 12:39:38 +03:00
if ( drv )
2007-11-29 02:59:15 +03:00
sysfs_remove_file ( & drv - > p - > kobj , & attr - > attr ) ;
2005-04-17 02:20:36 +04:00
}
2008-01-25 09:50:12 +03:00
EXPORT_SYMBOL_GPL ( driver_remove_file ) ;
2005-04-17 02:20:36 +04:00
2007-12-19 22:54:39 +03:00
/**
* driver_add_kobj - add a kobject below the specified driver
2008-02-19 00:09:03 +03:00
* @ drv : requesting device driver
* @ kobj : kobject to add below this driver
* @ fmt : format string that names the kobject
2007-12-19 22:54:39 +03:00
*
* You really don ' t want to do this , this is only here due to one looney
* iseries driver , go poke those developers if you are annoyed about
* this . . .
*/
int driver_add_kobj ( struct device_driver * drv , struct kobject * kobj ,
const char * fmt , . . . )
{
va_list args ;
char * name ;
driver core: fix small mem leak in driver_add_kobj()
The Coverity checker spotted that we leak the storage allocated to 'name' in
int driver_add_kobj(). The leak looks legit to me - this is the code :
int driver_add_kobj(struct device_driver *drv, struct kobject *kobj,
const char *fmt, ...)
{
va_list args;
char *name;
int ret;
va_start(args, fmt);
name = kvasprintf(GFP_KERNEL, fmt, args);
^^^^^^^^ This dynamically allocates space...
va_end(args);
if (!name)
return -ENOMEM;
return kobject_add(kobj, &drv->p->kobj, "%s", name);
^^^^^^^^ This neglects to free the space allocated
}
Inside kobject_add() a copy of 'name' will be made and used. As far as I can
see, Coverity is correct in flagging this as a leak, but I'd like some
configmation before the patch is applied.
This should fix it.
Signed-off-by: Jesper Juhl <jesper.juhl@gmail.com>
Cc: Greg KH <greg@kroah.com>
Cc: Kay Sievers <kay.sievers@vrfy.org>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2008-03-29 00:16:12 +03:00
int ret ;
2007-12-19 22:54:39 +03:00
va_start ( args , fmt ) ;
name = kvasprintf ( GFP_KERNEL , fmt , args ) ;
va_end ( args ) ;
if ( ! name )
return - ENOMEM ;
driver core: fix small mem leak in driver_add_kobj()
The Coverity checker spotted that we leak the storage allocated to 'name' in
int driver_add_kobj(). The leak looks legit to me - this is the code :
int driver_add_kobj(struct device_driver *drv, struct kobject *kobj,
const char *fmt, ...)
{
va_list args;
char *name;
int ret;
va_start(args, fmt);
name = kvasprintf(GFP_KERNEL, fmt, args);
^^^^^^^^ This dynamically allocates space...
va_end(args);
if (!name)
return -ENOMEM;
return kobject_add(kobj, &drv->p->kobj, "%s", name);
^^^^^^^^ This neglects to free the space allocated
}
Inside kobject_add() a copy of 'name' will be made and used. As far as I can
see, Coverity is correct in flagging this as a leak, but I'd like some
configmation before the patch is applied.
This should fix it.
Signed-off-by: Jesper Juhl <jesper.juhl@gmail.com>
Cc: Greg KH <greg@kroah.com>
Cc: Kay Sievers <kay.sievers@vrfy.org>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2008-03-29 00:16:12 +03:00
ret = kobject_add ( kobj , & drv - > p - > kobj , " %s " , name ) ;
kfree ( name ) ;
return ret ;
2007-12-19 22:54:39 +03:00
}
EXPORT_SYMBOL_GPL ( driver_add_kobj ) ;
2005-04-17 02:20:36 +04:00
/**
2008-01-25 09:50:12 +03:00
* get_driver - increment driver reference count .
* @ drv : driver .
2005-04-17 02:20:36 +04:00
*/
2008-01-25 09:50:12 +03:00
struct device_driver * get_driver ( struct device_driver * drv )
2005-04-17 02:20:36 +04:00
{
2007-11-29 02:59:15 +03:00
if ( drv ) {
struct driver_private * priv ;
struct kobject * kobj ;
kobj = kobject_get ( & drv - > p - > kobj ) ;
priv = to_driver ( kobj ) ;
return priv - > driver ;
}
return NULL ;
2005-04-17 02:20:36 +04:00
}
2008-01-25 09:50:12 +03:00
EXPORT_SYMBOL_GPL ( get_driver ) ;
2005-04-17 02:20:36 +04:00
/**
2008-01-25 09:50:12 +03:00
* put_driver - decrement driver ' s refcount .
* @ drv : driver .
2005-04-17 02:20:36 +04:00
*/
2008-01-25 09:50:12 +03:00
void put_driver ( struct device_driver * drv )
2005-04-17 02:20:36 +04:00
{
2007-11-29 02:59:15 +03:00
kobject_put ( & drv - > p - > kobj ) ;
2005-04-17 02:20:36 +04:00
}
2008-01-25 09:50:12 +03:00
EXPORT_SYMBOL_GPL ( put_driver ) ;
2005-04-17 02:20:36 +04:00
2007-12-05 14:50:23 +03:00
static int driver_add_groups ( struct device_driver * drv ,
2009-06-24 21:06:31 +04:00
const struct attribute_group * * groups )
2007-12-05 14:50:23 +03:00
{
int error = 0 ;
int i ;
if ( groups ) {
for ( i = 0 ; groups [ i ] ; i + + ) {
2007-11-29 02:59:15 +03:00
error = sysfs_create_group ( & drv - > p - > kobj , groups [ i ] ) ;
2007-12-05 14:50:23 +03:00
if ( error ) {
while ( - - i > = 0 )
2007-11-29 02:59:15 +03:00
sysfs_remove_group ( & drv - > p - > kobj ,
2007-12-05 14:50:23 +03:00
groups [ i ] ) ;
break ;
}
}
}
return error ;
}
static void driver_remove_groups ( struct device_driver * drv ,
2009-06-24 21:06:31 +04:00
const struct attribute_group * * groups )
2007-12-05 14:50:23 +03:00
{
int i ;
if ( groups )
for ( i = 0 ; groups [ i ] ; i + + )
2007-11-29 02:59:15 +03:00
sysfs_remove_group ( & drv - > p - > kobj , groups [ i ] ) ;
2007-12-05 14:50:23 +03:00
}
2005-04-17 02:20:36 +04:00
/**
2008-01-25 09:50:12 +03:00
* driver_register - register driver with bus
* @ drv : driver to register
2005-04-17 02:20:36 +04:00
*
2008-01-25 09:50:12 +03:00
* We pass off most of the work to the bus_add_driver ( ) call ,
* since most of the things we have to do deal with the bus
* structures .
2005-04-17 02:20:36 +04:00
*/
2008-01-25 09:50:12 +03:00
int driver_register ( struct device_driver * drv )
2005-04-17 02:20:36 +04:00
{
2007-12-05 14:50:23 +03:00
int ret ;
2008-04-26 19:52:35 +04:00
struct device_driver * other ;
2007-12-05 14:50:23 +03:00
2009-02-14 16:23:22 +03:00
BUG_ON ( ! drv - > bus - > p ) ;
2006-01-05 17:29:51 +03:00
if ( ( drv - > bus - > probe & & drv - > probe ) | |
( drv - > bus - > remove & & drv - > remove ) | |
2008-01-25 09:50:12 +03:00
( drv - > bus - > shutdown & & drv - > shutdown ) )
printk ( KERN_WARNING " Driver '%s' needs updating - please use "
" bus_type methods \n " , drv - > name ) ;
2008-04-26 19:52:35 +04:00
other = driver_find ( drv - > name , drv - > bus ) ;
if ( other ) {
put_driver ( other ) ;
printk ( KERN_ERR " Error: Driver '%s' is already registered, "
" aborting... \n " , drv - > name ) ;
2009-10-18 00:31:38 +04:00
return - EBUSY ;
2008-04-26 19:52:35 +04:00
}
2007-12-05 14:50:23 +03:00
ret = bus_add_driver ( drv ) ;
if ( ret )
return ret ;
ret = driver_add_groups ( drv , drv - > groups ) ;
if ( ret )
bus_remove_driver ( drv ) ;
return ret ;
2005-04-17 02:20:36 +04:00
}
2008-01-25 09:50:12 +03:00
EXPORT_SYMBOL_GPL ( driver_register ) ;
2005-04-17 02:20:36 +04:00
/**
2008-01-25 09:50:12 +03:00
* driver_unregister - remove driver from system .
* @ drv : driver .
2005-04-17 02:20:36 +04:00
*
2008-01-25 09:50:12 +03:00
* Again , we pass off most of the work to the bus - level call .
2005-04-17 02:20:36 +04:00
*/
2008-01-25 09:50:12 +03:00
void driver_unregister ( struct device_driver * drv )
2005-04-17 02:20:36 +04:00
{
2009-05-29 01:24:07 +04:00
if ( ! drv | | ! drv - > p ) {
WARN ( 1 , " Unexpected driver unregister! \n " ) ;
return ;
}
2007-12-05 14:50:23 +03:00
driver_remove_groups ( drv , drv - > groups ) ;
2005-04-17 02:20:36 +04:00
bus_remove_driver ( drv ) ;
}
2008-01-25 09:50:12 +03:00
EXPORT_SYMBOL_GPL ( driver_unregister ) ;
2005-04-17 02:20:36 +04:00
/**
2008-01-25 09:50:12 +03:00
* driver_find - locate driver on a bus by its name .
* @ name : name of the driver .
* @ bus : bus to scan for the driver .
2005-04-17 02:20:36 +04:00
*
2008-01-25 09:50:12 +03:00
* Call kset_find_obj ( ) to iterate over list of drivers on
* a bus to find driver by name . Return driver if found .
2005-04-17 02:20:36 +04:00
*
2008-01-25 09:50:12 +03:00
* Note that kset_find_obj increments driver ' s reference count .
2005-04-17 02:20:36 +04:00
*/
struct device_driver * driver_find ( const char * name , struct bus_type * bus )
{
2007-11-02 05:41:16 +03:00
struct kobject * k = kset_find_obj ( bus - > p - > drivers_kset , name ) ;
2007-11-29 02:59:15 +03:00
struct driver_private * priv ;
if ( k ) {
priv = to_driver ( k ) ;
return priv - > driver ;
}
2005-04-17 02:20:36 +04:00
return NULL ;
}
EXPORT_SYMBOL_GPL ( driver_find ) ;