Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1763412AbZCaSo4 (ORCPT ); Tue, 31 Mar 2009 14:44:56 -0400 Received: (majordomo@vger.kernel.org) by vger.kernel.org id S1761042AbZCaSlU (ORCPT ); Tue, 31 Mar 2009 14:41:20 -0400 Received: from victor.provo.novell.com ([137.65.250.26]:54900 "EHLO victor.provo.novell.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1761671AbZCaSlA (ORCPT ); Tue, 31 Mar 2009 14:41:00 -0400 From: Gregory Haskins Subject: [RFC PATCH 04/17] vbus: add bus-registration notifiers To: linux-kernel@vger.kernel.org Cc: agraf@suse.de, pmullaney@novell.com, pmorreale@novell.com, anthony@codemonkey.ws, rusty@rustcorp.com.au, netdev@vger.kernel.org, kvm@vger.kernel.org Date: Tue, 31 Mar 2009 14:43:07 -0400 Message-ID: <20090331184307.28333.20322.stgit@dev.haskins.net> In-Reply-To: <20090331184057.28333.77287.stgit@dev.haskins.net> References: <20090331184057.28333.77287.stgit@dev.haskins.net> User-Agent: StGIT/0.14.3 MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 7bit Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Length: 4285 Lines: 161 We need to get hotswap events in environments which cannot use existing facilities (e.g. inotify). So we add a notifier-chain to allow client callbacks whenever an interface is {un}registered. Signed-off-by: Gregory Haskins --- include/linux/vbus.h | 15 +++++++++++++ kernel/vbus/core.c | 59 ++++++++++++++++++++++++++++++++++++++++++++++++++ kernel/vbus/vbus.h | 1 + 3 files changed, 75 insertions(+), 0 deletions(-) diff --git a/include/linux/vbus.h b/include/linux/vbus.h index 5f0566c..04db4ff 100644 --- a/include/linux/vbus.h +++ b/include/linux/vbus.h @@ -29,6 +29,7 @@ #include #include #include +#include struct vbus; struct task_struct; @@ -137,6 +138,20 @@ static inline void task_vbus_disassociate(struct task_struct *p) } } +enum { + VBUS_EVENT_DEVADD, + VBUS_EVENT_DEVDROP, +}; + +struct vbus_event_devadd { + const char *type; + unsigned long id; +}; + +int vbus_notifier_register(struct vbus *vbus, struct notifier_block *nb); +int vbus_notifier_unregister(struct vbus *vbus, struct notifier_block *nb); + + #else /* CONFIG_VBUS */ #define fork_vbus(p) do { } while (0) diff --git a/kernel/vbus/core.c b/kernel/vbus/core.c index 033999f..b6df487 100644 --- a/kernel/vbus/core.c +++ b/kernel/vbus/core.c @@ -89,6 +89,7 @@ int vbus_device_interface_register(struct vbus_device *dev, { int ret; struct vbus_devshell *ds = to_devshell(dev->kobj); + struct vbus_event_devadd ev; mutex_lock(&vbus->lock); @@ -124,6 +125,14 @@ int vbus_device_interface_register(struct vbus_device *dev, if (ret) goto error; + ev.type = intf->type; + ev.id = intf->id; + + /* and let any clients know about the new device */ + ret = raw_notifier_call_chain(&vbus->notifier, VBUS_EVENT_DEVADD, &ev); + if (ret < 0) + goto error; + mutex_unlock(&vbus->lock); return 0; @@ -144,6 +153,7 @@ int vbus_device_interface_unregister(struct vbus_device_interface *intf) mutex_lock(&vbus->lock); _interface_unregister(intf); + raw_notifier_call_chain(&vbus->notifier, VBUS_EVENT_DEVDROP, &intf->id); mutex_unlock(&vbus->lock); kobject_put(&intf->kobj); @@ -346,6 +356,8 @@ int vbus_create(const char *name, struct vbus **bus) _bus->next_id = 0; + RAW_INIT_NOTIFIER_HEAD(&_bus->notifier); + mutex_lock(&vbus_root.lock); ret = map_add(&vbus_root.buses.map, &_bus->node); @@ -358,6 +370,53 @@ int vbus_create(const char *name, struct vbus **bus) return 0; } +#define for_each_rbnode(node, root) \ + for (node = rb_first(root); node != NULL; node = rb_next(node)) + +int vbus_notifier_register(struct vbus *vbus, struct notifier_block *nb) +{ + int ret; + struct rb_node *node; + + mutex_lock(&vbus->lock); + + /* + * resync the client for any devices we might already have + */ + for_each_rbnode(node, &vbus->devices.map.root) { + struct vbus_device_interface *intf = node_to_intf(node); + struct vbus_event_devadd ev = { + .type = intf->type, + .id = intf->id, + }; + + ret = nb->notifier_call(nb, VBUS_EVENT_DEVADD, &ev); + if (ret & NOTIFY_STOP_MASK) { + mutex_unlock(&vbus->lock); + return -EPERM; + } + } + + ret = raw_notifier_chain_register(&vbus->notifier, nb); + + mutex_unlock(&vbus->lock); + + return ret; +} +EXPORT_SYMBOL_GPL(vbus_notifier_register); + +int vbus_notifier_unregister(struct vbus *vbus, struct notifier_block *nb) +{ + int ret; + + mutex_lock(&vbus->lock); + ret = raw_notifier_chain_unregister(&vbus->notifier, nb); + mutex_unlock(&vbus->lock); + + return ret; +} +EXPORT_SYMBOL_GPL(vbus_notifier_unregister); + static void devshell_release(struct kobject *kobj) { struct vbus_devshell *ds = container_of(kobj, diff --git a/kernel/vbus/vbus.h b/kernel/vbus/vbus.h index 1266d69..cd2676b 100644 --- a/kernel/vbus/vbus.h +++ b/kernel/vbus/vbus.h @@ -51,6 +51,7 @@ struct vbus { struct vbus_subdir members; unsigned long next_id; struct rb_node node; + struct raw_notifier_head notifier; }; struct vbus_member { -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/