driver.c revision c6f7e72a3f4641095ade9ded287d910c980c6148
11da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
21da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * driver.c - centralized device driver management
31da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
41da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Copyright (c) 2002-3 Patrick Mochel
51da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Copyright (c) 2002-3 Open Source Development Labs
61da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
71da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * This file is released under the GPLv2
81da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
91da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/device.h>
121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/module.h>
131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/errno.h>
141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/string.h>
151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include "base.h"
161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define to_dev(node) container_of(node, struct device, driver_list)
181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define to_drv(obj) container_of(obj, struct device_driver, kobj)
191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
20fae3cd00255e3e51ffd59fedb1bdb91ec96be395Patrick Mochel
2194e7b1c5ff2055571703e38b059afffe17658432Patrick Mochelstatic struct device * next_device(struct klist_iter * i)
2294e7b1c5ff2055571703e38b059afffe17658432Patrick Mochel{
2394e7b1c5ff2055571703e38b059afffe17658432Patrick Mochel	struct klist_node * n = klist_next(i);
2494e7b1c5ff2055571703e38b059afffe17658432Patrick Mochel	return n ? container_of(n, struct device, knode_driver) : NULL;
2594e7b1c5ff2055571703e38b059afffe17658432Patrick Mochel}
2694e7b1c5ff2055571703e38b059afffe17658432Patrick Mochel
27fae3cd00255e3e51ffd59fedb1bdb91ec96be395Patrick Mochel/**
28fae3cd00255e3e51ffd59fedb1bdb91ec96be395Patrick Mochel *	driver_for_each_device - Iterator for devices bound to a driver.
29fae3cd00255e3e51ffd59fedb1bdb91ec96be395Patrick Mochel *	@drv:	Driver we're iterating.
30c41455fbac06712992da491844449775cf9a8c80Randy Dunlap *	@start: Device to begin with
31fae3cd00255e3e51ffd59fedb1bdb91ec96be395Patrick Mochel *	@data:	Data to pass to the callback.
32fae3cd00255e3e51ffd59fedb1bdb91ec96be395Patrick Mochel *	@fn:	Function to call for each device.
33fae3cd00255e3e51ffd59fedb1bdb91ec96be395Patrick Mochel *
344d12d2d953ca5e299de6a653f1d0478f670d7bc6Patrick Mochel *	Iterate over the @drv's list of devices calling @fn for each one.
35fae3cd00255e3e51ffd59fedb1bdb91ec96be395Patrick Mochel */
36fae3cd00255e3e51ffd59fedb1bdb91ec96be395Patrick Mochel
37fae3cd00255e3e51ffd59fedb1bdb91ec96be395Patrick Mochelint driver_for_each_device(struct device_driver * drv, struct device * start,
38fae3cd00255e3e51ffd59fedb1bdb91ec96be395Patrick Mochel			   void * data, int (*fn)(struct device *, void *))
39fae3cd00255e3e51ffd59fedb1bdb91ec96be395Patrick Mochel{
4094e7b1c5ff2055571703e38b059afffe17658432Patrick Mochel	struct klist_iter i;
41fae3cd00255e3e51ffd59fedb1bdb91ec96be395Patrick Mochel	struct device * dev;
42fae3cd00255e3e51ffd59fedb1bdb91ec96be395Patrick Mochel	int error = 0;
43fae3cd00255e3e51ffd59fedb1bdb91ec96be395Patrick Mochel
4494e7b1c5ff2055571703e38b059afffe17658432Patrick Mochel	if (!drv)
4594e7b1c5ff2055571703e38b059afffe17658432Patrick Mochel		return -EINVAL;
4694e7b1c5ff2055571703e38b059afffe17658432Patrick Mochel
4794e7b1c5ff2055571703e38b059afffe17658432Patrick Mochel	klist_iter_init_node(&drv->klist_devices, &i,
4894e7b1c5ff2055571703e38b059afffe17658432Patrick Mochel			     start ? &start->knode_driver : NULL);
4994e7b1c5ff2055571703e38b059afffe17658432Patrick Mochel	while ((dev = next_device(&i)) && !error)
50fae3cd00255e3e51ffd59fedb1bdb91ec96be395Patrick Mochel		error = fn(dev, data);
5194e7b1c5ff2055571703e38b059afffe17658432Patrick Mochel	klist_iter_exit(&i);
52fae3cd00255e3e51ffd59fedb1bdb91ec96be395Patrick Mochel	return error;
53fae3cd00255e3e51ffd59fedb1bdb91ec96be395Patrick Mochel}
54fae3cd00255e3e51ffd59fedb1bdb91ec96be395Patrick Mochel
55126eddfbf8cae8a20c22708192bffcbd77c8a889Greg Kroah-HartmanEXPORT_SYMBOL_GPL(driver_for_each_device);
56fae3cd00255e3e51ffd59fedb1bdb91ec96be395Patrick Mochel
57fae3cd00255e3e51ffd59fedb1bdb91ec96be395Patrick Mochel
581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/**
590edb586049e57c56e625536476931117a57671e9Cornelia Huck * driver_find_device - device iterator for locating a particular device.
60c41455fbac06712992da491844449775cf9a8c80Randy Dunlap * @drv: The device's driver
610edb586049e57c56e625536476931117a57671e9Cornelia Huck * @start: Device to begin with
620edb586049e57c56e625536476931117a57671e9Cornelia Huck * @data: Data to pass to match function
630edb586049e57c56e625536476931117a57671e9Cornelia Huck * @match: Callback function to check device
640edb586049e57c56e625536476931117a57671e9Cornelia Huck *
650edb586049e57c56e625536476931117a57671e9Cornelia Huck * This is similar to the driver_for_each_device() function above, but
660edb586049e57c56e625536476931117a57671e9Cornelia Huck * it returns a reference to a device that is 'found' for later use, as
670edb586049e57c56e625536476931117a57671e9Cornelia Huck * determined by the @match callback.
680edb586049e57c56e625536476931117a57671e9Cornelia Huck *
690edb586049e57c56e625536476931117a57671e9Cornelia Huck * The callback should return 0 if the device doesn't match and non-zero
700edb586049e57c56e625536476931117a57671e9Cornelia Huck * if it does.  If the callback returns non-zero, this function will
710edb586049e57c56e625536476931117a57671e9Cornelia Huck * return to the caller and not iterate over any more devices.
720edb586049e57c56e625536476931117a57671e9Cornelia Huck */
730edb586049e57c56e625536476931117a57671e9Cornelia Huckstruct device * driver_find_device(struct device_driver *drv,
740edb586049e57c56e625536476931117a57671e9Cornelia Huck				   struct device * start, void * data,
750edb586049e57c56e625536476931117a57671e9Cornelia Huck				   int (*match)(struct device *, void *))
760edb586049e57c56e625536476931117a57671e9Cornelia Huck{
770edb586049e57c56e625536476931117a57671e9Cornelia Huck	struct klist_iter i;
780edb586049e57c56e625536476931117a57671e9Cornelia Huck	struct device *dev;
790edb586049e57c56e625536476931117a57671e9Cornelia Huck
800edb586049e57c56e625536476931117a57671e9Cornelia Huck	if (!drv)
810edb586049e57c56e625536476931117a57671e9Cornelia Huck		return NULL;
820edb586049e57c56e625536476931117a57671e9Cornelia Huck
830edb586049e57c56e625536476931117a57671e9Cornelia Huck	klist_iter_init_node(&drv->klist_devices, &i,
840edb586049e57c56e625536476931117a57671e9Cornelia Huck			     (start ? &start->knode_driver : NULL));
850edb586049e57c56e625536476931117a57671e9Cornelia Huck	while ((dev = next_device(&i)))
860edb586049e57c56e625536476931117a57671e9Cornelia Huck		if (match(dev, data) && get_device(dev))
870edb586049e57c56e625536476931117a57671e9Cornelia Huck			break;
880edb586049e57c56e625536476931117a57671e9Cornelia Huck	klist_iter_exit(&i);
890edb586049e57c56e625536476931117a57671e9Cornelia Huck	return dev;
900edb586049e57c56e625536476931117a57671e9Cornelia Huck}
910edb586049e57c56e625536476931117a57671e9Cornelia HuckEXPORT_SYMBOL_GPL(driver_find_device);
920edb586049e57c56e625536476931117a57671e9Cornelia Huck
930edb586049e57c56e625536476931117a57671e9Cornelia Huck/**
941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	driver_create_file - create sysfs file for driver.
951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	@drv:	driver.
961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	@attr:	driver attribute descriptor.
971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsint driver_create_file(struct device_driver * drv, struct driver_attribute * attr)
1001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
1011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int error;
1021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (get_driver(drv)) {
1031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		error = sysfs_create_file(&drv->kobj, &attr->attr);
1041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		put_driver(drv);
1051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	} else
1061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		error = -EINVAL;
1071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return error;
1081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
1091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/**
1121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	driver_remove_file - remove sysfs file for driver.
1131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	@drv:	driver.
1141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	@attr:	driver attribute descriptor.
1151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
1161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsvoid driver_remove_file(struct device_driver * drv, struct driver_attribute * attr)
1181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
1191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (get_driver(drv)) {
1201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		sysfs_remove_file(&drv->kobj, &attr->attr);
1211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		put_driver(drv);
1221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
1231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
1241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/**
1271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	get_driver - increment driver reference count.
1281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	@drv:	driver.
1291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
1301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstruct device_driver * get_driver(struct device_driver * drv)
1311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
1321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return drv ? to_drv(kobject_get(&drv->kobj)) : NULL;
1331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
1341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/**
1371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	put_driver - decrement driver's refcount.
1381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	@drv:	driver.
1391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
1401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsvoid put_driver(struct device_driver * drv)
1411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
1421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	kobject_put(&drv->kobj);
1431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
1441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/**
1461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	driver_register - register driver with bus
1471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	@drv:	driver to register
1481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
1491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	We pass off most of the work to the bus_add_driver() call,
1501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	since most of the things we have to do deal with the bus
1511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	structures.
1521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
1531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsint driver_register(struct device_driver * drv)
1541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
155594c8281f90560faf9632d91bb9d402cbe560e63Russell King	if ((drv->bus->probe && drv->probe) ||
156594c8281f90560faf9632d91bb9d402cbe560e63Russell King	    (drv->bus->remove && drv->remove) ||
157594c8281f90560faf9632d91bb9d402cbe560e63Russell King	    (drv->bus->shutdown && drv->shutdown)) {
158594c8281f90560faf9632d91bb9d402cbe560e63Russell King		printk(KERN_WARNING "Driver '%s' needs updating - please use bus_type methods\n", drv->name);
159594c8281f90560faf9632d91bb9d402cbe560e63Russell King	}
16081107bf531d2524afbcd61f3b4ad57a71295d591Alan Stern	klist_init(&drv->klist_devices, NULL, NULL);
1611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return bus_add_driver(drv);
1621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
1631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/**
1651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	driver_unregister - remove driver from system.
1661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	@drv:	driver.
1671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
1681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	Again, we pass off most of the work to the bus-level call.
1691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
1701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsvoid driver_unregister(struct device_driver * drv)
1721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
1731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	bus_remove_driver(drv);
1741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
1751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/**
1771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	driver_find - locate driver on a bus by its name.
1781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	@name:	name of the driver.
1791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	@bus:	bus to scan for the driver.
1801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
1811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	Call kset_find_obj() to iterate over list of drivers on
1821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	a bus to find driver by name. Return driver if found.
1831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
1841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	Note that kset_find_obj increments driver's reference count.
1851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
1861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstruct device_driver *driver_find(const char *name, struct bus_type *bus)
1871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
188c6f7e72a3f4641095ade9ded287d910c980c6148Greg Kroah-Hartman	struct kobject *k = kset_find_obj(bus->p->drivers_kset, name);
1891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (k)
1901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return to_drv(k);
1911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return NULL;
1921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
1931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsEXPORT_SYMBOL_GPL(driver_register);
1951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsEXPORT_SYMBOL_GPL(driver_unregister);
1961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsEXPORT_SYMBOL_GPL(get_driver);
1971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsEXPORT_SYMBOL_GPL(put_driver);
1981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsEXPORT_SYMBOL_GPL(driver_find);
1991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsEXPORT_SYMBOL_GPL(driver_create_file);
2011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsEXPORT_SYMBOL_GPL(driver_remove_file);
202