public inbox for linux-kernel@vger.kernel.org
 help / color / mirror / Atom feed
From: Greg KH <greg@kroah.com>
To: linux-kernel@vger.kernel.org
Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org>,
	Greg Kroah-Hartman <gregkh@suse.de>
Subject: [PATCH 1/36] Driver core: add notification of bus events
Date: Fri,  1 Dec 2006 15:21:31 -0800	[thread overview]
Message-ID: <11650153262399-git-send-email-greg@kroah.com> (raw)
In-Reply-To: <20061201231620.GA7560@kroah.com>

From: Benjamin Herrenschmidt <benh@kernel.crashing.org>

I finally did as you suggested and added the notifier to the struct
bus_type itself. There are still problems to be expected is something
attaches to a bus type where the code can hook in different struct
device sub-classes (which is imho a big bogosity but I won't even try to
argue that case now) but it will solve nicely a number of issues I've
had so far.

That also means that clients interested in registering for such
notifications have to do it before devices are added and after bus types
are registered. Fortunately, most bus types that matter for the various
usage scenarios I have in mind are registerd at postcore_initcall time,
which means I have a really nice spot at arch_initcall time to add my
notifiers.

There are 4 notifications provided. Device being added (before hooked to
the bus) and removed (failure of previous case or after being unhooked
from the bus), along with driver being bound to a device and about to be
unbound.

The usage I have for these are:

 - The 2 first ones are used to maintain a struct device_ext that is
hooked to struct device.firmware_data. This structure contains for now a
pointer to the Open Firmware node related to the device (if any), the
NUMA node ID (for quick access to it) and the DMA operations pointers &
iommu table instance for DMA to/from this device. For bus types I own
(like IBM VIO or EBUS), I just maintain that structure directly from the
bus code when creating the devices. But for bus types managed by generic
code like PCI or platform (actually, of_platform which is a variation of
platform linked to Open Firmware device-tree), I need this notifier.

 - The other two ones have a completely different usage scenario. I have
cases where multiple devices and their drivers depend on each other. For
example, the IBM EMAC network driver needs to attach to a MAL DMA engine
which is a separate device, and a PHY interface which is also a separate
device. They are all of_platform_device's (well, about to be with my
upcoming patches) but there is no say in what precise order the core
will "probe" them and instanciate the various modules. The solution I
found for that is to have the drivers for emac to use multithread_probe,
and wait for a driver to be bound to the target MAL and PHY control
devices (the device-tree contains reference to the MAL and PHY interface
nodes, which I can then match to of_platform_devices). Right now, I've
been polling, but with that notifier, I can more cleanly wait (with a
timeout of course).

Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
---
 drivers/base/bus.c     |   14 ++++++++++++++
 drivers/base/core.c    |   12 ++++++++++++
 drivers/base/dd.c      |   10 ++++++++++
 include/linux/device.h |   25 +++++++++++++++++++++++++
 4 files changed, 61 insertions(+), 0 deletions(-)

diff --git a/drivers/base/bus.c b/drivers/base/bus.c
index 7d8a7ce..ed3e8a2 100644
--- a/drivers/base/bus.c
+++ b/drivers/base/bus.c
@@ -724,6 +724,8 @@ int bus_register(struct bus_type * bus)
 {
 	int retval;
 
+	BLOCKING_INIT_NOTIFIER_HEAD(&bus->bus_notifier);
+
 	retval = kobject_set_name(&bus->subsys.kset.kobj, "%s", bus->name);
 	if (retval)
 		goto out;
@@ -782,6 +784,18 @@ void bus_unregister(struct bus_type * bu
 	subsystem_unregister(&bus->subsys);
 }
 
+int bus_register_notifier(struct bus_type *bus, struct notifier_block *nb)
+{
+	return blocking_notifier_chain_register(&bus->bus_notifier, nb);
+}
+EXPORT_SYMBOL_GPL(bus_register_notifier);
+
+int bus_unregister_notifier(struct bus_type *bus, struct notifier_block *nb)
+{
+	return blocking_notifier_chain_unregister(&bus->bus_notifier, nb);
+}
+EXPORT_SYMBOL_GPL(bus_unregister_notifier);
+
 int __init buses_init(void)
 {
 	return subsystem_register(&bus_subsys);
diff --git a/drivers/base/core.c b/drivers/base/core.c
index 002fde4..d4f35d8 100644
--- a/drivers/base/core.c
+++ b/drivers/base/core.c
@@ -17,6 +17,7 @@
 #include <linux/slab.h>
 #include <linux/string.h>
 #include <linux/kdev_t.h>
+#include <linux/notifier.h>
 
 #include <asm/semaphore.h>
 
@@ -428,6 +429,11 @@ int device_add(struct device *dev)
 	if (platform_notify)
 		platform_notify(dev);
 
+	/* notify clients of device entry (new way) */
+	if (dev->bus)
+		blocking_notifier_call_chain(&dev->bus->bus_notifier,
+					     BUS_NOTIFY_ADD_DEVICE, dev);
+
 	dev->uevent_attr.attr.name = "uevent";
 	dev->uevent_attr.attr.mode = S_IWUSR;
 	if (dev->driver)
@@ -504,6 +510,9 @@ int device_add(struct device *dev)
  BusError:
 	device_pm_remove(dev);
  PMError:
+	if (dev->bus)
+		blocking_notifier_call_chain(&dev->bus->bus_notifier,
+					     BUS_NOTIFY_DEL_DEVICE, dev);
 	device_remove_groups(dev);
  GroupError:
  	device_remove_attrs(dev);
@@ -622,6 +631,9 @@ void device_del(struct device * dev)
 	 */
 	if (platform_notify_remove)
 		platform_notify_remove(dev);
+	if (dev->bus)
+		blocking_notifier_call_chain(&dev->bus->bus_notifier,
+					     BUS_NOTIFY_DEL_DEVICE, dev);
 	bus_remove_device(dev);
 	device_pm_remove(dev);
 	kobject_uevent(&dev->kobj, KOBJ_REMOVE);
diff --git a/drivers/base/dd.c b/drivers/base/dd.c
index c5d6bb4..9c88b1e 100644
--- a/drivers/base/dd.c
+++ b/drivers/base/dd.c
@@ -52,6 +52,11 @@ int device_bind_driver(struct device *de
 
 	pr_debug("bound device '%s' to driver '%s'\n",
 		 dev->bus_id, dev->driver->name);
+
+	if (dev->bus)
+		blocking_notifier_call_chain(&dev->bus->bus_notifier,
+					     BUS_NOTIFY_BOUND_DRIVER, dev);
+
 	klist_add_tail(&dev->knode_driver, &dev->driver->klist_devices);
 	ret = sysfs_create_link(&dev->driver->kobj, &dev->kobj,
 			  kobject_name(&dev->kobj));
@@ -288,6 +293,11 @@ static void __device_release_driver(stru
 		sysfs_remove_link(&dev->kobj, "driver");
 		klist_remove(&dev->knode_driver);
 
+		if (dev->bus)
+			blocking_notifier_call_chain(&dev->bus->bus_notifier,
+						     BUS_NOTIFY_UNBIND_DRIVER,
+						     dev);
+
 		if (dev->bus && dev->bus->remove)
 			dev->bus->remove(dev);
 		else if (drv->remove)
diff --git a/include/linux/device.h b/include/linux/device.h
index 9d4f6a9..b00e027 100644
--- a/include/linux/device.h
+++ b/include/linux/device.h
@@ -42,6 +42,8 @@ struct bus_type {
 	struct klist		klist_devices;
 	struct klist		klist_drivers;
 
+	struct blocking_notifier_head bus_notifier;
+
 	struct bus_attribute	* bus_attrs;
 	struct device_attribute	* dev_attrs;
 	struct driver_attribute	* drv_attrs;
@@ -75,6 +77,29 @@ int __must_check bus_for_each_drv(struct
 		struct device_driver *start, void *data,
 		int (*fn)(struct device_driver *, void *));
 
+/*
+ * Bus notifiers: Get notified of addition/removal of devices
+ * and binding/unbinding of drivers to devices.
+ * In the long run, it should be a replacement for the platform
+ * notify hooks.
+ */
+struct notifier_block;
+
+extern int bus_register_notifier(struct bus_type *bus,
+				 struct notifier_block *nb);
+extern int bus_unregister_notifier(struct bus_type *bus,
+				   struct notifier_block *nb);
+
+/* All 4 notifers below get called with the target struct device *
+ * as an argument. Note that those functions are likely to be called
+ * with the device semaphore held in the core, so be careful.
+ */
+#define BUS_NOTIFY_ADD_DEVICE		0x00000001 /* device added */
+#define BUS_NOTIFY_DEL_DEVICE		0x00000002 /* device removed */
+#define BUS_NOTIFY_BOUND_DRIVER		0x00000003 /* driver bound to device */
+#define BUS_NOTIFY_UNBIND_DRIVER	0x00000004 /* driver about to be
+						      unbound */
+
 /* driverfs interface for exporting bus attributes */
 
 struct bus_attribute {
-- 
1.4.4.1


  reply	other threads:[~2006-12-01 23:22 UTC|newest]

Thread overview: 46+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2006-12-01 23:16 [GIT PATCH] Driver core patches for 2.6.19 Greg KH
2006-12-01 23:21 ` Greg KH [this message]
2006-12-01 23:21   ` [PATCH 2/36] Driver core: fix "driver" symlink timing Greg KH
2006-12-01 23:21     ` [PATCH 3/36] Driver Core: Move virtual_device_parent() to core.c Greg KH
2006-12-01 23:21       ` [PATCH 4/36] CONFIG_SYSFS_DEPRECATED Greg KH
2006-12-01 23:21         ` [PATCH 5/36] Driver core: make old versions of udev work properly Greg KH
2006-12-01 23:21           ` [PATCH 6/36] CONFIG_SYSFS_DEPRECATED - bus symlinks Greg KH
2006-12-01 23:21             ` [PATCH 7/36] CONFIG_SYSFS_DEPRECATED - device symlinks Greg KH
2006-12-01 23:21               ` [PATCH 8/36] CONFIG_SYSFS_DEPRECATED - PHYSDEV* uevent variables Greg KH
2006-12-01 23:21                 ` [PATCH 9/36] CONFIG_SYSFS_DEPRECATED - class symlinks Greg KH
2006-12-01 23:21                   ` [PATCH 10/36] Driver core: convert vt code to use struct device Greg KH
2006-12-01 23:21                     ` [PATCH 11/36] Driver core: convert vc " Greg KH
2006-12-01 23:21                       ` [PATCH 12/36] Driver core: change misc class_devices to be real devices Greg KH
2006-12-01 23:21                         ` [PATCH 13/36] Driver core: convert tty core to use struct device Greg KH
2006-12-01 23:21                           ` [PATCH 14/36] Driver core: convert raw device code " Greg KH
2006-12-01 23:21                             ` [PATCH 15/36] I2C: convert i2c-dev to use struct device instead of struct class_device Greg KH
2006-12-01 23:21                               ` [PATCH 16/36] Driver core: convert msr code to use struct device Greg KH
2006-12-01 23:21                                 ` [PATCH 17/36] Driver core: convert cpuid " Greg KH
2006-12-01 23:21                                   ` [PATCH 18/36] Driver core: convert PPP " Greg KH
2006-12-01 23:21                                     ` [PATCH 19/36] Driver core: convert ppdev " Greg KH
2006-12-01 23:21                                       ` [PATCH 20/36] Driver core: convert mmc " Greg KH
2006-12-01 23:21                                         ` [PATCH 21/36] Driver core: convert firmware " Greg KH
2006-12-01 23:21                                           ` [PATCH 22/36] Driver core: convert fb " Greg KH
2006-12-01 23:21                                             ` [PATCH 23/36] Driver core: change mem class_devices to be real devices Greg KH
2006-12-01 23:21                                               ` [PATCH 24/36] Driver core: convert sound core to use struct device Greg KH
2006-12-01 23:21                                                 ` [PATCH 25/36] Driver core: add dev_archdata to " Greg KH
2006-12-01 23:21                                                   ` [PATCH 26/36] ACPI: Change ACPI to use dev_archdata instead of firmware_data Greg KH
2006-12-01 23:21                                                     ` [PATCH 27/36] Driver core: Call platform_notify_remove later Greg KH
2006-12-01 23:21                                                       ` [PATCH 28/36] cpu topology: consider sysfs_create_group return value Greg KH
2006-12-01 23:21                                                         ` [PATCH 29/36] sysfs: sysfs_write_file() writes zero terminated data Greg KH
2006-12-01 23:22                                                           ` [PATCH 30/36] driver core: Introduce device_find_child() Greg KH
2006-12-01 23:22                                                             ` [PATCH 31/36] Driver core: make drivers/base/core.c:setup_parent() static Greg KH
2006-12-01 23:22                                                               ` [PATCH 32/36] driver core: Introduce device_move(): move a device to a new parent Greg KH
2006-12-01 23:22                                                                 ` [PATCH 33/36] driver core: Use klist_remove() in device_move() Greg KH
2006-12-01 23:22                                                                   ` [PATCH 34/36] Driver core: platform_driver_probe(), can save codespace Greg KH
2006-12-01 23:22                                                                     ` [PATCH 35/36] Documentation/driver-model/platform.txt update/rewrite Greg KH
2006-12-01 23:22                                                                       ` [PATCH 36/36] Driver core: show drivers in /sys/module/ Greg KH
2006-12-03 16:26                                                                 ` [PATCH 32/36] driver core: Introduce device_move(): move a device to a new parent Marcel Holtmann
2006-12-04 19:58                                                                   ` Greg KH
2006-12-04 21:15                                                                     ` Marcel Holtmann
2006-12-04 23:05                                                                       ` Greg KH
2006-12-05 15:26                                                                         ` Marcel Holtmann
2006-12-06  5:58                                                                           ` Greg KH
2006-12-06  8:29                                                                             ` Marcel Holtmann
2006-12-06  9:03                                                                           ` Martin Schwidefsky
2007-01-08 13:21                                                                           ` Cornelia Huck

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=11650153262399-git-send-email-greg@kroah.com \
    --to=greg@kroah.com \
    --cc=benh@kernel.crashing.org \
    --cc=gregkh@suse.de \
    --cc=linux-kernel@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox