aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorKay Sievers <kay.sievers@vrfy.org>2007-02-16 11:33:36 -0500
committerGreg Kroah-Hartman <gregkh@suse.de>2007-04-27 13:57:28 -0400
commitb8c5cec23d5c33b767a1cddebd4f8813a9563e3c (patch)
treecffec2c5df58866aa6e7ed5540c2718a166c3246 /drivers
parenta456b7023e0abf80bb03b0bdf5471b48878e5c49 (diff)
Driver core: udev triggered device-<>driver binding
We get two per-bus sysfs files: ls-l /sys/subsystem/usb drwxr-xr-x 2 root root 0 2007-02-16 16:42 devices drwxr-xr-x 7 root root 0 2007-02-16 14:55 drivers -rw-r--r-- 1 root root 4096 2007-02-16 16:42 drivers_autoprobe --w------- 1 root root 4096 2007-02-16 16:42 drivers_probe The flag "drivers_autoprobe" controls the behavior of the bus to bind devices by default, or just initialize the device and leave it alone. The command "drivers_probe" accepts a bus_id and the bus tries to bind a driver to this device. Systems who want to control the driver binding with udev, switch off the bus initiated probing: echo 0 > /sys/subsystem/usb/drivers_autoprobe echo 0 > /sys/subsystem/pcmcia/drivers_autoprobe ... and initiate the probing with udev rules like: ACTION=="add", SUBSYSTEM=="usb", ATTR{subsystem/drivers_probe}="$kernel" ACTION=="add", SUBSYSTEM=="pcmcia", ATTR{subsystem/drivers_probe}="$kernel" ... Custom driver binding can happen in earlier rules by something like: ACTION=="add", SUBSYSTEM=="usb", \ ATTRS{idVendor}=="1234", ATTRS{idProduct}=="5678" \ ATTR{subsystem/drivers/<custom-driver>/bind}="$kernel" This is intended to solve the modprobe.conf mess with "install-rules", custom bind/unbind-scripts and all the weird things people invented over the years. It should also provide the functionality "libusual" was supposed to do. With udev, one can just write a udev rule to drive all USB-disks at the third port of USB-hub by the "ub" driver, and everything else by usb-storage. One can also instruct udev to bind different wireless drivers to identical cards - just selected by the pcmcia slot-number, and whatever ... To use the mentioned rules, it needs udev version 106, to be able to write ATTR{}="$kernel" to sysfs files. Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/base/bus.c84
1 files changed, 78 insertions, 6 deletions
diff --git a/drivers/base/bus.c b/drivers/base/bus.c
index 253868e03c70..9df2e6dff519 100644
--- a/drivers/base/bus.c
+++ b/drivers/base/bus.c
@@ -27,6 +27,9 @@
27#define to_driver(obj) container_of(obj, struct device_driver, kobj) 27#define to_driver(obj) container_of(obj, struct device_driver, kobj)
28 28
29 29
30static int __must_check bus_rescan_devices_helper(struct device *dev,
31 void *data);
32
30static ssize_t 33static ssize_t
31drv_attr_show(struct kobject * kobj, struct attribute * attr, char * buf) 34drv_attr_show(struct kobject * kobj, struct attribute * attr, char * buf)
32{ 35{
@@ -133,7 +136,6 @@ static decl_subsys(bus, &ktype_bus, NULL);
133 136
134 137
135#ifdef CONFIG_HOTPLUG 138#ifdef CONFIG_HOTPLUG
136
137/* Manually detach a device from its associated driver. */ 139/* Manually detach a device from its associated driver. */
138static int driver_helper(struct device *dev, void *data) 140static int driver_helper(struct device *dev, void *data)
139{ 141{
@@ -199,6 +201,33 @@ static ssize_t driver_bind(struct device_driver *drv,
199} 201}
200static DRIVER_ATTR(bind, S_IWUSR, NULL, driver_bind); 202static DRIVER_ATTR(bind, S_IWUSR, NULL, driver_bind);
201 203
204static ssize_t show_drivers_autoprobe(struct bus_type *bus, char *buf)
205{
206 return sprintf(buf, "%d\n", bus->drivers_autoprobe);
207}
208
209static ssize_t store_drivers_autoprobe(struct bus_type *bus,
210 const char *buf, size_t count)
211{
212 if (buf[0] == '0')
213 bus->drivers_autoprobe = 0;
214 else
215 bus->drivers_autoprobe = 1;
216 return count;
217}
218
219static ssize_t store_drivers_probe(struct bus_type *bus,
220 const char *buf, size_t count)
221{
222 struct device *dev;
223
224 dev = bus_find_device(bus, NULL, (void *)buf, driver_helper);
225 if (!dev)
226 return -ENODEV;
227 if (bus_rescan_devices_helper(dev, NULL) != 0)
228 return -EINVAL;
229 return count;
230}
202#endif 231#endif
203 232
204static struct device * next_device(struct klist_iter * i) 233static struct device * next_device(struct klist_iter * i)
@@ -425,7 +454,8 @@ int bus_attach_device(struct device * dev)
425 454
426 if (bus) { 455 if (bus) {
427 dev->is_registered = 1; 456 dev->is_registered = 1;
428 ret = device_attach(dev); 457 if (bus->drivers_autoprobe)
458 ret = device_attach(dev);
429 if (ret >= 0) { 459 if (ret >= 0) {
430 klist_add_tail(&dev->knode_bus, &bus->klist_devices); 460 klist_add_tail(&dev->knode_bus, &bus->klist_devices);
431 ret = 0; 461 ret = 0;
@@ -515,9 +545,41 @@ static void remove_bind_files(struct device_driver *drv)
515 driver_remove_file(drv, &driver_attr_bind); 545 driver_remove_file(drv, &driver_attr_bind);
516 driver_remove_file(drv, &driver_attr_unbind); 546 driver_remove_file(drv, &driver_attr_unbind);
517} 547}
548
549static int add_probe_files(struct bus_type *bus)
550{
551 int retval;
552
553 bus->drivers_probe_attr.attr.name = "drivers_probe";
554 bus->drivers_probe_attr.attr.mode = S_IWUSR;
555 bus->drivers_probe_attr.attr.owner = bus->owner;
556 bus->drivers_probe_attr.store = store_drivers_probe;
557 retval = bus_create_file(bus, &bus->drivers_probe_attr);
558 if (retval)
559 goto out;
560
561 bus->drivers_autoprobe_attr.attr.name = "drivers_autoprobe";
562 bus->drivers_autoprobe_attr.attr.mode = S_IWUSR | S_IRUGO;
563 bus->drivers_autoprobe_attr.attr.owner = bus->owner;
564 bus->drivers_autoprobe_attr.show = show_drivers_autoprobe;
565 bus->drivers_autoprobe_attr.store = store_drivers_autoprobe;
566 retval = bus_create_file(bus, &bus->drivers_autoprobe_attr);
567 if (retval)
568 bus_remove_file(bus, &bus->drivers_probe_attr);
569out:
570 return retval;
571}
572
573static void remove_probe_files(struct bus_type *bus)
574{
575 bus_remove_file(bus, &bus->drivers_autoprobe_attr);
576 bus_remove_file(bus, &bus->drivers_probe_attr);
577}
518#else 578#else
519static inline int add_bind_files(struct device_driver *drv) { return 0; } 579static inline int add_bind_files(struct device_driver *drv) { return 0; }
520static inline void remove_bind_files(struct device_driver *drv) {} 580static inline void remove_bind_files(struct device_driver *drv) {}
581static inline int add_probe_files(struct bus_type *bus) { return 0; }
582static inline void remove_probe_files(struct bus_type *bus) {}
521#endif 583#endif
522 584
523/** 585/**
@@ -541,9 +603,11 @@ int bus_add_driver(struct device_driver *drv)
541 if ((error = kobject_register(&drv->kobj))) 603 if ((error = kobject_register(&drv->kobj)))
542 goto out_put_bus; 604 goto out_put_bus;
543 605
544 error = driver_attach(drv); 606 if (drv->bus->drivers_autoprobe) {
545 if (error) 607 error = driver_attach(drv);
546 goto out_unregister; 608 if (error)
609 goto out_unregister;
610 }
547 klist_add_tail(&drv->knode_bus, &bus->klist_drivers); 611 klist_add_tail(&drv->knode_bus, &bus->klist_drivers);
548 module_add_driver(drv->owner, drv); 612 module_add_driver(drv->owner, drv);
549 613
@@ -762,6 +826,12 @@ int bus_register(struct bus_type * bus)
762 826
763 klist_init(&bus->klist_devices, klist_devices_get, klist_devices_put); 827 klist_init(&bus->klist_devices, klist_devices_get, klist_devices_put);
764 klist_init(&bus->klist_drivers, NULL, NULL); 828 klist_init(&bus->klist_drivers, NULL, NULL);
829
830 bus->drivers_autoprobe = 1;
831 retval = add_probe_files(bus);
832 if (retval)
833 goto bus_probe_files_fail;
834
765 retval = bus_add_attrs(bus); 835 retval = bus_add_attrs(bus);
766 if (retval) 836 if (retval)
767 goto bus_attrs_fail; 837 goto bus_attrs_fail;
@@ -770,6 +840,8 @@ int bus_register(struct bus_type * bus)
770 return 0; 840 return 0;
771 841
772bus_attrs_fail: 842bus_attrs_fail:
843 remove_probe_files(bus);
844bus_probe_files_fail:
773 kset_unregister(&bus->drivers); 845 kset_unregister(&bus->drivers);
774bus_drivers_fail: 846bus_drivers_fail:
775 kset_unregister(&bus->devices); 847 kset_unregister(&bus->devices);
@@ -779,7 +851,6 @@ out:
779 return retval; 851 return retval;
780} 852}
781 853
782
783/** 854/**
784 * bus_unregister - remove a bus from the system 855 * bus_unregister - remove a bus from the system
785 * @bus: bus. 856 * @bus: bus.
@@ -791,6 +862,7 @@ void bus_unregister(struct bus_type * bus)
791{ 862{
792 pr_debug("bus %s: unregistering\n", bus->name); 863 pr_debug("bus %s: unregistering\n", bus->name);
793 bus_remove_attrs(bus); 864 bus_remove_attrs(bus);
865 remove_probe_files(bus);
794 kset_unregister(&bus->drivers); 866 kset_unregister(&bus->drivers);
795 kset_unregister(&bus->devices); 867 kset_unregister(&bus->devices);
796 subsystem_unregister(&bus->subsys); 868 subsystem_unregister(&bus->subsys);