aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@ppc970.osdl.org>2005-06-30 12:04:36 -0400
committerLinus Torvalds <torvalds@ppc970.osdl.org>2005-06-30 12:04:36 -0400
commitbd53d1270f51c6cfb53b06c8f93fd42327871d6b (patch)
treede4e91f8ef4702d96ee98ee62357caa4f17ea687
parent12829dcb10efc576c3739131a5d57fe7213632d9 (diff)
parentbf164c790deb79b18faf304b0763e44a02c79f90 (diff)
Merge master.kernel.org:/pub/scm/linux/kernel/git/gregkh/driver-2.6
-rw-r--r--drivers/base/base.h1
-rw-r--r--drivers/base/bus.c117
-rw-r--r--drivers/base/core.c2
-rw-r--r--drivers/base/dd.c2
-rw-r--r--drivers/base/driver.c35
-rw-r--r--include/linux/device.h7
6 files changed, 143 insertions, 21 deletions
diff --git a/drivers/base/base.h b/drivers/base/base.h
index 645f62692920..783752b68a9a 100644
--- a/drivers/base/base.h
+++ b/drivers/base/base.h
@@ -5,6 +5,7 @@ extern int bus_add_driver(struct device_driver *);
5extern void bus_remove_driver(struct device_driver *); 5extern void bus_remove_driver(struct device_driver *);
6 6
7extern void driver_detach(struct device_driver * drv); 7extern void driver_detach(struct device_driver * drv);
8extern int driver_probe_device(struct device_driver *, struct device *);
8 9
9static inline struct class_device *to_class_dev(struct kobject *obj) 10static inline struct class_device *to_class_dev(struct kobject *obj)
10{ 11{
diff --git a/drivers/base/bus.c b/drivers/base/bus.c
index c3fac7fd555e..96fe2f956754 100644
--- a/drivers/base/bus.c
+++ b/drivers/base/bus.c
@@ -133,6 +133,58 @@ static struct kobj_type ktype_bus = {
133decl_subsys(bus, &ktype_bus, NULL); 133decl_subsys(bus, &ktype_bus, NULL);
134 134
135 135
136/* Manually detach a device from it's associated driver. */
137static int driver_helper(struct device *dev, void *data)
138{
139 const char *name = data;
140
141 if (strcmp(name, dev->bus_id) == 0)
142 return 1;
143 return 0;
144}
145
146static ssize_t driver_unbind(struct device_driver *drv,
147 const char *buf, size_t count)
148{
149 struct bus_type *bus = get_bus(drv->bus);
150 struct device *dev;
151 int err = -ENODEV;
152
153 dev = bus_find_device(bus, NULL, (void *)buf, driver_helper);
154 if ((dev) &&
155 (dev->driver == drv)) {
156 device_release_driver(dev);
157 err = count;
158 }
159 return err;
160}
161static DRIVER_ATTR(unbind, S_IWUSR, NULL, driver_unbind);
162
163/*
164 * Manually attach a device to a driver.
165 * Note: the driver must want to bind to the device,
166 * it is not possible to override the driver's id table.
167 */
168static ssize_t driver_bind(struct device_driver *drv,
169 const char *buf, size_t count)
170{
171 struct bus_type *bus = get_bus(drv->bus);
172 struct device *dev;
173 int err = -ENODEV;
174
175 dev = bus_find_device(bus, NULL, (void *)buf, driver_helper);
176 if ((dev) &&
177 (dev->driver == NULL)) {
178 down(&dev->sem);
179 err = driver_probe_device(drv, dev);
180 up(&dev->sem);
181 put_device(dev);
182 }
183 return err;
184}
185static DRIVER_ATTR(bind, S_IWUSR, NULL, driver_bind);
186
187
136static struct device * next_device(struct klist_iter * i) 188static struct device * next_device(struct klist_iter * i)
137{ 189{
138 struct klist_node * n = klist_next(i); 190 struct klist_node * n = klist_next(i);
@@ -177,6 +229,39 @@ int bus_for_each_dev(struct bus_type * bus, struct device * start,
177 return error; 229 return error;
178} 230}
179 231
232/**
233 * bus_find_device - device iterator for locating a particular device.
234 * @bus: bus type
235 * @start: Device to begin with
236 * @data: Data to pass to match function
237 * @match: Callback function to check device
238 *
239 * This is similar to the bus_for_each_dev() function above, but it
240 * returns a reference to a device that is 'found' for later use, as
241 * determined by the @match callback.
242 *
243 * The callback should return 0 if the device doesn't match and non-zero
244 * if it does. If the callback returns non-zero, this function will
245 * return to the caller and not iterate over any more devices.
246 */
247struct device * bus_find_device(struct bus_type *bus,
248 struct device *start, void *data,
249 int (*match)(struct device *, void *))
250{
251 struct klist_iter i;
252 struct device *dev;
253
254 if (!bus)
255 return NULL;
256
257 klist_iter_init_node(&bus->klist_devices, &i,
258 (start ? &start->knode_bus : NULL));
259 while ((dev = next_device(&i)))
260 if (match(dev, data) && get_device(dev))
261 break;
262 klist_iter_exit(&i);
263 return dev;
264}
180 265
181 266
182static struct device_driver * next_driver(struct klist_iter * i) 267static struct device_driver * next_driver(struct klist_iter * i)
@@ -363,6 +448,8 @@ int bus_add_driver(struct device_driver * drv)
363 module_add_driver(drv->owner, drv); 448 module_add_driver(drv->owner, drv);
364 449
365 driver_add_attrs(bus, drv); 450 driver_add_attrs(bus, drv);
451 driver_create_file(drv, &driver_attr_unbind);
452 driver_create_file(drv, &driver_attr_bind);
366 } 453 }
367 return error; 454 return error;
368} 455}
@@ -380,6 +467,8 @@ int bus_add_driver(struct device_driver * drv)
380void bus_remove_driver(struct device_driver * drv) 467void bus_remove_driver(struct device_driver * drv)
381{ 468{
382 if (drv->bus) { 469 if (drv->bus) {
470 driver_remove_file(drv, &driver_attr_bind);
471 driver_remove_file(drv, &driver_attr_unbind);
383 driver_remove_attrs(drv->bus, drv); 472 driver_remove_attrs(drv->bus, drv);
384 klist_remove(&drv->knode_bus); 473 klist_remove(&drv->knode_bus);
385 pr_debug("bus %s: remove driver %s\n", drv->bus->name, drv->name); 474 pr_debug("bus %s: remove driver %s\n", drv->bus->name, drv->name);
@@ -394,31 +483,22 @@ void bus_remove_driver(struct device_driver * drv)
394/* Helper for bus_rescan_devices's iter */ 483/* Helper for bus_rescan_devices's iter */
395static int bus_rescan_devices_helper(struct device *dev, void *data) 484static int bus_rescan_devices_helper(struct device *dev, void *data)
396{ 485{
397 int *count = data; 486 if (!dev->driver)
398 487 device_attach(dev);
399 if (!dev->driver && (device_attach(dev) > 0))
400 (*count)++;
401
402 return 0; 488 return 0;
403} 489}
404 490
405
406/** 491/**
407 * bus_rescan_devices - rescan devices on the bus for possible drivers 492 * bus_rescan_devices - rescan devices on the bus for possible drivers
408 * @bus: the bus to scan. 493 * @bus: the bus to scan.
409 * 494 *
410 * This function will look for devices on the bus with no driver 495 * This function will look for devices on the bus with no driver
411 * attached and rescan it against existing drivers to see if it 496 * attached and rescan it against existing drivers to see if it matches
412 * matches any. Calls device_attach(). Returns the number of devices 497 * any by calling device_attach() for the unbound devices.
413 * that were sucessfully bound to a driver.
414 */ 498 */
415int bus_rescan_devices(struct bus_type * bus) 499void bus_rescan_devices(struct bus_type * bus)
416{ 500{
417 int count = 0; 501 bus_for_each_dev(bus, NULL, NULL, bus_rescan_devices_helper);
418
419 bus_for_each_dev(bus, NULL, &count, bus_rescan_devices_helper);
420
421 return count;
422} 502}
423 503
424 504
@@ -557,6 +637,7 @@ int __init buses_init(void)
557 637
558 638
559EXPORT_SYMBOL_GPL(bus_for_each_dev); 639EXPORT_SYMBOL_GPL(bus_for_each_dev);
640EXPORT_SYMBOL_GPL(bus_find_device);
560EXPORT_SYMBOL_GPL(bus_for_each_drv); 641EXPORT_SYMBOL_GPL(bus_for_each_drv);
561 642
562EXPORT_SYMBOL_GPL(bus_add_device); 643EXPORT_SYMBOL_GPL(bus_add_device);
diff --git a/drivers/base/core.c b/drivers/base/core.c
index 86d79755fbfb..efe03a024a5b 100644
--- a/drivers/base/core.c
+++ b/drivers/base/core.c
@@ -333,7 +333,7 @@ void device_del(struct device * dev)
333 struct device * parent = dev->parent; 333 struct device * parent = dev->parent;
334 334
335 if (parent) 335 if (parent)
336 klist_remove(&dev->knode_parent); 336 klist_del(&dev->knode_parent);
337 337
338 /* Notify the platform of the removal, in case they 338 /* Notify the platform of the removal, in case they
339 * need to do anything... 339 * need to do anything...
diff --git a/drivers/base/dd.c b/drivers/base/dd.c
index 6db3a789c54f..16323f9cbff0 100644
--- a/drivers/base/dd.c
+++ b/drivers/base/dd.c
@@ -65,7 +65,7 @@ void device_bind_driver(struct device * dev)
65 * 65 *
66 * This function must be called with @dev->sem held. 66 * This function must be called with @dev->sem held.
67 */ 67 */
68static int driver_probe_device(struct device_driver * drv, struct device * dev) 68int driver_probe_device(struct device_driver * drv, struct device * dev)
69{ 69{
70 int ret = 0; 70 int ret = 0;
71 71
diff --git a/drivers/base/driver.c b/drivers/base/driver.c
index 1b645886e9eb..291c5954a3af 100644
--- a/drivers/base/driver.c
+++ b/drivers/base/driver.c
@@ -56,6 +56,41 @@ EXPORT_SYMBOL_GPL(driver_for_each_device);
56 56
57 57
58/** 58/**
59 * driver_find_device - device iterator for locating a particular device.
60 * @driver: 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/**
59 * driver_create_file - create sysfs file for driver. 94 * driver_create_file - create sysfs file for driver.
60 * @drv: driver. 95 * @drv: driver.
61 * @attr: driver attribute descriptor. 96 * @attr: driver attribute descriptor.
diff --git a/include/linux/device.h b/include/linux/device.h
index 7b781a72b293..f378c846e6d5 100644
--- a/include/linux/device.h
+++ b/include/linux/device.h
@@ -69,7 +69,7 @@ struct bus_type {
69extern int bus_register(struct bus_type * bus); 69extern int bus_register(struct bus_type * bus);
70extern void bus_unregister(struct bus_type * bus); 70extern void bus_unregister(struct bus_type * bus);
71 71
72extern int bus_rescan_devices(struct bus_type * bus); 72extern void bus_rescan_devices(struct bus_type * bus);
73 73
74extern struct bus_type * get_bus(struct bus_type * bus); 74extern struct bus_type * get_bus(struct bus_type * bus);
75extern void put_bus(struct bus_type * bus); 75extern void put_bus(struct bus_type * bus);
@@ -80,6 +80,8 @@ extern struct bus_type * find_bus(char * name);
80 80
81int bus_for_each_dev(struct bus_type * bus, struct device * start, void * data, 81int bus_for_each_dev(struct bus_type * bus, struct device * start, void * data,
82 int (*fn)(struct device *, void *)); 82 int (*fn)(struct device *, void *));
83struct device * bus_find_device(struct bus_type *bus, struct device *start,
84 void *data, int (*match)(struct device *, void *));
83 85
84int bus_for_each_drv(struct bus_type * bus, struct device_driver * start, 86int bus_for_each_drv(struct bus_type * bus, struct device_driver * start,
85 void * data, int (*fn)(struct device_driver *, void *)); 87 void * data, int (*fn)(struct device_driver *, void *));
@@ -142,6 +144,9 @@ extern void driver_remove_file(struct device_driver *, struct driver_attribute *
142 144
143extern int driver_for_each_device(struct device_driver * drv, struct device * start, 145extern int driver_for_each_device(struct device_driver * drv, struct device * start,
144 void * data, int (*fn)(struct device *, void *)); 146 void * data, int (*fn)(struct device *, void *));
147struct device * driver_find_device(struct device_driver *drv,
148 struct device *start, void *data,
149 int (*match)(struct device *, void *));
145 150
146 151
147/* 152/*