xref: /linux/drivers/base/bus.c (revision 7dc72b2842381684b864750af31a5fb168dec764)
11da177e4SLinus Torvalds /*
21da177e4SLinus Torvalds  * bus.c - bus driver management
31da177e4SLinus Torvalds  *
41da177e4SLinus Torvalds  * Copyright (c) 2002-3 Patrick Mochel
51da177e4SLinus Torvalds  * Copyright (c) 2002-3 Open Source Development Labs
6e5dd1278SGreg Kroah-Hartman  * Copyright (c) 2007 Greg Kroah-Hartman <gregkh@suse.de>
7e5dd1278SGreg Kroah-Hartman  * Copyright (c) 2007 Novell Inc.
81da177e4SLinus Torvalds  *
91da177e4SLinus Torvalds  * This file is released under the GPLv2
101da177e4SLinus Torvalds  *
111da177e4SLinus Torvalds  */
121da177e4SLinus Torvalds 
131da177e4SLinus Torvalds #include <linux/device.h>
141da177e4SLinus Torvalds #include <linux/module.h>
151da177e4SLinus Torvalds #include <linux/errno.h>
161da177e4SLinus Torvalds #include <linux/init.h>
171da177e4SLinus Torvalds #include <linux/string.h>
181da177e4SLinus Torvalds #include "base.h"
191da177e4SLinus Torvalds #include "power/power.h"
201da177e4SLinus Torvalds 
211da177e4SLinus Torvalds #define to_bus_attr(_attr) container_of(_attr, struct bus_attribute, attr)
22c6f7e72aSGreg Kroah-Hartman #define to_bus(obj) container_of(obj, struct bus_type_private, subsys.kobj)
231da177e4SLinus Torvalds 
241da177e4SLinus Torvalds /*
251da177e4SLinus Torvalds  * sysfs bindings for drivers
261da177e4SLinus Torvalds  */
271da177e4SLinus Torvalds 
281da177e4SLinus Torvalds #define to_drv_attr(_attr) container_of(_attr, struct driver_attribute, attr)
291da177e4SLinus Torvalds 
301da177e4SLinus Torvalds 
31b8c5cec2SKay Sievers static int __must_check bus_rescan_devices_helper(struct device *dev,
32b8c5cec2SKay Sievers 						void *data);
33b8c5cec2SKay Sievers 
345901d014SGreg Kroah-Hartman static struct bus_type *bus_get(struct bus_type *bus)
355901d014SGreg Kroah-Hartman {
36c6f7e72aSGreg Kroah-Hartman 	if (bus) {
37c6f7e72aSGreg Kroah-Hartman 		kset_get(&bus->p->subsys);
38c6f7e72aSGreg Kroah-Hartman 		return bus;
39c6f7e72aSGreg Kroah-Hartman 	}
40c6f7e72aSGreg Kroah-Hartman 	return NULL;
415901d014SGreg Kroah-Hartman }
425901d014SGreg Kroah-Hartman 
43fc1ede58SGreg Kroah-Hartman static void bus_put(struct bus_type *bus)
44fc1ede58SGreg Kroah-Hartman {
45c6f7e72aSGreg Kroah-Hartman 	if (bus)
46c6f7e72aSGreg Kroah-Hartman 		kset_put(&bus->p->subsys);
47fc1ede58SGreg Kroah-Hartman }
48fc1ede58SGreg Kroah-Hartman 
491da177e4SLinus Torvalds static ssize_t
501da177e4SLinus Torvalds drv_attr_show(struct kobject * kobj, struct attribute * attr, char * buf)
511da177e4SLinus Torvalds {
521da177e4SLinus Torvalds 	struct driver_attribute * drv_attr = to_drv_attr(attr);
53e5dd1278SGreg Kroah-Hartman 	struct driver_private *drv_priv = to_driver(kobj);
544a0c20bfSDmitry Torokhov 	ssize_t ret = -EIO;
551da177e4SLinus Torvalds 
561da177e4SLinus Torvalds 	if (drv_attr->show)
57e5dd1278SGreg Kroah-Hartman 		ret = drv_attr->show(drv_priv->driver, buf);
581da177e4SLinus Torvalds 	return ret;
591da177e4SLinus Torvalds }
601da177e4SLinus Torvalds 
611da177e4SLinus Torvalds static ssize_t
621da177e4SLinus Torvalds drv_attr_store(struct kobject * kobj, struct attribute * attr,
631da177e4SLinus Torvalds 	       const char * buf, size_t count)
641da177e4SLinus Torvalds {
651da177e4SLinus Torvalds 	struct driver_attribute * drv_attr = to_drv_attr(attr);
66e5dd1278SGreg Kroah-Hartman 	struct driver_private *drv_priv = to_driver(kobj);
674a0c20bfSDmitry Torokhov 	ssize_t ret = -EIO;
681da177e4SLinus Torvalds 
691da177e4SLinus Torvalds 	if (drv_attr->store)
70e5dd1278SGreg Kroah-Hartman 		ret = drv_attr->store(drv_priv->driver, buf, count);
711da177e4SLinus Torvalds 	return ret;
721da177e4SLinus Torvalds }
731da177e4SLinus Torvalds 
741da177e4SLinus Torvalds static struct sysfs_ops driver_sysfs_ops = {
751da177e4SLinus Torvalds 	.show	= drv_attr_show,
761da177e4SLinus Torvalds 	.store	= drv_attr_store,
771da177e4SLinus Torvalds };
781da177e4SLinus Torvalds 
791da177e4SLinus Torvalds static void driver_release(struct kobject *kobj)
801da177e4SLinus Torvalds {
81e5dd1278SGreg Kroah-Hartman 	struct driver_private *drv_priv = to_driver(kobj);
82e5dd1278SGreg Kroah-Hartman 
83*7dc72b28SGreg Kroah-Hartman 	pr_debug("driver: '%s': %s\n", kobject_name(kobj), __FUNCTION__);
84e5dd1278SGreg Kroah-Hartman 	kfree(drv_priv);
851da177e4SLinus Torvalds }
861da177e4SLinus Torvalds 
87a1148fb0SGreg Kroah-Hartman static struct kobj_type driver_ktype = {
881da177e4SLinus Torvalds 	.sysfs_ops	= &driver_sysfs_ops,
891da177e4SLinus Torvalds 	.release	= driver_release,
901da177e4SLinus Torvalds };
911da177e4SLinus Torvalds 
921da177e4SLinus Torvalds 
931da177e4SLinus Torvalds /*
941da177e4SLinus Torvalds  * sysfs bindings for buses
951da177e4SLinus Torvalds  */
961da177e4SLinus Torvalds 
971da177e4SLinus Torvalds 
981da177e4SLinus Torvalds static ssize_t
991da177e4SLinus Torvalds bus_attr_show(struct kobject * kobj, struct attribute * attr, char * buf)
1001da177e4SLinus Torvalds {
1011da177e4SLinus Torvalds 	struct bus_attribute * bus_attr = to_bus_attr(attr);
102c6f7e72aSGreg Kroah-Hartman 	struct bus_type_private *bus_priv = to_bus(kobj);
1031da177e4SLinus Torvalds 	ssize_t ret = 0;
1041da177e4SLinus Torvalds 
1051da177e4SLinus Torvalds 	if (bus_attr->show)
106c6f7e72aSGreg Kroah-Hartman 		ret = bus_attr->show(bus_priv->bus, buf);
1071da177e4SLinus Torvalds 	return ret;
1081da177e4SLinus Torvalds }
1091da177e4SLinus Torvalds 
1101da177e4SLinus Torvalds static ssize_t
1111da177e4SLinus Torvalds bus_attr_store(struct kobject * kobj, struct attribute * attr,
1121da177e4SLinus Torvalds 	       const char * buf, size_t count)
1131da177e4SLinus Torvalds {
1141da177e4SLinus Torvalds 	struct bus_attribute * bus_attr = to_bus_attr(attr);
115c6f7e72aSGreg Kroah-Hartman 	struct bus_type_private *bus_priv = to_bus(kobj);
1161da177e4SLinus Torvalds 	ssize_t ret = 0;
1171da177e4SLinus Torvalds 
1181da177e4SLinus Torvalds 	if (bus_attr->store)
119c6f7e72aSGreg Kroah-Hartman 		ret = bus_attr->store(bus_priv->bus, buf, count);
1201da177e4SLinus Torvalds 	return ret;
1211da177e4SLinus Torvalds }
1221da177e4SLinus Torvalds 
1231da177e4SLinus Torvalds static struct sysfs_ops bus_sysfs_ops = {
1241da177e4SLinus Torvalds 	.show	= bus_attr_show,
1251da177e4SLinus Torvalds 	.store	= bus_attr_store,
1261da177e4SLinus Torvalds };
1271da177e4SLinus Torvalds 
1281da177e4SLinus Torvalds int bus_create_file(struct bus_type * bus, struct bus_attribute * attr)
1291da177e4SLinus Torvalds {
1301da177e4SLinus Torvalds 	int error;
1315901d014SGreg Kroah-Hartman 	if (bus_get(bus)) {
132c6f7e72aSGreg Kroah-Hartman 		error = sysfs_create_file(&bus->p->subsys.kobj, &attr->attr);
133fc1ede58SGreg Kroah-Hartman 		bus_put(bus);
1341da177e4SLinus Torvalds 	} else
1351da177e4SLinus Torvalds 		error = -EINVAL;
1361da177e4SLinus Torvalds 	return error;
1371da177e4SLinus Torvalds }
1381da177e4SLinus Torvalds 
1391da177e4SLinus Torvalds void bus_remove_file(struct bus_type * bus, struct bus_attribute * attr)
1401da177e4SLinus Torvalds {
1415901d014SGreg Kroah-Hartman 	if (bus_get(bus)) {
142c6f7e72aSGreg Kroah-Hartman 		sysfs_remove_file(&bus->p->subsys.kobj, &attr->attr);
143fc1ede58SGreg Kroah-Hartman 		bus_put(bus);
1441da177e4SLinus Torvalds 	}
1451da177e4SLinus Torvalds }
1461da177e4SLinus Torvalds 
14780f03e34SKay Sievers static struct kobj_type bus_ktype = {
1481da177e4SLinus Torvalds 	.sysfs_ops	= &bus_sysfs_ops,
1491da177e4SLinus Torvalds };
1501da177e4SLinus Torvalds 
15180f03e34SKay Sievers static int bus_uevent_filter(struct kset *kset, struct kobject *kobj)
15280f03e34SKay Sievers {
15380f03e34SKay Sievers 	struct kobj_type *ktype = get_ktype(kobj);
15480f03e34SKay Sievers 
15580f03e34SKay Sievers 	if (ktype == &bus_ktype)
15680f03e34SKay Sievers 		return 1;
15780f03e34SKay Sievers 	return 0;
15880f03e34SKay Sievers }
15980f03e34SKay Sievers 
16080f03e34SKay Sievers static struct kset_uevent_ops bus_uevent_ops = {
16180f03e34SKay Sievers 	.filter = bus_uevent_filter,
16280f03e34SKay Sievers };
16380f03e34SKay Sievers 
16459a54833SGreg Kroah-Hartman static struct kset *bus_kset;
1651da177e4SLinus Torvalds 
1661da177e4SLinus Torvalds 
1672139bdd5SRussell King #ifdef CONFIG_HOTPLUG
1682b08c8d0SAlan Stern /* Manually detach a device from its associated driver. */
169151ef38fSGreg Kroah-Hartman static int driver_helper(struct device *dev, void *data)
170151ef38fSGreg Kroah-Hartman {
171151ef38fSGreg Kroah-Hartman 	const char *name = data;
172151ef38fSGreg Kroah-Hartman 
173151ef38fSGreg Kroah-Hartman 	if (strcmp(name, dev->bus_id) == 0)
174151ef38fSGreg Kroah-Hartman 		return 1;
175151ef38fSGreg Kroah-Hartman 	return 0;
176151ef38fSGreg Kroah-Hartman }
177151ef38fSGreg Kroah-Hartman 
178151ef38fSGreg Kroah-Hartman static ssize_t driver_unbind(struct device_driver *drv,
179151ef38fSGreg Kroah-Hartman 			     const char *buf, size_t count)
180151ef38fSGreg Kroah-Hartman {
1815901d014SGreg Kroah-Hartman 	struct bus_type *bus = bus_get(drv->bus);
182151ef38fSGreg Kroah-Hartman 	struct device *dev;
183151ef38fSGreg Kroah-Hartman 	int err = -ENODEV;
184151ef38fSGreg Kroah-Hartman 
185151ef38fSGreg Kroah-Hartman 	dev = bus_find_device(bus, NULL, (void *)buf, driver_helper);
1862b08c8d0SAlan Stern 	if (dev && dev->driver == drv) {
187bf74ad5bSAlan Stern 		if (dev->parent)	/* Needed for USB */
188bf74ad5bSAlan Stern 			down(&dev->parent->sem);
189151ef38fSGreg Kroah-Hartman 		device_release_driver(dev);
190bf74ad5bSAlan Stern 		if (dev->parent)
191bf74ad5bSAlan Stern 			up(&dev->parent->sem);
192151ef38fSGreg Kroah-Hartman 		err = count;
193151ef38fSGreg Kroah-Hartman 	}
1942b08c8d0SAlan Stern 	put_device(dev);
195fc1ede58SGreg Kroah-Hartman 	bus_put(bus);
196151ef38fSGreg Kroah-Hartman 	return err;
197151ef38fSGreg Kroah-Hartman }
198151ef38fSGreg Kroah-Hartman static DRIVER_ATTR(unbind, S_IWUSR, NULL, driver_unbind);
199151ef38fSGreg Kroah-Hartman 
200afdce75fSGreg Kroah-Hartman /*
201afdce75fSGreg Kroah-Hartman  * Manually attach a device to a driver.
202afdce75fSGreg Kroah-Hartman  * Note: the driver must want to bind to the device,
203afdce75fSGreg Kroah-Hartman  * it is not possible to override the driver's id table.
204afdce75fSGreg Kroah-Hartman  */
205afdce75fSGreg Kroah-Hartman static ssize_t driver_bind(struct device_driver *drv,
206afdce75fSGreg Kroah-Hartman 			   const char *buf, size_t count)
207afdce75fSGreg Kroah-Hartman {
2085901d014SGreg Kroah-Hartman 	struct bus_type *bus = bus_get(drv->bus);
209afdce75fSGreg Kroah-Hartman 	struct device *dev;
210afdce75fSGreg Kroah-Hartman 	int err = -ENODEV;
211afdce75fSGreg Kroah-Hartman 
212afdce75fSGreg Kroah-Hartman 	dev = bus_find_device(bus, NULL, (void *)buf, driver_helper);
2132b08c8d0SAlan Stern 	if (dev && dev->driver == NULL) {
214bf74ad5bSAlan Stern 		if (dev->parent)	/* Needed for USB */
215bf74ad5bSAlan Stern 			down(&dev->parent->sem);
216afdce75fSGreg Kroah-Hartman 		down(&dev->sem);
217afdce75fSGreg Kroah-Hartman 		err = driver_probe_device(drv, dev);
218afdce75fSGreg Kroah-Hartman 		up(&dev->sem);
219bf74ad5bSAlan Stern 		if (dev->parent)
220bf74ad5bSAlan Stern 			up(&dev->parent->sem);
22137225401SRyan Wilson 
22237225401SRyan Wilson 		if (err > 0) 		/* success */
22337225401SRyan Wilson 			err = count;
22437225401SRyan Wilson 		else if (err == 0)	/* driver didn't accept device */
22537225401SRyan Wilson 			err = -ENODEV;
226afdce75fSGreg Kroah-Hartman 	}
2272b08c8d0SAlan Stern 	put_device(dev);
228fc1ede58SGreg Kroah-Hartman 	bus_put(bus);
229afdce75fSGreg Kroah-Hartman 	return err;
230afdce75fSGreg Kroah-Hartman }
231afdce75fSGreg Kroah-Hartman static DRIVER_ATTR(bind, S_IWUSR, NULL, driver_bind);
232afdce75fSGreg Kroah-Hartman 
233b8c5cec2SKay Sievers static ssize_t show_drivers_autoprobe(struct bus_type *bus, char *buf)
234b8c5cec2SKay Sievers {
235c6f7e72aSGreg Kroah-Hartman 	return sprintf(buf, "%d\n", bus->p->drivers_autoprobe);
236b8c5cec2SKay Sievers }
237b8c5cec2SKay Sievers 
238b8c5cec2SKay Sievers static ssize_t store_drivers_autoprobe(struct bus_type *bus,
239b8c5cec2SKay Sievers 				       const char *buf, size_t count)
240b8c5cec2SKay Sievers {
241b8c5cec2SKay Sievers 	if (buf[0] == '0')
242c6f7e72aSGreg Kroah-Hartman 		bus->p->drivers_autoprobe = 0;
243b8c5cec2SKay Sievers 	else
244c6f7e72aSGreg Kroah-Hartman 		bus->p->drivers_autoprobe = 1;
245b8c5cec2SKay Sievers 	return count;
246b8c5cec2SKay Sievers }
247b8c5cec2SKay Sievers 
248b8c5cec2SKay Sievers static ssize_t store_drivers_probe(struct bus_type *bus,
249b8c5cec2SKay Sievers 				   const char *buf, size_t count)
250b8c5cec2SKay Sievers {
251b8c5cec2SKay Sievers 	struct device *dev;
252b8c5cec2SKay Sievers 
253b8c5cec2SKay Sievers 	dev = bus_find_device(bus, NULL, (void *)buf, driver_helper);
254b8c5cec2SKay Sievers 	if (!dev)
255b8c5cec2SKay Sievers 		return -ENODEV;
256b8c5cec2SKay Sievers 	if (bus_rescan_devices_helper(dev, NULL) != 0)
257b8c5cec2SKay Sievers 		return -EINVAL;
258b8c5cec2SKay Sievers 	return count;
259b8c5cec2SKay Sievers }
2602139bdd5SRussell King #endif
261151ef38fSGreg Kroah-Hartman 
262465c7a3aSmochel@digitalimplant.org static struct device * next_device(struct klist_iter * i)
263465c7a3aSmochel@digitalimplant.org {
264465c7a3aSmochel@digitalimplant.org 	struct klist_node * n = klist_next(i);
265465c7a3aSmochel@digitalimplant.org 	return n ? container_of(n, struct device, knode_bus) : NULL;
266465c7a3aSmochel@digitalimplant.org }
267465c7a3aSmochel@digitalimplant.org 
2681da177e4SLinus Torvalds /**
2691da177e4SLinus Torvalds  *	bus_for_each_dev - device iterator.
2701da177e4SLinus Torvalds  *	@bus:	bus type.
2711da177e4SLinus Torvalds  *	@start:	device to start iterating from.
2721da177e4SLinus Torvalds  *	@data:	data for the callback.
2731da177e4SLinus Torvalds  *	@fn:	function to be called for each device.
2741da177e4SLinus Torvalds  *
2751da177e4SLinus Torvalds  *	Iterate over @bus's list of devices, and call @fn for each,
2761da177e4SLinus Torvalds  *	passing it @data. If @start is not NULL, we use that device to
2771da177e4SLinus Torvalds  *	begin iterating from.
2781da177e4SLinus Torvalds  *
2791da177e4SLinus Torvalds  *	We check the return of @fn each time. If it returns anything
2801da177e4SLinus Torvalds  *	other than 0, we break out and return that value.
2811da177e4SLinus Torvalds  *
2821da177e4SLinus Torvalds  *	NOTE: The device that returns a non-zero value is not retained
2831da177e4SLinus Torvalds  *	in any way, nor is its refcount incremented. If the caller needs
2841da177e4SLinus Torvalds  *	to retain this data, it should do, and increment the reference
2851da177e4SLinus Torvalds  *	count in the supplied callback.
2861da177e4SLinus Torvalds  */
2871da177e4SLinus Torvalds 
2881da177e4SLinus Torvalds int bus_for_each_dev(struct bus_type * bus, struct device * start,
2891da177e4SLinus Torvalds 		     void * data, int (*fn)(struct device *, void *))
2901da177e4SLinus Torvalds {
291465c7a3aSmochel@digitalimplant.org 	struct klist_iter i;
292465c7a3aSmochel@digitalimplant.org 	struct device * dev;
293465c7a3aSmochel@digitalimplant.org 	int error = 0;
2941da177e4SLinus Torvalds 
295465c7a3aSmochel@digitalimplant.org 	if (!bus)
296465c7a3aSmochel@digitalimplant.org 		return -EINVAL;
297465c7a3aSmochel@digitalimplant.org 
298c6f7e72aSGreg Kroah-Hartman 	klist_iter_init_node(&bus->p->klist_devices, &i,
299465c7a3aSmochel@digitalimplant.org 			     (start ? &start->knode_bus : NULL));
300465c7a3aSmochel@digitalimplant.org 	while ((dev = next_device(&i)) && !error)
301465c7a3aSmochel@digitalimplant.org 		error = fn(dev, data);
302465c7a3aSmochel@digitalimplant.org 	klist_iter_exit(&i);
303465c7a3aSmochel@digitalimplant.org 	return error;
3041da177e4SLinus Torvalds }
3051da177e4SLinus Torvalds 
3060edb5860SCornelia Huck /**
3070edb5860SCornelia Huck  * bus_find_device - device iterator for locating a particular device.
3080edb5860SCornelia Huck  * @bus: bus type
3090edb5860SCornelia Huck  * @start: Device to begin with
3100edb5860SCornelia Huck  * @data: Data to pass to match function
3110edb5860SCornelia Huck  * @match: Callback function to check device
3120edb5860SCornelia Huck  *
3130edb5860SCornelia Huck  * This is similar to the bus_for_each_dev() function above, but it
3140edb5860SCornelia Huck  * returns a reference to a device that is 'found' for later use, as
3150edb5860SCornelia Huck  * determined by the @match callback.
3160edb5860SCornelia Huck  *
3170edb5860SCornelia Huck  * The callback should return 0 if the device doesn't match and non-zero
3180edb5860SCornelia Huck  * if it does.  If the callback returns non-zero, this function will
3190edb5860SCornelia Huck  * return to the caller and not iterate over any more devices.
3200edb5860SCornelia Huck  */
3210edb5860SCornelia Huck struct device * bus_find_device(struct bus_type *bus,
3220edb5860SCornelia Huck 				struct device *start, void *data,
3230edb5860SCornelia Huck 				int (*match)(struct device *, void *))
3240edb5860SCornelia Huck {
3250edb5860SCornelia Huck 	struct klist_iter i;
3260edb5860SCornelia Huck 	struct device *dev;
3270edb5860SCornelia Huck 
3280edb5860SCornelia Huck 	if (!bus)
3290edb5860SCornelia Huck 		return NULL;
3300edb5860SCornelia Huck 
331c6f7e72aSGreg Kroah-Hartman 	klist_iter_init_node(&bus->p->klist_devices, &i,
3320edb5860SCornelia Huck 			     (start ? &start->knode_bus : NULL));
3330edb5860SCornelia Huck 	while ((dev = next_device(&i)))
3340edb5860SCornelia Huck 		if (match(dev, data) && get_device(dev))
3350edb5860SCornelia Huck 			break;
3360edb5860SCornelia Huck 	klist_iter_exit(&i);
3370edb5860SCornelia Huck 	return dev;
3380edb5860SCornelia Huck }
33938fdac3cSmochel@digitalimplant.org 
34038fdac3cSmochel@digitalimplant.org 
34138fdac3cSmochel@digitalimplant.org static struct device_driver * next_driver(struct klist_iter * i)
34238fdac3cSmochel@digitalimplant.org {
34338fdac3cSmochel@digitalimplant.org 	struct klist_node * n = klist_next(i);
344e5dd1278SGreg Kroah-Hartman 	struct driver_private *drv_priv;
345e5dd1278SGreg Kroah-Hartman 
346e5dd1278SGreg Kroah-Hartman 	if (n) {
347e5dd1278SGreg Kroah-Hartman 		drv_priv = container_of(n, struct driver_private, knode_bus);
348e5dd1278SGreg Kroah-Hartman 		return drv_priv->driver;
349e5dd1278SGreg Kroah-Hartman 	}
350e5dd1278SGreg Kroah-Hartman 	return NULL;
35138fdac3cSmochel@digitalimplant.org }
35238fdac3cSmochel@digitalimplant.org 
3531da177e4SLinus Torvalds /**
3541da177e4SLinus Torvalds  *	bus_for_each_drv - driver iterator
3551da177e4SLinus Torvalds  *	@bus:	bus we're dealing with.
3561da177e4SLinus Torvalds  *	@start:	driver to start iterating on.
3571da177e4SLinus Torvalds  *	@data:	data to pass to the callback.
3581da177e4SLinus Torvalds  *	@fn:	function to call for each driver.
3591da177e4SLinus Torvalds  *
3601da177e4SLinus Torvalds  *	This is nearly identical to the device iterator above.
3611da177e4SLinus Torvalds  *	We iterate over each driver that belongs to @bus, and call
3621da177e4SLinus Torvalds  *	@fn for each. If @fn returns anything but 0, we break out
3631da177e4SLinus Torvalds  *	and return it. If @start is not NULL, we use it as the head
3641da177e4SLinus Torvalds  *	of the list.
3651da177e4SLinus Torvalds  *
3661da177e4SLinus Torvalds  *	NOTE: we don't return the driver that returns a non-zero
3671da177e4SLinus Torvalds  *	value, nor do we leave the reference count incremented for that
3681da177e4SLinus Torvalds  *	driver. If the caller needs to know that info, it must set it
3691da177e4SLinus Torvalds  *	in the callback. It must also be sure to increment the refcount
3701da177e4SLinus Torvalds  *	so it doesn't disappear before returning to the caller.
3711da177e4SLinus Torvalds  */
3721da177e4SLinus Torvalds 
3731da177e4SLinus Torvalds int bus_for_each_drv(struct bus_type * bus, struct device_driver * start,
3741da177e4SLinus Torvalds 		     void * data, int (*fn)(struct device_driver *, void *))
3751da177e4SLinus Torvalds {
37638fdac3cSmochel@digitalimplant.org 	struct klist_iter i;
37738fdac3cSmochel@digitalimplant.org 	struct device_driver * drv;
37838fdac3cSmochel@digitalimplant.org 	int error = 0;
3791da177e4SLinus Torvalds 
38038fdac3cSmochel@digitalimplant.org 	if (!bus)
38138fdac3cSmochel@digitalimplant.org 		return -EINVAL;
38238fdac3cSmochel@digitalimplant.org 
383c6f7e72aSGreg Kroah-Hartman 	klist_iter_init_node(&bus->p->klist_drivers, &i,
384e5dd1278SGreg Kroah-Hartman 			     start ? &start->p->knode_bus : NULL);
38538fdac3cSmochel@digitalimplant.org 	while ((drv = next_driver(&i)) && !error)
38638fdac3cSmochel@digitalimplant.org 		error = fn(drv, data);
38738fdac3cSmochel@digitalimplant.org 	klist_iter_exit(&i);
38838fdac3cSmochel@digitalimplant.org 	return error;
3891da177e4SLinus Torvalds }
3901da177e4SLinus Torvalds 
3911da177e4SLinus Torvalds static int device_add_attrs(struct bus_type *bus, struct device *dev)
3921da177e4SLinus Torvalds {
3931da177e4SLinus Torvalds 	int error = 0;
3941da177e4SLinus Torvalds 	int i;
3951da177e4SLinus Torvalds 
3964aca67e5SAndrew Morton 	if (!bus->dev_attrs)
3974aca67e5SAndrew Morton 		return 0;
3984aca67e5SAndrew Morton 
3991da177e4SLinus Torvalds 	for (i = 0; attr_name(bus->dev_attrs[i]); i++) {
4001da177e4SLinus Torvalds 		error = device_create_file(dev,&bus->dev_attrs[i]);
4014aca67e5SAndrew Morton 		if (error) {
4021da177e4SLinus Torvalds 			while (--i >= 0)
4031da177e4SLinus Torvalds 				device_remove_file(dev, &bus->dev_attrs[i]);
4044aca67e5SAndrew Morton 			break;
4051da177e4SLinus Torvalds 		}
4064aca67e5SAndrew Morton 	}
4074aca67e5SAndrew Morton 	return error;
4084aca67e5SAndrew Morton }
4091da177e4SLinus Torvalds 
4101da177e4SLinus Torvalds static void device_remove_attrs(struct bus_type * bus, struct device * dev)
4111da177e4SLinus Torvalds {
4121da177e4SLinus Torvalds 	int i;
4131da177e4SLinus Torvalds 
4141da177e4SLinus Torvalds 	if (bus->dev_attrs) {
4151da177e4SLinus Torvalds 		for (i = 0; attr_name(bus->dev_attrs[i]); i++)
4161da177e4SLinus Torvalds 			device_remove_file(dev,&bus->dev_attrs[i]);
4171da177e4SLinus Torvalds 	}
4181da177e4SLinus Torvalds }
4191da177e4SLinus Torvalds 
420b9cafc7dSKay Sievers #ifdef CONFIG_SYSFS_DEPRECATED
421b9cafc7dSKay Sievers static int make_deprecated_bus_links(struct device *dev)
422b9cafc7dSKay Sievers {
423b9cafc7dSKay Sievers 	return sysfs_create_link(&dev->kobj,
424c6f7e72aSGreg Kroah-Hartman 				 &dev->bus->p->subsys.kobj, "bus");
425b9cafc7dSKay Sievers }
426b9cafc7dSKay Sievers 
427b9cafc7dSKay Sievers static void remove_deprecated_bus_links(struct device *dev)
428b9cafc7dSKay Sievers {
429b9cafc7dSKay Sievers 	sysfs_remove_link(&dev->kobj, "bus");
430b9cafc7dSKay Sievers }
431b9cafc7dSKay Sievers #else
432b9cafc7dSKay Sievers static inline int make_deprecated_bus_links(struct device *dev) { return 0; }
433b9cafc7dSKay Sievers static inline void remove_deprecated_bus_links(struct device *dev) { }
434b9cafc7dSKay Sievers #endif
4351da177e4SLinus Torvalds 
4361da177e4SLinus Torvalds /**
4371da177e4SLinus Torvalds  *	bus_add_device - add device to bus
4381da177e4SLinus Torvalds  *	@dev:	device being added
4391da177e4SLinus Torvalds  *
4401da177e4SLinus Torvalds  *	- Add the device to its bus's list of devices.
44153877d06SKay Sievers  *	- Create link to device's bus.
4421da177e4SLinus Torvalds  */
4431da177e4SLinus Torvalds int bus_add_device(struct device * dev)
4441da177e4SLinus Torvalds {
4455901d014SGreg Kroah-Hartman 	struct bus_type * bus = bus_get(dev->bus);
4461da177e4SLinus Torvalds 	int error = 0;
4471da177e4SLinus Torvalds 
4481da177e4SLinus Torvalds 	if (bus) {
449*7dc72b28SGreg Kroah-Hartman 		pr_debug("bus: '%s': add device %s\n", bus->name, dev->bus_id);
450ca2b94baSHannes Reinecke 		error = device_add_attrs(bus, dev);
451f86db396SAndrew Morton 		if (error)
452513e7337SCornelia Huck 			goto out_put;
453c6f7e72aSGreg Kroah-Hartman 		error = sysfs_create_link(&bus->p->devices_kset->kobj,
454f86db396SAndrew Morton 						&dev->kobj, dev->bus_id);
455f86db396SAndrew Morton 		if (error)
456513e7337SCornelia Huck 			goto out_id;
457f86db396SAndrew Morton 		error = sysfs_create_link(&dev->kobj,
458c6f7e72aSGreg Kroah-Hartman 				&dev->bus->p->subsys.kobj, "subsystem");
459f86db396SAndrew Morton 		if (error)
460513e7337SCornelia Huck 			goto out_subsys;
461b9cafc7dSKay Sievers 		error = make_deprecated_bus_links(dev);
462513e7337SCornelia Huck 		if (error)
463513e7337SCornelia Huck 			goto out_deprecated;
4641da177e4SLinus Torvalds 	}
465513e7337SCornelia Huck 	return 0;
466513e7337SCornelia Huck 
467513e7337SCornelia Huck out_deprecated:
468513e7337SCornelia Huck 	sysfs_remove_link(&dev->kobj, "subsystem");
469513e7337SCornelia Huck out_subsys:
470c6f7e72aSGreg Kroah-Hartman 	sysfs_remove_link(&bus->p->devices_kset->kobj, dev->bus_id);
471513e7337SCornelia Huck out_id:
472513e7337SCornelia Huck 	device_remove_attrs(bus, dev);
473513e7337SCornelia Huck out_put:
474fc1ede58SGreg Kroah-Hartman 	bus_put(dev->bus);
4751da177e4SLinus Torvalds 	return error;
4761da177e4SLinus Torvalds }
4771da177e4SLinus Torvalds 
4781da177e4SLinus Torvalds /**
47953877d06SKay Sievers  *	bus_attach_device - add device to bus
48053877d06SKay Sievers  *	@dev:	device tried to attach to a driver
48153877d06SKay Sievers  *
482f2eaae19SAlan Stern  *	- Add device to bus's list of devices.
48353877d06SKay Sievers  *	- Try to attach to driver.
48453877d06SKay Sievers  */
485c6a46696SCornelia Huck void bus_attach_device(struct device * dev)
48653877d06SKay Sievers {
48753877d06SKay Sievers 	struct bus_type *bus = dev->bus;
488f86db396SAndrew Morton 	int ret = 0;
48953877d06SKay Sievers 
49053877d06SKay Sievers 	if (bus) {
491f2eaae19SAlan Stern 		dev->is_registered = 1;
492c6f7e72aSGreg Kroah-Hartman 		if (bus->p->drivers_autoprobe)
493f86db396SAndrew Morton 			ret = device_attach(dev);
494c6a46696SCornelia Huck 		WARN_ON(ret < 0);
495c6a46696SCornelia Huck 		if (ret >= 0)
496c6f7e72aSGreg Kroah-Hartman 			klist_add_tail(&dev->knode_bus, &bus->p->klist_devices);
497c6a46696SCornelia Huck 		else
498f2eaae19SAlan Stern 			dev->is_registered = 0;
49953877d06SKay Sievers 	}
500f86db396SAndrew Morton }
50153877d06SKay Sievers 
50253877d06SKay Sievers /**
5031da177e4SLinus Torvalds  *	bus_remove_device - remove device from bus
5041da177e4SLinus Torvalds  *	@dev:	device to be removed
5051da177e4SLinus Torvalds  *
5061da177e4SLinus Torvalds  *	- Remove symlink from bus's directory.
5071da177e4SLinus Torvalds  *	- Delete device from bus's list.
5081da177e4SLinus Torvalds  *	- Detach from its driver.
5091da177e4SLinus Torvalds  *	- Drop reference taken in bus_add_device().
5101da177e4SLinus Torvalds  */
5111da177e4SLinus Torvalds void bus_remove_device(struct device * dev)
5121da177e4SLinus Torvalds {
5131da177e4SLinus Torvalds 	if (dev->bus) {
514b9d9c82bSKay Sievers 		sysfs_remove_link(&dev->kobj, "subsystem");
515b9cafc7dSKay Sievers 		remove_deprecated_bus_links(dev);
516c6f7e72aSGreg Kroah-Hartman 		sysfs_remove_link(&dev->bus->p->devices_kset->kobj, dev->bus_id);
5171da177e4SLinus Torvalds 		device_remove_attrs(dev->bus, dev);
518f70fa629SAlan Stern 		if (dev->is_registered) {
519f2eaae19SAlan Stern 			dev->is_registered = 0;
520f2eaae19SAlan Stern 			klist_del(&dev->knode_bus);
521f70fa629SAlan Stern 		}
522*7dc72b28SGreg Kroah-Hartman 		pr_debug("bus: '%s': remove device %s\n", dev->bus->name, dev->bus_id);
5231da177e4SLinus Torvalds 		device_release_driver(dev);
524fc1ede58SGreg Kroah-Hartman 		bus_put(dev->bus);
5251da177e4SLinus Torvalds 	}
5261da177e4SLinus Torvalds }
5271da177e4SLinus Torvalds 
5281da177e4SLinus Torvalds static int driver_add_attrs(struct bus_type * bus, struct device_driver * drv)
5291da177e4SLinus Torvalds {
5301da177e4SLinus Torvalds 	int error = 0;
5311da177e4SLinus Torvalds 	int i;
5321da177e4SLinus Torvalds 
5331da177e4SLinus Torvalds 	if (bus->drv_attrs) {
5341da177e4SLinus Torvalds 		for (i = 0; attr_name(bus->drv_attrs[i]); i++) {
5351da177e4SLinus Torvalds 			error = driver_create_file(drv, &bus->drv_attrs[i]);
5361da177e4SLinus Torvalds 			if (error)
5371da177e4SLinus Torvalds 				goto Err;
5381da177e4SLinus Torvalds 		}
5391da177e4SLinus Torvalds 	}
5401da177e4SLinus Torvalds  Done:
5411da177e4SLinus Torvalds 	return error;
5421da177e4SLinus Torvalds  Err:
5431da177e4SLinus Torvalds 	while (--i >= 0)
5441da177e4SLinus Torvalds 		driver_remove_file(drv, &bus->drv_attrs[i]);
5451da177e4SLinus Torvalds 	goto Done;
5461da177e4SLinus Torvalds }
5471da177e4SLinus Torvalds 
5481da177e4SLinus Torvalds 
5491da177e4SLinus Torvalds static void driver_remove_attrs(struct bus_type * bus, struct device_driver * drv)
5501da177e4SLinus Torvalds {
5511da177e4SLinus Torvalds 	int i;
5521da177e4SLinus Torvalds 
5531da177e4SLinus Torvalds 	if (bus->drv_attrs) {
5541da177e4SLinus Torvalds 		for (i = 0; attr_name(bus->drv_attrs[i]); i++)
5551da177e4SLinus Torvalds 			driver_remove_file(drv, &bus->drv_attrs[i]);
5561da177e4SLinus Torvalds 	}
5571da177e4SLinus Torvalds }
5581da177e4SLinus Torvalds 
559874c6241SGreg Kroah-Hartman #ifdef CONFIG_HOTPLUG
560874c6241SGreg Kroah-Hartman /*
561874c6241SGreg Kroah-Hartman  * Thanks to drivers making their tables __devinit, we can't allow manual
562874c6241SGreg Kroah-Hartman  * bind and unbind from userspace unless CONFIG_HOTPLUG is enabled.
563874c6241SGreg Kroah-Hartman  */
564f86db396SAndrew Morton static int __must_check add_bind_files(struct device_driver *drv)
565874c6241SGreg Kroah-Hartman {
566f86db396SAndrew Morton 	int ret;
567f86db396SAndrew Morton 
568f86db396SAndrew Morton 	ret = driver_create_file(drv, &driver_attr_unbind);
569f86db396SAndrew Morton 	if (ret == 0) {
570f86db396SAndrew Morton 		ret = driver_create_file(drv, &driver_attr_bind);
571f86db396SAndrew Morton 		if (ret)
572f86db396SAndrew Morton 			driver_remove_file(drv, &driver_attr_unbind);
573f86db396SAndrew Morton 	}
574f86db396SAndrew Morton 	return ret;
575874c6241SGreg Kroah-Hartman }
576874c6241SGreg Kroah-Hartman 
577874c6241SGreg Kroah-Hartman static void remove_bind_files(struct device_driver *drv)
578874c6241SGreg Kroah-Hartman {
579874c6241SGreg Kroah-Hartman 	driver_remove_file(drv, &driver_attr_bind);
580874c6241SGreg Kroah-Hartman 	driver_remove_file(drv, &driver_attr_unbind);
581874c6241SGreg Kroah-Hartman }
582b8c5cec2SKay Sievers 
5838380770cSKay Sievers static BUS_ATTR(drivers_probe, S_IWUSR, NULL, store_drivers_probe);
5848380770cSKay Sievers static BUS_ATTR(drivers_autoprobe, S_IWUSR | S_IRUGO,
5858380770cSKay Sievers 		show_drivers_autoprobe, store_drivers_autoprobe);
5868380770cSKay Sievers 
587b8c5cec2SKay Sievers static int add_probe_files(struct bus_type *bus)
588b8c5cec2SKay Sievers {
589b8c5cec2SKay Sievers 	int retval;
590b8c5cec2SKay Sievers 
5918380770cSKay Sievers 	retval = bus_create_file(bus, &bus_attr_drivers_probe);
592b8c5cec2SKay Sievers 	if (retval)
593b8c5cec2SKay Sievers 		goto out;
594b8c5cec2SKay Sievers 
5958380770cSKay Sievers 	retval = bus_create_file(bus, &bus_attr_drivers_autoprobe);
596b8c5cec2SKay Sievers 	if (retval)
5978380770cSKay Sievers 		bus_remove_file(bus, &bus_attr_drivers_probe);
598b8c5cec2SKay Sievers out:
599b8c5cec2SKay Sievers 	return retval;
600b8c5cec2SKay Sievers }
601b8c5cec2SKay Sievers 
602b8c5cec2SKay Sievers static void remove_probe_files(struct bus_type *bus)
603b8c5cec2SKay Sievers {
6048380770cSKay Sievers 	bus_remove_file(bus, &bus_attr_drivers_autoprobe);
6058380770cSKay Sievers 	bus_remove_file(bus, &bus_attr_drivers_probe);
606b8c5cec2SKay Sievers }
607874c6241SGreg Kroah-Hartman #else
60835acfdd7SYoichi Yuasa static inline int add_bind_files(struct device_driver *drv) { return 0; }
609874c6241SGreg Kroah-Hartman static inline void remove_bind_files(struct device_driver *drv) {}
610b8c5cec2SKay Sievers static inline int add_probe_files(struct bus_type *bus) { return 0; }
611b8c5cec2SKay Sievers static inline void remove_probe_files(struct bus_type *bus) {}
612874c6241SGreg Kroah-Hartman #endif
6131da177e4SLinus Torvalds 
6147ac1cf4aSKay Sievers static ssize_t driver_uevent_store(struct device_driver *drv,
6157ac1cf4aSKay Sievers 				   const char *buf, size_t count)
6167ac1cf4aSKay Sievers {
6177ac1cf4aSKay Sievers 	enum kobject_action action;
6187ac1cf4aSKay Sievers 
6197ac1cf4aSKay Sievers 	if (kobject_action_type(buf, count, &action) == 0)
620e5dd1278SGreg Kroah-Hartman 		kobject_uevent(&drv->p->kobj, action);
6217ac1cf4aSKay Sievers 	return count;
6227ac1cf4aSKay Sievers }
6237ac1cf4aSKay Sievers static DRIVER_ATTR(uevent, S_IWUSR, NULL, driver_uevent_store);
6247ac1cf4aSKay Sievers 
6251da177e4SLinus Torvalds /**
6261da177e4SLinus Torvalds  *	bus_add_driver - Add a driver to the bus.
6271da177e4SLinus Torvalds  *	@drv:	driver.
6281da177e4SLinus Torvalds  *
6291da177e4SLinus Torvalds  */
6301da177e4SLinus Torvalds int bus_add_driver(struct device_driver *drv)
6311da177e4SLinus Torvalds {
632e5dd1278SGreg Kroah-Hartman 	struct bus_type *bus;
633e5dd1278SGreg Kroah-Hartman 	struct driver_private *priv;
6341da177e4SLinus Torvalds 	int error = 0;
6351da177e4SLinus Torvalds 
636e5dd1278SGreg Kroah-Hartman 	bus = bus_get(drv->bus);
637d9fd4d3bSJeff Garzik 	if (!bus)
6384f6e1945SGreg Kroah-Hartman 		return -EINVAL;
639d9fd4d3bSJeff Garzik 
640*7dc72b28SGreg Kroah-Hartman 	pr_debug("bus: '%s': add driver %s\n", bus->name, drv->name);
641e5dd1278SGreg Kroah-Hartman 
642e5dd1278SGreg Kroah-Hartman 	priv = kzalloc(sizeof(*priv), GFP_KERNEL);
643e5dd1278SGreg Kroah-Hartman 	if (!priv)
644e5dd1278SGreg Kroah-Hartman 		return -ENOMEM;
645e5dd1278SGreg Kroah-Hartman 
646e5dd1278SGreg Kroah-Hartman 	error = kobject_set_name(&priv->kobj, "%s", drv->name);
647f86db396SAndrew Morton 	if (error)
648f86db396SAndrew Morton 		goto out_put_bus;
649e5dd1278SGreg Kroah-Hartman 	priv->kobj.kset = bus->p->drivers_kset;
650e5dd1278SGreg Kroah-Hartman 	priv->kobj.ktype = &driver_ktype;
651e5dd1278SGreg Kroah-Hartman 	klist_init(&priv->klist_devices, NULL, NULL);
652e5dd1278SGreg Kroah-Hartman 	priv->driver = drv;
653e5dd1278SGreg Kroah-Hartman 	drv->p = priv;
654e5dd1278SGreg Kroah-Hartman 	error = kobject_register(&priv->kobj);
655dc0afa83SCornelia Huck 	if (error)
656f86db396SAndrew Morton 		goto out_put_bus;
6571da177e4SLinus Torvalds 
658c6f7e72aSGreg Kroah-Hartman 	if (drv->bus->p->drivers_autoprobe) {
659f86db396SAndrew Morton 		error = driver_attach(drv);
660f86db396SAndrew Morton 		if (error)
661f86db396SAndrew Morton 			goto out_unregister;
662b8c5cec2SKay Sievers 	}
663e5dd1278SGreg Kroah-Hartman 	klist_add_tail(&priv->knode_bus, &bus->p->klist_drivers);
6641da177e4SLinus Torvalds 	module_add_driver(drv->owner, drv);
6651da177e4SLinus Torvalds 
6667ac1cf4aSKay Sievers 	error = driver_create_file(drv, &driver_attr_uevent);
6677ac1cf4aSKay Sievers 	if (error) {
6687ac1cf4aSKay Sievers 		printk(KERN_ERR "%s: uevent attr (%s) failed\n",
6697ac1cf4aSKay Sievers 			__FUNCTION__, drv->name);
6707ac1cf4aSKay Sievers 	}
671f86db396SAndrew Morton 	error = driver_add_attrs(bus, drv);
672f86db396SAndrew Morton 	if (error) {
673f86db396SAndrew Morton 		/* How the hell do we get out of this pickle? Give up */
674f86db396SAndrew Morton 		printk(KERN_ERR "%s: driver_add_attrs(%s) failed\n",
675f86db396SAndrew Morton 			__FUNCTION__, drv->name);
676f86db396SAndrew Morton 	}
677f86db396SAndrew Morton 	error = add_bind_files(drv);
678f86db396SAndrew Morton 	if (error) {
679f86db396SAndrew Morton 		/* Ditto */
680f86db396SAndrew Morton 		printk(KERN_ERR "%s: add_bind_files(%s) failed\n",
681f86db396SAndrew Morton 			__FUNCTION__, drv->name);
682f86db396SAndrew Morton 	}
683d9fd4d3bSJeff Garzik 
6841da177e4SLinus Torvalds 	return error;
685f86db396SAndrew Morton out_unregister:
686e5dd1278SGreg Kroah-Hartman 	kobject_unregister(&priv->kobj);
687f86db396SAndrew Morton out_put_bus:
688fc1ede58SGreg Kroah-Hartman 	bus_put(bus);
689f86db396SAndrew Morton 	return error;
6901da177e4SLinus Torvalds }
6911da177e4SLinus Torvalds 
6921da177e4SLinus Torvalds /**
6931da177e4SLinus Torvalds  *	bus_remove_driver - delete driver from bus's knowledge.
6941da177e4SLinus Torvalds  *	@drv:	driver.
6951da177e4SLinus Torvalds  *
6961da177e4SLinus Torvalds  *	Detach the driver from the devices it controls, and remove
6971da177e4SLinus Torvalds  *	it from its bus's list of drivers. Finally, we drop the reference
6981da177e4SLinus Torvalds  *	to the bus we took in bus_add_driver().
6991da177e4SLinus Torvalds  */
7001da177e4SLinus Torvalds 
7011da177e4SLinus Torvalds void bus_remove_driver(struct device_driver * drv)
7021da177e4SLinus Torvalds {
703d9fd4d3bSJeff Garzik 	if (!drv->bus)
704d9fd4d3bSJeff Garzik 		return;
705d9fd4d3bSJeff Garzik 
706874c6241SGreg Kroah-Hartman 	remove_bind_files(drv);
7071da177e4SLinus Torvalds 	driver_remove_attrs(drv->bus, drv);
7087ac1cf4aSKay Sievers 	driver_remove_file(drv, &driver_attr_uevent);
709e5dd1278SGreg Kroah-Hartman 	klist_remove(&drv->p->knode_bus);
710*7dc72b28SGreg Kroah-Hartman 	pr_debug("bus: '%s': remove driver %s\n", drv->bus->name, drv->name);
7111da177e4SLinus Torvalds 	driver_detach(drv);
7121da177e4SLinus Torvalds 	module_remove_driver(drv);
713e5dd1278SGreg Kroah-Hartman 	kobject_unregister(&drv->p->kobj);
714fc1ede58SGreg Kroah-Hartman 	bus_put(drv->bus);
7151da177e4SLinus Torvalds }
7161da177e4SLinus Torvalds 
7171da177e4SLinus Torvalds 
7181da177e4SLinus Torvalds /* Helper for bus_rescan_devices's iter */
719f86db396SAndrew Morton static int __must_check bus_rescan_devices_helper(struct device *dev,
720f86db396SAndrew Morton 						void *data)
7211da177e4SLinus Torvalds {
722f86db396SAndrew Morton 	int ret = 0;
723f86db396SAndrew Morton 
724bf74ad5bSAlan Stern 	if (!dev->driver) {
725bf74ad5bSAlan Stern 		if (dev->parent)	/* Needed for USB */
726bf74ad5bSAlan Stern 			down(&dev->parent->sem);
727f86db396SAndrew Morton 		ret = device_attach(dev);
728bf74ad5bSAlan Stern 		if (dev->parent)
729bf74ad5bSAlan Stern 			up(&dev->parent->sem);
730bf74ad5bSAlan Stern 	}
731f86db396SAndrew Morton 	return ret < 0 ? ret : 0;
7321da177e4SLinus Torvalds }
7331da177e4SLinus Torvalds 
7341da177e4SLinus Torvalds /**
7351da177e4SLinus Torvalds  * bus_rescan_devices - rescan devices on the bus for possible drivers
7361da177e4SLinus Torvalds  * @bus: the bus to scan.
7371da177e4SLinus Torvalds  *
7381da177e4SLinus Torvalds  * This function will look for devices on the bus with no driver
73923d3d602SGreg Kroah-Hartman  * attached and rescan it against existing drivers to see if it matches
74023d3d602SGreg Kroah-Hartman  * any by calling device_attach() for the unbound devices.
7411da177e4SLinus Torvalds  */
742f86db396SAndrew Morton int bus_rescan_devices(struct bus_type * bus)
7431da177e4SLinus Torvalds {
744f86db396SAndrew Morton 	return bus_for_each_dev(bus, NULL, NULL, bus_rescan_devices_helper);
7451da177e4SLinus Torvalds }
7461da177e4SLinus Torvalds 
747e935d5daSMoore, Eric /**
748e935d5daSMoore, Eric  * device_reprobe - remove driver for a device and probe for a new driver
749e935d5daSMoore, Eric  * @dev: the device to reprobe
750e935d5daSMoore, Eric  *
751e935d5daSMoore, Eric  * This function detaches the attached driver (if any) for the given
752e935d5daSMoore, Eric  * device and restarts the driver probing process.  It is intended
753e935d5daSMoore, Eric  * to use if probing criteria changed during a devices lifetime and
754e935d5daSMoore, Eric  * driver attachment should change accordingly.
755e935d5daSMoore, Eric  */
756f86db396SAndrew Morton int device_reprobe(struct device *dev)
757e935d5daSMoore, Eric {
758e935d5daSMoore, Eric 	if (dev->driver) {
759e935d5daSMoore, Eric 		if (dev->parent)        /* Needed for USB */
760e935d5daSMoore, Eric 			down(&dev->parent->sem);
761e935d5daSMoore, Eric 		device_release_driver(dev);
762e935d5daSMoore, Eric 		if (dev->parent)
763e935d5daSMoore, Eric 			up(&dev->parent->sem);
764e935d5daSMoore, Eric 	}
765f86db396SAndrew Morton 	return bus_rescan_devices_helper(dev, NULL);
766e935d5daSMoore, Eric }
767e935d5daSMoore, Eric EXPORT_SYMBOL_GPL(device_reprobe);
7681da177e4SLinus Torvalds 
7691da177e4SLinus Torvalds /**
7701da177e4SLinus Torvalds  *	find_bus - locate bus by name.
7711da177e4SLinus Torvalds  *	@name:	name of bus.
7721da177e4SLinus Torvalds  *
7731da177e4SLinus Torvalds  *	Call kset_find_obj() to iterate over list of buses to
7741da177e4SLinus Torvalds  *	find a bus by name. Return bus if found.
7751da177e4SLinus Torvalds  *
7761da177e4SLinus Torvalds  *	Note that kset_find_obj increments bus' reference count.
7771da177e4SLinus Torvalds  */
7787e4ef085SAdrian Bunk #if 0
7791da177e4SLinus Torvalds struct bus_type * find_bus(char * name)
7801da177e4SLinus Torvalds {
78159a54833SGreg Kroah-Hartman 	struct kobject * k = kset_find_obj(bus_kset, name);
7821da177e4SLinus Torvalds 	return k ? to_bus(k) : NULL;
7831da177e4SLinus Torvalds }
7847e4ef085SAdrian Bunk #endif  /*  0  */
7851da177e4SLinus Torvalds 
7861da177e4SLinus Torvalds 
7871da177e4SLinus Torvalds /**
7881da177e4SLinus Torvalds  *	bus_add_attrs - Add default attributes for this bus.
7891da177e4SLinus Torvalds  *	@bus:	Bus that has just been registered.
7901da177e4SLinus Torvalds  */
7911da177e4SLinus Torvalds 
7921da177e4SLinus Torvalds static int bus_add_attrs(struct bus_type * bus)
7931da177e4SLinus Torvalds {
7941da177e4SLinus Torvalds 	int error = 0;
7951da177e4SLinus Torvalds 	int i;
7961da177e4SLinus Torvalds 
7971da177e4SLinus Torvalds 	if (bus->bus_attrs) {
7981da177e4SLinus Torvalds 		for (i = 0; attr_name(bus->bus_attrs[i]); i++) {
799dc0afa83SCornelia Huck 			error = bus_create_file(bus,&bus->bus_attrs[i]);
800dc0afa83SCornelia Huck 			if (error)
8011da177e4SLinus Torvalds 				goto Err;
8021da177e4SLinus Torvalds 		}
8031da177e4SLinus Torvalds 	}
8041da177e4SLinus Torvalds  Done:
8051da177e4SLinus Torvalds 	return error;
8061da177e4SLinus Torvalds  Err:
8071da177e4SLinus Torvalds 	while (--i >= 0)
8081da177e4SLinus Torvalds 		bus_remove_file(bus,&bus->bus_attrs[i]);
8091da177e4SLinus Torvalds 	goto Done;
8101da177e4SLinus Torvalds }
8111da177e4SLinus Torvalds 
8121da177e4SLinus Torvalds static void bus_remove_attrs(struct bus_type * bus)
8131da177e4SLinus Torvalds {
8141da177e4SLinus Torvalds 	int i;
8151da177e4SLinus Torvalds 
8161da177e4SLinus Torvalds 	if (bus->bus_attrs) {
8171da177e4SLinus Torvalds 		for (i = 0; attr_name(bus->bus_attrs[i]); i++)
8181da177e4SLinus Torvalds 			bus_remove_file(bus,&bus->bus_attrs[i]);
8191da177e4SLinus Torvalds 	}
8201da177e4SLinus Torvalds }
8211da177e4SLinus Torvalds 
82234bb61f9SJames Bottomley static void klist_devices_get(struct klist_node *n)
82334bb61f9SJames Bottomley {
82434bb61f9SJames Bottomley 	struct device *dev = container_of(n, struct device, knode_bus);
82534bb61f9SJames Bottomley 
82634bb61f9SJames Bottomley 	get_device(dev);
82734bb61f9SJames Bottomley }
82834bb61f9SJames Bottomley 
82934bb61f9SJames Bottomley static void klist_devices_put(struct klist_node *n)
83034bb61f9SJames Bottomley {
83134bb61f9SJames Bottomley 	struct device *dev = container_of(n, struct device, knode_bus);
83234bb61f9SJames Bottomley 
83334bb61f9SJames Bottomley 	put_device(dev);
83434bb61f9SJames Bottomley }
83534bb61f9SJames Bottomley 
8367ac1cf4aSKay Sievers static ssize_t bus_uevent_store(struct bus_type *bus,
8377ac1cf4aSKay Sievers 				const char *buf, size_t count)
8387ac1cf4aSKay Sievers {
8397ac1cf4aSKay Sievers 	enum kobject_action action;
8407ac1cf4aSKay Sievers 
8417ac1cf4aSKay Sievers 	if (kobject_action_type(buf, count, &action) == 0)
842c6f7e72aSGreg Kroah-Hartman 		kobject_uevent(&bus->p->subsys.kobj, action);
8437ac1cf4aSKay Sievers 	return count;
8447ac1cf4aSKay Sievers }
8457ac1cf4aSKay Sievers static BUS_ATTR(uevent, S_IWUSR, NULL, bus_uevent_store);
8467ac1cf4aSKay Sievers 
8471da177e4SLinus Torvalds /**
8481da177e4SLinus Torvalds  *	bus_register - register a bus with the system.
8491da177e4SLinus Torvalds  *	@bus:	bus.
8501da177e4SLinus Torvalds  *
8511da177e4SLinus Torvalds  *	Once we have that, we registered the bus with the kobject
8521da177e4SLinus Torvalds  *	infrastructure, then register the children subsystems it has:
8531da177e4SLinus Torvalds  *	the devices and drivers that belong to the bus.
8541da177e4SLinus Torvalds  */
8551da177e4SLinus Torvalds int bus_register(struct bus_type * bus)
8561da177e4SLinus Torvalds {
8571da177e4SLinus Torvalds 	int retval;
858c6f7e72aSGreg Kroah-Hartman 	struct bus_type_private *priv;
8591da177e4SLinus Torvalds 
860c6f7e72aSGreg Kroah-Hartman 	priv = kzalloc(sizeof(struct bus_type_private), GFP_KERNEL);
861c6f7e72aSGreg Kroah-Hartman 	if (!priv)
862c6f7e72aSGreg Kroah-Hartman 		return -ENOMEM;
863116af378SBenjamin Herrenschmidt 
864c6f7e72aSGreg Kroah-Hartman 	priv->bus = bus;
865c6f7e72aSGreg Kroah-Hartman 	bus->p = priv;
866c6f7e72aSGreg Kroah-Hartman 
867c6f7e72aSGreg Kroah-Hartman 	BLOCKING_INIT_NOTIFIER_HEAD(&priv->bus_notifier);
868c6f7e72aSGreg Kroah-Hartman 
869c6f7e72aSGreg Kroah-Hartman 	retval = kobject_set_name(&priv->subsys.kobj, "%s", bus->name);
8701da177e4SLinus Torvalds 	if (retval)
8711da177e4SLinus Torvalds 		goto out;
8721da177e4SLinus Torvalds 
873c6f7e72aSGreg Kroah-Hartman 	priv->subsys.kobj.kset = bus_kset;
874c6f7e72aSGreg Kroah-Hartman 	priv->subsys.kobj.ktype = &bus_ktype;
875c6f7e72aSGreg Kroah-Hartman 	priv->drivers_autoprobe = 1;
876d6b05b84SGreg Kroah-Hartman 
877c6f7e72aSGreg Kroah-Hartman 	retval = kset_register(&priv->subsys);
8781da177e4SLinus Torvalds 	if (retval)
8791da177e4SLinus Torvalds 		goto out;
8801da177e4SLinus Torvalds 
8817ac1cf4aSKay Sievers 	retval = bus_create_file(bus, &bus_attr_uevent);
8827ac1cf4aSKay Sievers 	if (retval)
8837ac1cf4aSKay Sievers 		goto bus_uevent_fail;
8847ac1cf4aSKay Sievers 
885c6f7e72aSGreg Kroah-Hartman 	priv->devices_kset = kset_create_and_add("devices", NULL,
886c6f7e72aSGreg Kroah-Hartman 						 &priv->subsys.kobj);
887c6f7e72aSGreg Kroah-Hartman 	if (!priv->devices_kset) {
8883d899596SGreg Kroah-Hartman 		retval = -ENOMEM;
8891da177e4SLinus Torvalds 		goto bus_devices_fail;
8903d899596SGreg Kroah-Hartman 	}
8911da177e4SLinus Torvalds 
892c6f7e72aSGreg Kroah-Hartman 	priv->drivers_kset = kset_create_and_add("drivers", NULL,
893c6f7e72aSGreg Kroah-Hartman 						 &priv->subsys.kobj);
894c6f7e72aSGreg Kroah-Hartman 	if (!priv->drivers_kset) {
8956dcec251SGreg Kroah-Hartman 		retval = -ENOMEM;
8961da177e4SLinus Torvalds 		goto bus_drivers_fail;
8976dcec251SGreg Kroah-Hartman 	}
898465c7a3aSmochel@digitalimplant.org 
899c6f7e72aSGreg Kroah-Hartman 	klist_init(&priv->klist_devices, klist_devices_get, klist_devices_put);
900c6f7e72aSGreg Kroah-Hartman 	klist_init(&priv->klist_drivers, NULL, NULL);
901b8c5cec2SKay Sievers 
902b8c5cec2SKay Sievers 	retval = add_probe_files(bus);
903b8c5cec2SKay Sievers 	if (retval)
904b8c5cec2SKay Sievers 		goto bus_probe_files_fail;
905b8c5cec2SKay Sievers 
9061bb6881aSCornelia Huck 	retval = bus_add_attrs(bus);
9071bb6881aSCornelia Huck 	if (retval)
9081bb6881aSCornelia Huck 		goto bus_attrs_fail;
9091da177e4SLinus Torvalds 
910*7dc72b28SGreg Kroah-Hartman 	pr_debug("bus: '%s': registered\n", bus->name);
9111da177e4SLinus Torvalds 	return 0;
9121da177e4SLinus Torvalds 
9131bb6881aSCornelia Huck bus_attrs_fail:
914b8c5cec2SKay Sievers 	remove_probe_files(bus);
915b8c5cec2SKay Sievers bus_probe_files_fail:
916c6f7e72aSGreg Kroah-Hartman 	kset_unregister(bus->p->drivers_kset);
9171da177e4SLinus Torvalds bus_drivers_fail:
918c6f7e72aSGreg Kroah-Hartman 	kset_unregister(bus->p->devices_kset);
9191da177e4SLinus Torvalds bus_devices_fail:
9207ac1cf4aSKay Sievers 	bus_remove_file(bus, &bus_attr_uevent);
9217ac1cf4aSKay Sievers bus_uevent_fail:
922c6f7e72aSGreg Kroah-Hartman 	kset_unregister(&bus->p->subsys);
923c6f7e72aSGreg Kroah-Hartman 	kfree(bus->p);
9241da177e4SLinus Torvalds out:
9251da177e4SLinus Torvalds 	return retval;
9261da177e4SLinus Torvalds }
9271da177e4SLinus Torvalds 
9281da177e4SLinus Torvalds /**
9291da177e4SLinus Torvalds  *	bus_unregister - remove a bus from the system
9301da177e4SLinus Torvalds  *	@bus:	bus.
9311da177e4SLinus Torvalds  *
9321da177e4SLinus Torvalds  *	Unregister the child subsystems and the bus itself.
933fc1ede58SGreg Kroah-Hartman  *	Finally, we call bus_put() to release the refcount
9341da177e4SLinus Torvalds  */
9351da177e4SLinus Torvalds void bus_unregister(struct bus_type * bus)
9361da177e4SLinus Torvalds {
937*7dc72b28SGreg Kroah-Hartman 	pr_debug("bus: '%s': unregistering\n", bus->name);
9381da177e4SLinus Torvalds 	bus_remove_attrs(bus);
939b8c5cec2SKay Sievers 	remove_probe_files(bus);
940c6f7e72aSGreg Kroah-Hartman 	kset_unregister(bus->p->drivers_kset);
941c6f7e72aSGreg Kroah-Hartman 	kset_unregister(bus->p->devices_kset);
9427ac1cf4aSKay Sievers 	bus_remove_file(bus, &bus_attr_uevent);
943c6f7e72aSGreg Kroah-Hartman 	kset_unregister(&bus->p->subsys);
944c6f7e72aSGreg Kroah-Hartman 	kfree(bus->p);
9451da177e4SLinus Torvalds }
9461da177e4SLinus Torvalds 
947116af378SBenjamin Herrenschmidt int bus_register_notifier(struct bus_type *bus, struct notifier_block *nb)
948116af378SBenjamin Herrenschmidt {
949c6f7e72aSGreg Kroah-Hartman 	return blocking_notifier_chain_register(&bus->p->bus_notifier, nb);
950116af378SBenjamin Herrenschmidt }
951116af378SBenjamin Herrenschmidt EXPORT_SYMBOL_GPL(bus_register_notifier);
952116af378SBenjamin Herrenschmidt 
953116af378SBenjamin Herrenschmidt int bus_unregister_notifier(struct bus_type *bus, struct notifier_block *nb)
954116af378SBenjamin Herrenschmidt {
955c6f7e72aSGreg Kroah-Hartman 	return blocking_notifier_chain_unregister(&bus->p->bus_notifier, nb);
956116af378SBenjamin Herrenschmidt }
957116af378SBenjamin Herrenschmidt EXPORT_SYMBOL_GPL(bus_unregister_notifier);
958116af378SBenjamin Herrenschmidt 
9590fed80f7SGreg Kroah-Hartman struct kset *bus_get_kset(struct bus_type *bus)
9600fed80f7SGreg Kroah-Hartman {
961c6f7e72aSGreg Kroah-Hartman 	return &bus->p->subsys;
9620fed80f7SGreg Kroah-Hartman }
9630fed80f7SGreg Kroah-Hartman EXPORT_SYMBOL_GPL(bus_get_kset);
9640fed80f7SGreg Kroah-Hartman 
965b249072eSGreg Kroah-Hartman struct klist *bus_get_device_klist(struct bus_type *bus)
966b249072eSGreg Kroah-Hartman {
967c6f7e72aSGreg Kroah-Hartman 	return &bus->p->klist_devices;
968b249072eSGreg Kroah-Hartman }
969b249072eSGreg Kroah-Hartman EXPORT_SYMBOL_GPL(bus_get_device_klist);
970b249072eSGreg Kroah-Hartman 
9711da177e4SLinus Torvalds int __init buses_init(void)
9721da177e4SLinus Torvalds {
97359a54833SGreg Kroah-Hartman 	bus_kset = kset_create_and_add("bus", &bus_uevent_ops, NULL);
97459a54833SGreg Kroah-Hartman 	if (!bus_kset)
97559a54833SGreg Kroah-Hartman 		return -ENOMEM;
97659a54833SGreg Kroah-Hartman 	return 0;
9771da177e4SLinus Torvalds }
9781da177e4SLinus Torvalds 
9791da177e4SLinus Torvalds 
9801da177e4SLinus Torvalds EXPORT_SYMBOL_GPL(bus_for_each_dev);
9810edb5860SCornelia Huck EXPORT_SYMBOL_GPL(bus_find_device);
9821da177e4SLinus Torvalds EXPORT_SYMBOL_GPL(bus_for_each_drv);
9831da177e4SLinus Torvalds 
9841da177e4SLinus Torvalds EXPORT_SYMBOL_GPL(bus_register);
9851da177e4SLinus Torvalds EXPORT_SYMBOL_GPL(bus_unregister);
9861da177e4SLinus Torvalds EXPORT_SYMBOL_GPL(bus_rescan_devices);
9871da177e4SLinus Torvalds 
9881da177e4SLinus Torvalds EXPORT_SYMBOL_GPL(bus_create_file);
9891da177e4SLinus Torvalds EXPORT_SYMBOL_GPL(bus_remove_file);
990