Sophie

Sophie

distrib > Scientific%20Linux > 5x > x86_64 > by-pkgid > 27922b4260f65d317aabda37e42bbbff > files > 1828

kernel-2.6.18-238.el5.src.rpm

From: Mark McLoughlin <markmc@redhat.com>
Date: Tue, 14 Apr 2009 18:43:58 +0100
Subject: [misc] add /sys/bus/*/driver_probe
Message-id: 1239731038.8530.93.camel@blaa
O-Subject: [RHEL5.4 PATCH 1/5] [driver core] add /sys/bus/*/driver_probe
Bugzilla: 491842
RH-Acked-by: Prarit Bhargava <prarit@redhat.com>
RH-Acked-by: Don Dutile <ddutile@redhat.com>
RH-Acked-by: Chris Wright <chrisw@redhat.com>

https://bugzilla.redhat.com/491842

This patch adds a new per-bus sysfs file:

  # 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
  --w------- 1 root root 4096 2007-02-16 16:42 drivers_probe

The command "drivers_probe" accepts a bus_id and the bus tries to bind a
driver to this device.

This is needed by libvirt in order to re-bind the real device driver
to a PCI device once a guest is finished using it.

This is a backport of a patch which also included a drivers_autprobe
command. The original commit is here:

  http://git.kernel.org/?p=linux/kernel/git/torvalds/linux-2.6.git;a=commitdiff;h=b8c5cec23d

Signed-off-by: Mark McLoughlin <markmc@redhat.com>

diff --git a/drivers/base/bus.c b/drivers/base/bus.c
index 2643bf8..2beb313 100644
--- a/drivers/base/bus.c
+++ b/drivers/base/bus.c
@@ -27,6 +27,8 @@
 #define to_driver(obj) container_of(obj, struct device_driver, kobj)
 
 
+static int bus_rescan_devices_helper(struct device *dev, void *data);
+
 static ssize_t
 drv_attr_show(struct kobject * kobj, struct attribute * attr, char * buf)
 {
@@ -199,6 +201,18 @@ static ssize_t driver_bind(struct device_driver *drv,
 }
 static DRIVER_ATTR(bind, S_IWUSR, NULL, driver_bind);
 
+static ssize_t store_drivers_probe(struct bus_type *bus,
+				   const char *buf, size_t count)
+{
+	struct device *dev;
+
+	dev = bus_find_device(bus, NULL, (void *)buf, driver_helper);
+	if (!dev)
+		return -ENODEV;
+	if (bus_rescan_devices_helper(dev, NULL) != 0)
+		return -EINVAL;
+	return count;
+}
 #endif
 
 static struct device * next_device(struct klist_iter * i)
@@ -466,9 +480,23 @@ static void remove_bind_files(struct device_driver *drv)
 	driver_remove_file(drv, &driver_attr_bind);
 	driver_remove_file(drv, &driver_attr_unbind);
 }
+
+static BUS_ATTR(drivers_probe, S_IWUSR, NULL, store_drivers_probe);
+
+static int add_probe_files(struct bus_type *bus)
+{
+	return bus_create_file(bus, &bus_attr_drivers_probe);
+}
+
+static void remove_probe_files(struct bus_type *bus)
+{
+	bus_remove_file(bus, &bus_attr_drivers_probe);
+}
 #else
 static inline void add_bind_files(struct device_driver *drv) {}
 static inline void remove_bind_files(struct device_driver *drv) {}
+static inline int add_probe_files(struct bus_type *bus) { return 0; }
+static inline void remove_probe_files(struct bus_type *bus) {}
 #endif
 
 /**
@@ -786,11 +814,18 @@ int bus_register(struct bus_type * bus)
 
 	klist_init(&bus->klist_devices, klist_devices_get, klist_devices_put);
 	klist_init(&bus->klist_drivers, klist_drivers_get, klist_drivers_put);
+
+	retval = add_probe_files(bus);
+	if (retval)
+		goto bus_probe_files_fail;
+
 	bus_add_attrs(bus);
 
 	pr_debug("bus type '%s' registered\n", bus->name);
 	return 0;
 
+bus_probe_files_fail:
+	kset_unregister(&bus->drivers);
 bus_drivers_fail:
 	kset_unregister(&bus->devices);
 bus_devices_fail:
@@ -833,6 +868,7 @@ void bus_unregister(struct bus_type * bus)
 	pr_debug("bus %s: unregistering\n", bus->name);
 	free_notifier_for_bus(bus);
 	bus_remove_attrs(bus);
+	remove_probe_files(bus);
 	kset_unregister(&bus->drivers);
 	kset_unregister(&bus->devices);
 	subsystem_unregister(&bus->subsys);