Branch data Line data Source code
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 : : * Copyright (c) 2007 Greg Kroah-Hartman <gregkh@suse.de>
7 : : * Copyright (c) 2007 Novell Inc.
8 : : *
9 : : * This file is released under the GPLv2
10 : : *
11 : : */
12 : :
13 : : #include <linux/device.h>
14 : : #include <linux/module.h>
15 : : #include <linux/errno.h>
16 : : #include <linux/slab.h>
17 : : #include <linux/string.h>
18 : : #include <linux/sysfs.h>
19 : : #include "base.h"
20 : :
21 : : static struct device *next_device(struct klist_iter *i)
22 : : {
23 : 0 : struct klist_node *n = klist_next(i);
24 : : struct device *dev = NULL;
25 : : struct device_private *dev_prv;
26 : :
27 [ # # # # ]: 0 : if (n) {
28 : : dev_prv = to_device_private_driver(n);
29 : 0 : dev = dev_prv->device;
30 : : }
31 : : return dev;
32 : : }
33 : :
34 : : /**
35 : : * driver_for_each_device - Iterator for devices bound to a driver.
36 : : * @drv: Driver we're iterating.
37 : : * @start: Device to begin with
38 : : * @data: Data to pass to the callback.
39 : : * @fn: Function to call for each device.
40 : : *
41 : : * Iterate over the @drv's list of devices calling @fn for each one.
42 : : */
43 : 0 : int driver_for_each_device(struct device_driver *drv, struct device *start,
44 : : void *data, int (*fn)(struct device *, void *))
45 : : {
46 : : struct klist_iter i;
47 : : struct device *dev;
48 : : int error = 0;
49 : :
50 [ # # ]: 0 : if (!drv)
51 : : return -EINVAL;
52 : :
53 [ # # ]: 0 : klist_iter_init_node(&drv->p->klist_devices, &i,
54 : 0 : start ? &start->p->knode_driver : NULL);
55 [ # # ][ # # ]: 0 : while ((dev = next_device(&i)) && !error)
56 : 0 : error = fn(dev, data);
57 : 0 : klist_iter_exit(&i);
58 : 0 : return error;
59 : : }
60 : : EXPORT_SYMBOL_GPL(driver_for_each_device);
61 : :
62 : : /**
63 : : * driver_find_device - device iterator for locating a particular device.
64 : : * @drv: The device's driver
65 : : * @start: Device to begin with
66 : : * @data: Data to pass to match function
67 : : * @match: Callback function to check device
68 : : *
69 : : * This is similar to the driver_for_each_device() function above, but
70 : : * it returns a reference to a device that is 'found' for later use, as
71 : : * determined by the @match callback.
72 : : *
73 : : * The callback should return 0 if the device doesn't match and non-zero
74 : : * if it does. If the callback returns non-zero, this function will
75 : : * return to the caller and not iterate over any more devices.
76 : : */
77 : 0 : struct device *driver_find_device(struct device_driver *drv,
78 : : struct device *start, void *data,
79 : : int (*match)(struct device *dev, void *data))
80 : : {
81 : : struct klist_iter i;
82 : : struct device *dev;
83 : :
84 [ # # ][ # # ]: 0 : if (!drv || !drv->p)
85 : : return NULL;
86 : :
87 [ # # ]: 0 : klist_iter_init_node(&drv->p->klist_devices, &i,
88 : 0 : (start ? &start->p->knode_driver : NULL));
89 [ # # ]: 0 : while ((dev = next_device(&i)))
90 [ # # ][ # # ]: 0 : if (match(dev, data) && get_device(dev))
91 : : break;
92 : 0 : klist_iter_exit(&i);
93 : 0 : return dev;
94 : : }
95 : : EXPORT_SYMBOL_GPL(driver_find_device);
96 : :
97 : : /**
98 : : * driver_create_file - create sysfs file for driver.
99 : : * @drv: driver.
100 : : * @attr: driver attribute descriptor.
101 : : */
102 : 0 : int driver_create_file(struct device_driver *drv,
103 : : const struct driver_attribute *attr)
104 : : {
105 : : int error;
106 [ # # ]: 0 : if (drv)
107 : 0 : error = sysfs_create_file(&drv->p->kobj, &attr->attr);
108 : : else
109 : : error = -EINVAL;
110 : 0 : return error;
111 : : }
112 : : EXPORT_SYMBOL_GPL(driver_create_file);
113 : :
114 : : /**
115 : : * driver_remove_file - remove sysfs file for driver.
116 : : * @drv: driver.
117 : : * @attr: driver attribute descriptor.
118 : : */
119 : 0 : void driver_remove_file(struct device_driver *drv,
120 : : const struct driver_attribute *attr)
121 : : {
122 [ # # ]: 0 : if (drv)
123 : 0 : sysfs_remove_file(&drv->p->kobj, &attr->attr);
124 : 0 : }
125 : : EXPORT_SYMBOL_GPL(driver_remove_file);
126 : :
127 : 0 : int driver_add_groups(struct device_driver *drv,
128 : : const struct attribute_group **groups)
129 : : {
130 : 0 : return sysfs_create_groups(&drv->p->kobj, groups);
131 : : }
132 : :
133 : 0 : void driver_remove_groups(struct device_driver *drv,
134 : : const struct attribute_group **groups)
135 : : {
136 : 0 : sysfs_remove_groups(&drv->p->kobj, groups);
137 : 0 : }
138 : :
139 : : /**
140 : : * driver_register - register driver with bus
141 : : * @drv: driver to register
142 : : *
143 : : * We pass off most of the work to the bus_add_driver() call,
144 : : * since most of the things we have to do deal with the bus
145 : : * structures.
146 : : */
147 : 0 : int driver_register(struct device_driver *drv)
148 : : {
149 : : int ret;
150 : : struct device_driver *other;
151 : :
152 [ # # ]: 0 : BUG_ON(!drv->bus->p);
153 : :
154 [ # # ][ # # ]: 0 : if ((drv->bus->probe && drv->probe) ||
[ # # ]
155 [ # # ][ # # ]: 0 : (drv->bus->remove && drv->remove) ||
156 [ # # ]: 0 : (drv->bus->shutdown && drv->shutdown))
157 : 0 : printk(KERN_WARNING "Driver '%s' needs updating - please use "
158 : : "bus_type methods\n", drv->name);
159 : :
160 : 0 : other = driver_find(drv->name, drv->bus);
161 [ # # ]: 0 : if (other) {
162 : 0 : printk(KERN_ERR "Error: Driver '%s' is already registered, "
163 : : "aborting...\n", drv->name);
164 : 0 : return -EBUSY;
165 : : }
166 : :
167 : 0 : ret = bus_add_driver(drv);
168 [ # # ]: 0 : if (ret)
169 : : return ret;
170 : 0 : ret = driver_add_groups(drv, drv->groups);
171 [ # # ]: 0 : if (ret) {
172 : 0 : bus_remove_driver(drv);
173 : 0 : return ret;
174 : : }
175 : 0 : kobject_uevent(&drv->p->kobj, KOBJ_ADD);
176 : :
177 : 0 : return ret;
178 : : }
179 : : EXPORT_SYMBOL_GPL(driver_register);
180 : :
181 : : /**
182 : : * driver_unregister - remove driver from system.
183 : : * @drv: driver.
184 : : *
185 : : * Again, we pass off most of the work to the bus-level call.
186 : : */
187 : 0 : void driver_unregister(struct device_driver *drv)
188 : : {
189 [ # # ][ # # ]: 0 : if (!drv || !drv->p) {
190 : 0 : WARN(1, "Unexpected driver unregister!\n");
191 : 0 : return;
192 : : }
193 : 0 : driver_remove_groups(drv, drv->groups);
194 : 0 : bus_remove_driver(drv);
195 : : }
196 : : EXPORT_SYMBOL_GPL(driver_unregister);
197 : :
198 : : /**
199 : : * driver_find - locate driver on a bus by its name.
200 : : * @name: name of the driver.
201 : : * @bus: bus to scan for the driver.
202 : : *
203 : : * Call kset_find_obj() to iterate over list of drivers on
204 : : * a bus to find driver by name. Return driver if found.
205 : : *
206 : : * This routine provides no locking to prevent the driver it returns
207 : : * from being unregistered or unloaded while the caller is using it.
208 : : * The caller is responsible for preventing this.
209 : : */
210 : 0 : struct device_driver *driver_find(const char *name, struct bus_type *bus)
211 : : {
212 : 0 : struct kobject *k = kset_find_obj(bus->p->drivers_kset, name);
213 : : struct driver_private *priv;
214 : :
215 [ # # ]: 0 : if (k) {
216 : : /* Drop reference added by kset_find_obj() */
217 : 0 : kobject_put(k);
218 : : priv = to_driver(k);
219 : 0 : return priv->driver;
220 : : }
221 : : return NULL;
222 : : }
223 : : EXPORT_SYMBOL_GPL(driver_find);
|