1/*
2 * driver.c - centralized device driver management
3 *
4 * Copyright (c) 2002-3 Patrick Mochel
5 * Copyright (c) 2002-3 Open Source Development Labs
6 *
7 * This file is released under the GPLv2
8 *
9 */
10
11#include <linux/device.h>
12#include <linux/module.h>
13#include <linux/errno.h>
14#include <linux/string.h>
15#include "base.h"
16
17#define to_dev(node) container_of(node, struct device, driver_list)
18#define to_drv(obj) container_of(obj, struct device_driver, kobj)
19
20
21static struct device * next_device(struct klist_iter * i)
22{
23	struct klist_node * n = klist_next(i);
24	return n ? container_of(n, struct device, knode_driver) : NULL;
25}
26
27/**
28 *	driver_for_each_device - Iterator for devices bound to a driver.
29 *	@drv:	Driver we're iterating.
30 *	@start: Device to begin with
31 *	@data:	Data to pass to the callback.
32 *	@fn:	Function to call for each device.
33 *
34 *	Iterate over the @drv's list of devices calling @fn for each one.
35 */
36
37int driver_for_each_device(struct device_driver * drv, struct device * start,
38			   void * data, int (*fn)(struct device *, void *))
39{
40	struct klist_iter i;
41	struct device * dev;
42	int error = 0;
43
44	if (!drv)
45		return -EINVAL;
46
47	klist_iter_init_node(&drv->klist_devices, &i,
48			     start ? &start->knode_driver : NULL);
49	while ((dev = next_device(&i)) && !error)
50		error = fn(dev, data);
51	klist_iter_exit(&i);
52	return error;
53}
54
55EXPORT_SYMBOL_GPL(driver_for_each_device);
56
57
58/**
59 * driver_find_device - device iterator for locating a particular device.
60 * @drv: The device's driver
61 * @start: Device to begin with
62 * @data: Data to pass to match function
63 * @match: Callback function to check device
64 *
65 * This is similar to the driver_for_each_device() function above, but
66 * it returns a reference to a device that is 'found' for later use, as
67 * determined by the @match callback.
68 *
69 * The callback should return 0 if the device doesn't match and non-zero
70 * if it does.  If the callback returns non-zero, this function will
71 * return to the caller and not iterate over any more devices.
72 */
73struct device * driver_find_device(struct device_driver *drv,
74				   struct device * start, void * data,
75				   int (*match)(struct device *, void *))
76{
77	struct klist_iter i;
78	struct device *dev;
79
80	if (!drv)
81		return NULL;
82
83	klist_iter_init_node(&drv->klist_devices, &i,
84			     (start ? &start->knode_driver : NULL));
85	while ((dev = next_device(&i)))
86		if (match(dev, data) && get_device(dev))
87			break;
88	klist_iter_exit(&i);
89	return dev;
90}
91EXPORT_SYMBOL_GPL(driver_find_device);
92
93/**
94 *	driver_create_file - create sysfs file for driver.
95 *	@drv:	driver.
96 *	@attr:	driver attribute descriptor.
97 */
98
99int driver_create_file(struct device_driver * drv, struct driver_attribute * attr)
100{
101	int error;
102	if (get_driver(drv)) {
103		error = sysfs_create_file(&drv->kobj, &attr->attr);
104		put_driver(drv);
105	} else
106		error = -EINVAL;
107	return error;
108}
109
110
111/**
112 *	driver_remove_file - remove sysfs file for driver.
113 *	@drv:	driver.
114 *	@attr:	driver attribute descriptor.
115 */
116
117void driver_remove_file(struct device_driver * drv, struct driver_attribute * attr)
118{
119	if (get_driver(drv)) {
120		sysfs_remove_file(&drv->kobj, &attr->attr);
121		put_driver(drv);
122	}
123}
124
125
126/**
127 *	get_driver - increment driver reference count.
128 *	@drv:	driver.
129 */
130struct device_driver * get_driver(struct device_driver * drv)
131{
132	return drv ? to_drv(kobject_get(&drv->kobj)) : NULL;
133}
134
135
136/**
137 *	put_driver - decrement driver's refcount.
138 *	@drv:	driver.
139 */
140void put_driver(struct device_driver * drv)
141{
142	kobject_put(&drv->kobj);
143}
144
145/**
146 *	driver_register - register driver with bus
147 *	@drv:	driver to register
148 *
149 *	We pass off most of the work to the bus_add_driver() call,
150 *	since most of the things we have to do deal with the bus
151 *	structures.
152 */
153int driver_register(struct device_driver * drv)
154{
155	if ((drv->bus->probe && drv->probe) ||
156	    (drv->bus->remove && drv->remove) ||
157	    (drv->bus->shutdown && drv->shutdown)) {
158		printk(KERN_WARNING "Driver '%s' needs updating - please use bus_type methods\n", drv->name);
159	}
160	klist_init(&drv->klist_devices, NULL, NULL);
161	return bus_add_driver(drv);
162}
163
164/**
165 *	driver_unregister - remove driver from system.
166 *	@drv:	driver.
167 *
168 *	Again, we pass off most of the work to the bus-level call.
169 */
170
171void driver_unregister(struct device_driver * drv)
172{
173	bus_remove_driver(drv);
174}
175
176/**
177 *	driver_find - locate driver on a bus by its name.
178 *	@name:	name of the driver.
179 *	@bus:	bus to scan for the driver.
180 *
181 *	Call kset_find_obj() to iterate over list of drivers on
182 *	a bus to find driver by name. Return driver if found.
183 *
184 *	Note that kset_find_obj increments driver's reference count.
185 */
186struct device_driver *driver_find(const char *name, struct bus_type *bus)
187{
188	struct kobject *k = kset_find_obj(&bus->drivers, name);
189	if (k)
190		return to_drv(k);
191	return NULL;
192}
193
194EXPORT_SYMBOL_GPL(driver_register);
195EXPORT_SYMBOL_GPL(driver_unregister);
196EXPORT_SYMBOL_GPL(get_driver);
197EXPORT_SYMBOL_GPL(put_driver);
198EXPORT_SYMBOL_GPL(driver_find);
199
200EXPORT_SYMBOL_GPL(driver_create_file);
201EXPORT_SYMBOL_GPL(driver_remove_file);
202