* [RFC] drivers/base: Add bus_register_notifier_alldev() variant
@ 2009-03-06 16:10 Grant Likely
2009-03-11 16:26 ` Greg KH
0 siblings, 1 reply; 5+ messages in thread
From: Grant Likely @ 2009-03-06 16:10 UTC (permalink / raw)
Cc: linuxppc-dev, Greg Kroah-Hartman, linux-kernel
From: Grant Likely <grant.likely@secretlab.ca>
bus_register_notifier_alldev() is a variation on bus_register_notifier()
which also triggers the notifier callback for devices already on the bus
and already bound to drivers.
This function is useful for the case where a driver needs to get a
reference to a struct device other than the one it is bound to and
it is not known if the device will be bound before or after this
function is called. For example, an Ethernet device connected to
a PHY that is probed separately.
Signed-off-by: Grant Likely <grant.likely@secretlab.ca>
CC: linux-kernel@vger.kernel.org
CC: linuxppc-dev@ozlabs.org
CC: Greg Kroah-Hartman <gregkh@suse.de>
---
I'm using this as part of some changes to phylib to make it easier for
Ethernet drivers to find their PHY device. Before I'm completely committed
to this approach I'd like some feedback on this change to drivers core.
Thanks,
g.
drivers/base/bus.c | 47 +++++++++++++++++++++++++++++++++++++++++++++++
include/linux/device.h | 2 ++
2 files changed, 49 insertions(+), 0 deletions(-)
diff --git a/drivers/base/bus.c b/drivers/base/bus.c
index 83f32b8..6edde85 100644
--- a/drivers/base/bus.c
+++ b/drivers/base/bus.c
@@ -962,6 +962,53 @@ int bus_register_notifier(struct bus_type *bus, struct notifier_block *nb)
}
EXPORT_SYMBOL_GPL(bus_register_notifier);
+/**
+ * bus_register_notifier_alldev_helper - internal support function
+ * Used by bus_register_notifier_alldev() to create ADD and BOUND events
+ * for devices.
+ */
+static int bus_register_notifier_alldev_helper(struct device *dev, void *data)
+{
+ struct notifier_block *nb = data;
+ nb->notifier_call(nb, BUS_NOTIFY_ADD_DEVICE, dev);
+ if (dev->driver)
+ nb->notifier_call(nb, BUS_NOTIFY_BOUND_DRIVER, dev);
+ return 0;
+}
+
+/**
+ * bus_register_notifier_alldev - Register for bus events; include existing devs
+ * @bus: pointer to bus_type
+ * @nb: pointer to notifier block to register with the bus
+ *
+ * Similar to bus_register_notifier() except it also generates events for
+ * devices already on the bus when the notifier is registered. When this
+ * function is called the notifier is called once for each device with
+ * the BUS_NOTIFY_ADD_DEVICE event, and once for each device registered to
+ * a driver * with the BUS_NOTIFY_BOUND_DRIVER event.
+ *
+ * There is a small chance that the notifier could be called more than once
+ * for a device. This would happen if a new device was registered on the bus
+ * or bound to a driver between the call to bus_register_notifier() and the
+ * call to bus_for_each_dev(). The only way I can see to protect against
+ * this would be to take the klist_devices spinlock while calling the
+ * notifier; but that would be a Very Bad Thing (tm). Caller needs to be
+ * aware that a notifier called before this function returns might get
+ * called a second time on the same device.
+ */
+int bus_register_notifier_alldev(struct bus_type *b, struct notifier_block *nb)
+{
+ int ret;
+
+ ret = bus_register_notifier(b, nb);
+ if (ret == 0) {
+ bus_for_each_dev(b, NULL, nb,
+ bus_register_notifier_alldev_helper);
+ }
+ return ret;
+}
+EXPORT_SYMBOL_GPL(bus_register_notifier_alldev);
+
int bus_unregister_notifier(struct bus_type *bus, struct notifier_block *nb)
{
return blocking_notifier_chain_unregister(&bus->p->bus_notifier, nb);
diff --git a/include/linux/device.h b/include/linux/device.h
index 45e5b19..05c7d5b 100644
--- a/include/linux/device.h
+++ b/include/linux/device.h
@@ -103,6 +103,8 @@ struct notifier_block;
extern int bus_register_notifier(struct bus_type *bus,
struct notifier_block *nb);
+extern int bus_register_notifier_alldev(struct bus_type *b,
+ struct notifier_block *nb);
extern int bus_unregister_notifier(struct bus_type *bus,
struct notifier_block *nb);
^ permalink raw reply related [flat|nested] 5+ messages in thread
* Re: [RFC] drivers/base: Add bus_register_notifier_alldev() variant
2009-03-06 16:10 [RFC] drivers/base: Add bus_register_notifier_alldev() variant Grant Likely
@ 2009-03-11 16:26 ` Greg KH
2009-03-11 16:35 ` Grant Likely
0 siblings, 1 reply; 5+ messages in thread
From: Greg KH @ 2009-03-11 16:26 UTC (permalink / raw)
To: Grant Likely; +Cc: linuxppc-dev, linux-kernel
On Fri, Mar 06, 2009 at 09:10:19AM -0700, Grant Likely wrote:
> From: Grant Likely <grant.likely@secretlab.ca>
>
> bus_register_notifier_alldev() is a variation on bus_register_notifier()
> which also triggers the notifier callback for devices already on the bus
> and already bound to drivers.
>
> This function is useful for the case where a driver needs to get a
> reference to a struct device other than the one it is bound to and
> it is not known if the device will be bound before or after this
> function is called. For example, an Ethernet device connected to
> a PHY that is probed separately.
Can't you just walk the list of all devices already on the bus to get
"notified" of them, and then register your notifier handler as well (or
register it first, and then walk the list, which is pretty much what
your patch does)?
I see this api addition as just confusing people as to which one they
should register for :)
thanks,
greg k-h
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [RFC] drivers/base: Add bus_register_notifier_alldev() variant
2009-03-11 16:26 ` Greg KH
@ 2009-03-11 16:35 ` Grant Likely
2009-03-11 17:00 ` Greg KH
0 siblings, 1 reply; 5+ messages in thread
From: Grant Likely @ 2009-03-11 16:35 UTC (permalink / raw)
To: Greg KH; +Cc: linuxppc-dev, linux-kernel
On Wed, Mar 11, 2009 at 10:26 AM, Greg KH <gregkh@suse.de> wrote:
> On Fri, Mar 06, 2009 at 09:10:19AM -0700, Grant Likely wrote:
>> From: Grant Likely <grant.likely@secretlab.ca>
>>
>> bus_register_notifier_alldev() is a variation on bus_register_notifier()
>> which also triggers the notifier callback for devices already on the bus
>> and already bound to drivers.
>>
>> This function is useful for the case where a driver needs to get a
>> reference to a struct device other than the one it is bound to and
>> it is not known if the device will be bound before or after this
>> function is called. =A0For example, an Ethernet device connected to
>> a PHY that is probed separately.
>
> Can't you just walk the list of all devices already on the bus to get
> "notified" of them, and then register your notifier handler as well (or
> register it first, and then walk the list, which is pretty much what
> your patch does)?
Yes, and I originally did, but it looks to me like a useful common
pattern that is less error prone than open coding it.
g.
--=20
Grant Likely, B.Sc., P.Eng.
Secret Lab Technologies Ltd.
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [RFC] drivers/base: Add bus_register_notifier_alldev() variant
2009-03-11 16:35 ` Grant Likely
@ 2009-03-11 17:00 ` Greg KH
2009-03-16 21:22 ` Grant Likely
0 siblings, 1 reply; 5+ messages in thread
From: Greg KH @ 2009-03-11 17:00 UTC (permalink / raw)
To: Grant Likely; +Cc: linuxppc-dev, linux-kernel
On Wed, Mar 11, 2009 at 10:35:29AM -0600, Grant Likely wrote:
> On Wed, Mar 11, 2009 at 10:26 AM, Greg KH <gregkh@suse.de> wrote:
> > On Fri, Mar 06, 2009 at 09:10:19AM -0700, Grant Likely wrote:
> >> From: Grant Likely <grant.likely@secretlab.ca>
> >>
> >> bus_register_notifier_alldev() is a variation on bus_register_notifier()
> >> which also triggers the notifier callback for devices already on the bus
> >> and already bound to drivers.
> >>
> >> This function is useful for the case where a driver needs to get a
> >> reference to a struct device other than the one it is bound to and
> >> it is not known if the device will be bound before or after this
> >> function is called. For example, an Ethernet device connected to
> >> a PHY that is probed separately.
> >
> > Can't you just walk the list of all devices already on the bus to get
> > "notified" of them, and then register your notifier handler as well (or
> > register it first, and then walk the list, which is pretty much what
> > your patch does)?
>
> Yes, and I originally did, but it looks to me like a useful common
> pattern that is less error prone than open coding it.
How about we wait, and if someone else does the same thing, we then add
it to the core like this?
Actually, wouldn't it make more sense to just change the default
"bus_register_notifier" to do this? Is there some reason that the
caller would not want this kind of thing to happen?
thanks,
greg k-h
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [RFC] drivers/base: Add bus_register_notifier_alldev() variant
2009-03-11 17:00 ` Greg KH
@ 2009-03-16 21:22 ` Grant Likely
0 siblings, 0 replies; 5+ messages in thread
From: Grant Likely @ 2009-03-16 21:22 UTC (permalink / raw)
To: Greg KH; +Cc: linuxppc-dev, linux-kernel
On Wed, Mar 11, 2009 at 11:00 AM, Greg KH <gregkh@suse.de> wrote:
> On Wed, Mar 11, 2009 at 10:35:29AM -0600, Grant Likely wrote:
>> On Wed, Mar 11, 2009 at 10:26 AM, Greg KH <gregkh@suse.de> wrote:
>> > On Fri, Mar 06, 2009 at 09:10:19AM -0700, Grant Likely wrote:
>> >> From: Grant Likely <grant.likely@secretlab.ca>
>> >>
>> >> bus_register_notifier_alldev() is a variation on bus_register_notifie=
r()
>> >> which also triggers the notifier callback for devices already on the =
bus
>> >> and already bound to drivers.
>> >>
>> >> This function is useful for the case where a driver needs to get a
>> >> reference to a struct device other than the one it is bound to and
>> >> it is not known if the device will be bound before or after this
>> >> function is called. =A0For example, an Ethernet device connected to
>> >> a PHY that is probed separately.
>> >
>> > Can't you just walk the list of all devices already on the bus to get
>> > "notified" of them, and then register your notifier handler as well (o=
r
>> > register it first, and then walk the list, which is pretty much what
>> > your patch does)?
>>
>> Yes, and I originally did, but it looks to me like a useful common
>> pattern that is less error prone than open coding it.
>
> How about we wait, and if someone else does the same thing, we then add
> it to the core like this?
I'm okay with that. Actually, I had two drivers that were using this,
but that need has gone away because I've learned that I can defer
locating the other device to open() time. I still think that it may
be useful, but I agree that simply theoretical usage is not a good
reason to add the API.
> Actually, wouldn't it make more sense to just change the default
> "bus_register_notifier" to do this? =A0Is there some reason that the
> caller would not want this kind of thing to happen?
It doesn't look like there are many users of this facility, and from
looking at them it appears that adding the reporting of already
registered & bound devices would make sense. However, to do this my
patch would need to be fixed to eliminate the race condition where an
add or bind event could get reported more than once on a single
device. It looks like the existing users expect never to be called
more than once for each device. Unfortunately, I don't know how to
fix the race. I need to research more.
g.
--=20
Grant Likely, B.Sc., P.Eng.
Secret Lab Technologies Ltd.
^ permalink raw reply [flat|nested] 5+ messages in thread
end of thread, other threads:[~2009-03-16 21:22 UTC | newest]
Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2009-03-06 16:10 [RFC] drivers/base: Add bus_register_notifier_alldev() variant Grant Likely
2009-03-11 16:26 ` Greg KH
2009-03-11 16:35 ` Grant Likely
2009-03-11 17:00 ` Greg KH
2009-03-16 21:22 ` Grant Likely
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).