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