aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/base/bus.c14
-rw-r--r--drivers/base/core.c12
-rw-r--r--drivers/base/dd.c10
-rw-r--r--include/linux/device.h25
4 files changed, 61 insertions, 0 deletions
diff --git a/drivers/base/bus.c b/drivers/base/bus.c
index 7d8a7ce73fb3..ed3e8a2be64a 100644
--- a/drivers/base/bus.c
+++ b/drivers/base/bus.c
@@ -724,6 +724,8 @@ int bus_register(struct bus_type * bus)
724{ 724{
725 int retval; 725 int retval;
726 726
727 BLOCKING_INIT_NOTIFIER_HEAD(&bus->bus_notifier);
728
727 retval = kobject_set_name(&bus->subsys.kset.kobj, "%s", bus->name); 729 retval = kobject_set_name(&bus->subsys.kset.kobj, "%s", bus->name);
728 if (retval) 730 if (retval)
729 goto out; 731 goto out;
@@ -782,6 +784,18 @@ void bus_unregister(struct bus_type * bus)
782 subsystem_unregister(&bus->subsys); 784 subsystem_unregister(&bus->subsys);
783} 785}
784 786
787int bus_register_notifier(struct bus_type *bus, struct notifier_block *nb)
788{
789 return blocking_notifier_chain_register(&bus->bus_notifier, nb);
790}
791EXPORT_SYMBOL_GPL(bus_register_notifier);
792
793int bus_unregister_notifier(struct bus_type *bus, struct notifier_block *nb)
794{
795 return blocking_notifier_chain_unregister(&bus->bus_notifier, nb);
796}
797EXPORT_SYMBOL_GPL(bus_unregister_notifier);
798
785int __init buses_init(void) 799int __init buses_init(void)
786{ 800{
787 return subsystem_register(&bus_subsys); 801 return subsystem_register(&bus_subsys);
diff --git a/drivers/base/core.c b/drivers/base/core.c
index 002fde46d38d..d4f35d8902a2 100644
--- a/drivers/base/core.c
+++ b/drivers/base/core.c
@@ -17,6 +17,7 @@
17#include <linux/slab.h> 17#include <linux/slab.h>
18#include <linux/string.h> 18#include <linux/string.h>
19#include <linux/kdev_t.h> 19#include <linux/kdev_t.h>
20#include <linux/notifier.h>
20 21
21#include <asm/semaphore.h> 22#include <asm/semaphore.h>
22 23
@@ -428,6 +429,11 @@ int device_add(struct device *dev)
428 if (platform_notify) 429 if (platform_notify)
429 platform_notify(dev); 430 platform_notify(dev);
430 431
432 /* notify clients of device entry (new way) */
433 if (dev->bus)
434 blocking_notifier_call_chain(&dev->bus->bus_notifier,
435 BUS_NOTIFY_ADD_DEVICE, dev);
436
431 dev->uevent_attr.attr.name = "uevent"; 437 dev->uevent_attr.attr.name = "uevent";
432 dev->uevent_attr.attr.mode = S_IWUSR; 438 dev->uevent_attr.attr.mode = S_IWUSR;
433 if (dev->driver) 439 if (dev->driver)
@@ -504,6 +510,9 @@ int device_add(struct device *dev)
504 BusError: 510 BusError:
505 device_pm_remove(dev); 511 device_pm_remove(dev);
506 PMError: 512 PMError:
513 if (dev->bus)
514 blocking_notifier_call_chain(&dev->bus->bus_notifier,
515 BUS_NOTIFY_DEL_DEVICE, dev);
507 device_remove_groups(dev); 516 device_remove_groups(dev);
508 GroupError: 517 GroupError:
509 device_remove_attrs(dev); 518 device_remove_attrs(dev);
@@ -622,6 +631,9 @@ void device_del(struct device * dev)
622 */ 631 */
623 if (platform_notify_remove) 632 if (platform_notify_remove)
624 platform_notify_remove(dev); 633 platform_notify_remove(dev);
634 if (dev->bus)
635 blocking_notifier_call_chain(&dev->bus->bus_notifier,
636 BUS_NOTIFY_DEL_DEVICE, dev);
625 bus_remove_device(dev); 637 bus_remove_device(dev);
626 device_pm_remove(dev); 638 device_pm_remove(dev);
627 kobject_uevent(&dev->kobj, KOBJ_REMOVE); 639 kobject_uevent(&dev->kobj, KOBJ_REMOVE);
diff --git a/drivers/base/dd.c b/drivers/base/dd.c
index c5d6bb4290ad..9c88b1e34bc3 100644
--- a/drivers/base/dd.c
+++ b/drivers/base/dd.c
@@ -52,6 +52,11 @@ int device_bind_driver(struct device *dev)
52 52
53 pr_debug("bound device '%s' to driver '%s'\n", 53 pr_debug("bound device '%s' to driver '%s'\n",
54 dev->bus_id, dev->driver->name); 54 dev->bus_id, dev->driver->name);
55
56 if (dev->bus)
57 blocking_notifier_call_chain(&dev->bus->bus_notifier,
58 BUS_NOTIFY_BOUND_DRIVER, dev);
59
55 klist_add_tail(&dev->knode_driver, &dev->driver->klist_devices); 60 klist_add_tail(&dev->knode_driver, &dev->driver->klist_devices);
56 ret = sysfs_create_link(&dev->driver->kobj, &dev->kobj, 61 ret = sysfs_create_link(&dev->driver->kobj, &dev->kobj,
57 kobject_name(&dev->kobj)); 62 kobject_name(&dev->kobj));
@@ -288,6 +293,11 @@ static void __device_release_driver(struct device * dev)
288 sysfs_remove_link(&dev->kobj, "driver"); 293 sysfs_remove_link(&dev->kobj, "driver");
289 klist_remove(&dev->knode_driver); 294 klist_remove(&dev->knode_driver);
290 295
296 if (dev->bus)
297 blocking_notifier_call_chain(&dev->bus->bus_notifier,
298 BUS_NOTIFY_UNBIND_DRIVER,
299 dev);
300
291 if (dev->bus && dev->bus->remove) 301 if (dev->bus && dev->bus->remove)
292 dev->bus->remove(dev); 302 dev->bus->remove(dev);
293 else if (drv->remove) 303 else if (drv->remove)
diff --git a/include/linux/device.h b/include/linux/device.h
index 9d4f6a963936..b00e02711393 100644
--- a/include/linux/device.h
+++ b/include/linux/device.h
@@ -42,6 +42,8 @@ struct bus_type {
42 struct klist klist_devices; 42 struct klist klist_devices;
43 struct klist klist_drivers; 43 struct klist klist_drivers;
44 44
45 struct blocking_notifier_head bus_notifier;
46
45 struct bus_attribute * bus_attrs; 47 struct bus_attribute * bus_attrs;
46 struct device_attribute * dev_attrs; 48 struct device_attribute * dev_attrs;
47 struct driver_attribute * drv_attrs; 49 struct driver_attribute * drv_attrs;
@@ -75,6 +77,29 @@ int __must_check bus_for_each_drv(struct bus_type *bus,
75 struct device_driver *start, void *data, 77 struct device_driver *start, void *data,
76 int (*fn)(struct device_driver *, void *)); 78 int (*fn)(struct device_driver *, void *));
77 79
80/*
81 * Bus notifiers: Get notified of addition/removal of devices
82 * and binding/unbinding of drivers to devices.
83 * In the long run, it should be a replacement for the platform
84 * notify hooks.
85 */
86struct notifier_block;
87
88extern int bus_register_notifier(struct bus_type *bus,
89 struct notifier_block *nb);
90extern int bus_unregister_notifier(struct bus_type *bus,
91 struct notifier_block *nb);
92
93/* All 4 notifers below get called with the target struct device *
94 * as an argument. Note that those functions are likely to be called
95 * with the device semaphore held in the core, so be careful.
96 */
97#define BUS_NOTIFY_ADD_DEVICE 0x00000001 /* device added */
98#define BUS_NOTIFY_DEL_DEVICE 0x00000002 /* device removed */
99#define BUS_NOTIFY_BOUND_DRIVER 0x00000003 /* driver bound to device */
100#define BUS_NOTIFY_UNBIND_DRIVER 0x00000004 /* driver about to be
101 unbound */
102
78/* driverfs interface for exporting bus attributes */ 103/* driverfs interface for exporting bus attributes */
79 104
80struct bus_attribute { 105struct bus_attribute {