* A better way to sequence driver initialization? @ 2010-04-09 19:23 Bill Gatliff 2010-04-10 3:54 ` Bill Gatliff ` (2 more replies) 0 siblings, 3 replies; 17+ messages in thread From: Bill Gatliff @ 2010-04-09 19:23 UTC (permalink / raw) To: Linux/PPC Development, linux-embedded Guys: My recent post, "Requesting a GPIO that hasn't been registered yet", and Anton's reply thereto (thanks, Anton!) on linuxppc-dev got me thinking about the problem of dependencies between devices in different classes, and/or between drivers/devices in general. I'd like to float an idea to see if it's worth pursuing. Changing the link order to get drivers to initialize in the right order will always be a problem for someone--- the order will be right for some people, but exactly wrong for others. And the problem is made worse for Device Tree-based systems, where just about everything including IRQ descriptors are created on a demand and/or as-available basis. What if we let the kernel sort those dependencies out for us, at runtime? I think it's possible, and I can't be the only one who would like to see this happen. There are two parts to my idea for a solution. First part is to modify do_initcalls() so that it launches each initcall function in its own kernel thread. Wait, don't panic yet! Second, we create/modify functions like gpio_request() so that if they fail, they can optionally stop in a wait queue until the call could succeed. Then gpiochip_add() would signal that queue each time a new gpiochip was added. Functions like request_irq() and clk_get()--- and probably many others--- would do the same thing, but with their own wait queues. Something like this: static wait_queue_head_t requestor_wq; int gpiochip_add(struct gpio_chip *chip) { ... wake_up_interruptible(&requestor_wq); return status; } int gpio_request_wait(unsigned gpio, const char *label) { return wait_event_interruptible(&requestor_wq, !gpio_request(gpio, label)); } Or we might want to make the above code be the actual gpio_request(), and bury the wait_event_interruptible() inside of that. Doing so would prevent having to touch a lot of code, but would definitely change the behavior of gpio_request(). Not sure which approach is best. Finally, I think that do_initcalls() would turn into something like this: static void __init do_initcalls(void) { initcall_t *fn; for (fn = __early_initcall_end; fn < __initcall_end; fn++) kthread_create(do_one_initcall, *fn, "do_initcalls"); flush_scheduled_work(); } If someone doesn't tell me this is a stupid idea, I might post it to lkml. Now's your chance! :) b.g. -- Bill Gatliff bgat@billgatliff.com ^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: A better way to sequence driver initialization? 2010-04-09 19:23 A better way to sequence driver initialization? Bill Gatliff @ 2010-04-10 3:54 ` Bill Gatliff 2010-04-10 3:59 ` Bill Gatliff 2010-04-10 5:29 ` Grant Likely 2010-04-10 8:53 ` Benjamin Herrenschmidt 2 siblings, 1 reply; 17+ messages in thread From: Bill Gatliff @ 2010-04-10 3:54 UTC (permalink / raw) To: Linux/PPC Development, linux-embedded Bill Gatliff wrote: > If someone doesn't tell me this is a stupid idea, I might post it to > lkml. Now's your chance! :) > So I went ahead and tried it anyway: $ git diff init/main.c diff --git a/init/main.c b/init/main.c index dac44a9..1461d09 100644 --- a/init/main.c +++ b/init/main.c @@ -753,7 +753,11 @@ static void __init do_initcalls(void) initcall_t *fn; for (fn = __early_initcall_end; fn < __initcall_end; fn++) +#if 1 + kthread_run(do_one_initcall, *fn, "do_initcalls"); +#else do_one_initcall(*fn); +#endif /* Make sure there is no pending stuff from the initcall sequence */ flush_scheduled_work(); Interestingly, things didn't blow up as quickly as I had expected they would. :) Booting with initcall_debug=1 both with and without the kthread_run() mod has proven insightful. The first OOPS I get with the mod looks like this: ... calling ch_init+0x0/0x18 @ 325 Unable to handle kernel NULL pointer dereference at virtual address 00000000 pgd = c0004000 [00000000] *pgd=00000000 Internal error: Oops: 5 [#4] PREEMPT last sysfs file: Modules linked in: CPU: 0 Tainted: GD (2.6.33-rc5-csb737-00010-gaba040a-dirty #59) PC is at kset_find_obj+0x18/0x98 LR is at kset_find_obj+0x18/0x98 pc : [<c018156c>] lr : [<c018156c>] psr: 20000013 sp : c3937f68 ip : c3937f68 fp : 00000000 r10: 00000000 r9 : 00000000 r8 : 00000000 r7 : c0396a6f r6 : 00000000 r5 : 00000005 r4 : c03f03b0 r3 : 00000003 r2 : c3936000 r1 : 00000000 r0 : 00000001 Flags: nzCv IRQs on FIQs on Mode SVC_32 ISA ARM Segment kernel Control: 0005317f Table: 20004000 DAC: 00000017 Process do_initcalls (pid: 325, stack limit = 0xc3936270) Stack: (0xc3937f68 to 0xc3938000) 7f60: c03fc050 c03f03b0 00000005 c03f03b0 00000000 c01c471c 7f80: c03f03b0 00000005 c001e62c 00000000 00000000 c024007c 00000000 1b58d32c 7fa0: 00000005 c002c39c c381bfac c001e62c 1b58d32c 00000005 00000000 c3937fd4 7fc0: c381bfac c001e62c c002c340 c005cb3c 00000000 00000000 c3937fd8 c3937fd8 7fe0: 00000000 00000000 00000000 00000000 00000000 c002df78 00000000 00000000 [<c018156c>] (kset_find_obj+0x18/0x98) from [<c01c471c>] (driver_register+0x88/0x150) [<c01c471c>] (driver_register+0x88/0x150) from [<c024007c>] (__hid_register_driver+0x38/0x70) [<c024007c>] (__hid_register_driver+0x38/0x70) from [<c002c39c>] (do_one_initcall+0x5c/0x1c4) [<c002c39c>] (do_one_initcall+0x5c/0x1c4) from [<c005cb3c>] (kthread+0x78/0x80) [<c005cb3c>] (kthread+0x78/0x80) from [<c002df78>] (kernel_thread_exit+0x0/0x8) Code: e24dd004 e3a00001 e1a07001 ebfaf76c (e5963000) ---[ end trace f9bb68fd55862436 ]--- note: do_initcalls[325] exited with preempt_count 1 ... There is a ch_init() function in drivers/hid/hid-cherry.c. I think that function is calling hid_register_driver() before hid_init() has set up hid_bus_type. That causes kset_find_obj() to die because the kset structure it gets passed in ch_init() refers to a bus that doesn't exist yet. It's a plain 'ole initialization race. Maybe there are fewer places that would need wait queues than I originally thought! At least for drivers that use the device API, kset_find_obj() might be the only place that needs to wait until a device or bus appears. If I get a second next week, I might hack one in there and see how much farther I get... b.g. -- Bill Gatliff bgat@billgatliff.com ^ permalink raw reply related [flat|nested] 17+ messages in thread
* Re: A better way to sequence driver initialization? 2010-04-10 3:54 ` Bill Gatliff @ 2010-04-10 3:59 ` Bill Gatliff 2010-04-10 4:19 ` Bill Gatliff 0 siblings, 1 reply; 17+ messages in thread From: Bill Gatliff @ 2010-04-10 3:59 UTC (permalink / raw) To: Linux/PPC Development, linux-embedded Bill Gatliff wrote: > Maybe there are fewer places that would need wait queues than I > originally thought! At least for drivers that use the device API, > kset_find_obj() might be the only place that needs to wait until a > device or bus appears. ... and kset_register() might be the only place that calls wake_up_interruptible(). Wow. b.g. -- Bill Gatliff bgat@billgatliff.com ^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: A better way to sequence driver initialization? 2010-04-10 3:59 ` Bill Gatliff @ 2010-04-10 4:19 ` Bill Gatliff 0 siblings, 0 replies; 17+ messages in thread From: Bill Gatliff @ 2010-04-10 4:19 UTC (permalink / raw) To: Linux/PPC Development, linux-embedded Bill Gatliff wrote: > > ... and kset_register() might be the only place that calls > wake_up_interruptible(). Wow. > Wow, indeed. With just the attached patch, I get exactly one OOPS now--- in ssc_free(), which I think is getting called because atmel_ssc_modinit() is racing with something. I wasn't able to get all the way to mounting my NFS rootfs, I think because I'm getting to ip_auto_config() before my ethernet controller has registered! :) $ git diff lib/kobject.c diff --git a/lib/kobject.c b/lib/kobject.c index b512b74..e75556c 100644 --- a/lib/kobject.c +++ b/lib/kobject.c @@ -18,6 +18,10 @@ #include <linux/stat.h> #include <linux/slab.h> +#include <linux/sched.h> +#include <linux/wait.h> +DECLARE_WAIT_QUEUE_HEAD(kset_wait); + /* * populate_dir - populate directory with attributes. * @kobj: object we're working on. @@ -721,6 +725,7 @@ int kset_register(struct kset *k) if (err) return err; kobject_uevent(&k->kobj, KOBJ_ADD); + wake_up_interruptible(&kset_wait); return 0; } @@ -744,7 +749,7 @@ void kset_unregister(struct kset *k) * looking for a matching kobject. If matching object is found * take a reference and return the object. */ -struct kobject *kset_find_obj(struct kset *kset, const char *name) +struct kobject *__kset_find_obj(struct kset *kset, const char *name) { struct kobject *k; struct kobject *ret = NULL; @@ -760,6 +765,14 @@ struct kobject *kset_find_obj(struct kset *kset, const char *name) return ret; } +struct kobject *kset_find_obj(struct kset *kset, const char *name) +{ + struct kobject *ret = NULL; + wait_event_interruptible(kset_wait, (ret = __kset_find_obj(kset, name))); + return ret; +} + static void kset_release(struct kobject *kobj) { struct kset *kset = container_of(kobj, struct kset, kobj); b.g. -- Bill Gatliff bgat@billgatliff.com ^ permalink raw reply related [flat|nested] 17+ messages in thread
* Re: A better way to sequence driver initialization? 2010-04-09 19:23 A better way to sequence driver initialization? Bill Gatliff 2010-04-10 3:54 ` Bill Gatliff @ 2010-04-10 5:29 ` Grant Likely 2010-04-10 13:56 ` Bill Gatliff 2010-04-10 8:53 ` Benjamin Herrenschmidt 2 siblings, 1 reply; 17+ messages in thread From: Grant Likely @ 2010-04-10 5:29 UTC (permalink / raw) To: Bill Gatliff; +Cc: Linux/PPC Development, linux-embedded On Fri, Apr 9, 2010 at 1:23 PM, Bill Gatliff <bgat@billgatliff.com> wrote: > Guys: > > > My recent post, "Requesting a GPIO that hasn't been registered yet", and > Anton's reply thereto (thanks, Anton!) on linuxppc-dev got me thinking > about the problem of dependencies between devices in different classes, > and/or between drivers/devices in general. I'd like to float an idea to > see if it's worth pursuing. > > Changing the link order to get drivers to initialize in the right order > will always be a problem for someone--- the order will be right for some > people, but exactly wrong for others. And the problem is made worse for > Device Tree-based systems, where just about everything including IRQ > descriptors are created on a demand and/or as-available basis. What if > we let the kernel sort those dependencies out for us, at runtime? I > think it's possible, and I can't be the only one who would like to see > this happen. > > There are two parts to my idea for a solution. First part is to modify > do_initcalls() so that it launches each initcall function in its own > kernel thread. Wait, don't panic yet! Is initcall the right granularity? Shouldn't it be that each .probe() hook gets its own thread? Otherwise one device missing its resources could block another device using the same driver (whose resources are available) from probing. Regardless, parallel probe has be attempted and failed before. There are lots of fiddly bits to get right. In fact, there *used* to be code in the kernel that does exactly that. It was put in 2.6.20, but removed in 2.6.21-rc1. Here's the relevant commits, and a very interesting thread discussing the issues: http://git.kernel.org/?p=linux/kernel/git/torvalds/linux-2.6.git;a=commitdiff;h=21c7f30b1d3f8a3de3128478daca3ce203fc8733 http://git.kernel.org/?p=linux/kernel/git/torvalds/linux-2.6.git;a=commitdiff;h=5adc55da4a7758021bcc374904b0f8b076508a11 http://lkml.indiana.edu/hypermail/linux/kernel/0705.1/0205.html It is pointed out in that thread that a big part of the problem is that a large number of drivers in the tree just aren't safe for multithreaded probing which is kind of a showstopper. Now, maybe doing it at the initcall level makes it less scary and more sane, but I suspect that it will still expose a lot of broken code that assumes things are already set up because it has always been that way. > Second, we create/modify functions like gpio_request() so that if they > fail, they can optionally stop in a wait queue until the call could > succeed. Then gpiochip_add() would signal that queue each time a new > gpiochip was added. Functions like request_irq() and clk_get()--- and > probably many others--- would do the same thing, but with their own wait > queues. You could take a look at the bus notifier code too. I made an attempt at solving a similar problem between Ethernet MAC drivers and binding against the correct phy. I ended up solving the problem in a different way, but the experimenting I did convince me that it is a viable concept. Basically, if the driver depends on another resource/device then it can register a callback to be notified when a new device becomes available. Once the needed device shows up (or immediately if the device is already there), the driver gets called back and it can complete registration. Not quite the same model that you are talking about here, but it would solve the problem on a per-driver basis. > Something like this: > > static wait_queue_head_t requestor_wq; > > int gpiochip_add(struct gpio_chip *chip) > { > ... > wake_up_interruptible(&requestor_wq); > return status; > } > > int gpio_request_wait(unsigned gpio, const char *label) > { > return wait_event_interruptible(&requestor_wq, > !gpio_request(gpio, label)); > } > > > Or we might want to make the above code be the actual gpio_request(), > and bury the wait_event_interruptible() inside of that. Doing so would > prevent having to touch a lot of code, but would definitely change the > behavior of gpio_request(). Not sure which approach is best. > > Finally, I think that do_initcalls() would turn into something like this: > > static void __init do_initcalls(void) > { > initcall_t *fn; > > for (fn = __early_initcall_end; fn < __initcall_end; fn++) > kthread_create(do_one_initcall, *fn, "do_initcalls"); > > flush_scheduled_work(); > } > > > If someone doesn't tell me this is a stupid idea, I might post it to > lkml. Now's your chance! :) Have you dug into the Arjan's asynchronous function call infrastructure? http://lwn.net/Articles/314808/ g. ^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: A better way to sequence driver initialization? 2010-04-10 5:29 ` Grant Likely @ 2010-04-10 13:56 ` Bill Gatliff 0 siblings, 0 replies; 17+ messages in thread From: Bill Gatliff @ 2010-04-10 13:56 UTC (permalink / raw) To: Grant Likely; +Cc: Linux/PPC Development, linux-embedded Grant Likely wrote: > On Fri, Apr 9, 2010 at 1:23 PM, Bill Gatliff <bgat@billgatliff.com> wrote: > >> Guys: >> >> >> My recent post, "Requesting a GPIO that hasn't been registered yet", and >> Anton's reply thereto (thanks, Anton!) on linuxppc-dev got me thinking >> about the problem of dependencies between devices in different classes, >> and/or between drivers/devices in general. I'd like to float an idea to >> see if it's worth pursuing. >> >> Changing the link order to get drivers to initialize in the right order >> will always be a problem for someone--- the order will be right for some >> people, but exactly wrong for others. And the problem is made worse for >> Device Tree-based systems, where just about everything including IRQ >> descriptors are created on a demand and/or as-available basis. What if >> we let the kernel sort those dependencies out for us, at runtime? I >> think it's possible, and I can't be the only one who would like to see >> this happen. >> >> There are two parts to my idea for a solution. First part is to modify >> do_initcalls() so that it launches each initcall function in its own >> kernel thread. Wait, don't panic yet! >> > > Is initcall the right granularity? Shouldn't it be that each .probe() > hook gets its own thread? Otherwise one device missing its resources > could block another device using the same driver (whose resources are > available) from probing. Good point, one that I missed. Yea, I guess I really want multithreaded probing. > Regardless, parallel probe has be attempted and failed before. There are lots of fiddly bits to get right. > Yep. I wasnt aware of any specific attempts before, but I did suspect that there were fiddly bits lurking about. :) > In fact, there *used* to be code in the kernel that does exactly that. > It was put in 2.6.20, but removed in 2.6.21-rc1. Here's the relevant > commits, and a very interesting thread discussing the issues: > > http://git.kernel.org/?p=linux/kernel/git/torvalds/linux-2.6.git;a=commitdiff;h=21c7f30b1d3f8a3de3128478daca3ce203fc8733 > http://git.kernel.org/?p=linux/kernel/git/torvalds/linux-2.6.git;a=commitdiff;h=5adc55da4a7758021bcc374904b0f8b076508a11 > http://lkml.indiana.edu/hypermail/linux/kernel/0705.1/0205.html > > It is pointed out in that thread that a big part of the problem is > that a large number of drivers in the tree just aren't safe for > multithreaded probing which is kind of a showstopper. Now, maybe > doing it at the initcall level makes it less scary and more sane, but > I suspect that it will still expose a lot of broken code that assumes > things are already set up because it has always been that way. > Yep. > Not quite the same model that you are talking about here, but it would > solve the problem on a per-driver basis. > Yea, but it's the per-driver part that I'm trying to avoid. > Have you dug into the Arjan's asynchronous function call infrastructure? > > http://lwn.net/Articles/314808/ > No, but I think I will now. :) b.g. -- Bill Gatliff bgat@billgatliff.com ^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: A better way to sequence driver initialization? 2010-04-09 19:23 A better way to sequence driver initialization? Bill Gatliff 2010-04-10 3:54 ` Bill Gatliff 2010-04-10 5:29 ` Grant Likely @ 2010-04-10 8:53 ` Benjamin Herrenschmidt 2010-04-10 13:35 ` Bill Gatliff 2 siblings, 1 reply; 17+ messages in thread From: Benjamin Herrenschmidt @ 2010-04-10 8:53 UTC (permalink / raw) To: Bill Gatliff; +Cc: Linux/PPC Development, linux-embedded On Fri, 2010-04-09 at 14:23 -0500, Bill Gatliff wrote: > > My recent post, "Requesting a GPIO that hasn't been registered yet", and > Anton's reply thereto (thanks, Anton!) on linuxppc-dev got me thinking > about the problem of dependencies between devices in different classes, > and/or between drivers/devices in general. I'd like to float an idea to > see if it's worth pursuing. I'd rather do things a bit more explicitely and less prone to break existing stuff... something along the lines of, first defining a variant of the initcalls to enable that "multithreaded" stuff, along with an explicit wait_for_service("subsys:hid"); for example. One could also expose service deps via the module info, thus delaying module init, or things like that (in fact, initcalls could even come with a list of dependencies). Cheers, Ben. ^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: A better way to sequence driver initialization? 2010-04-10 8:53 ` Benjamin Herrenschmidt @ 2010-04-10 13:35 ` Bill Gatliff 2010-04-10 23:39 ` Paul Mundt 2010-04-11 7:15 ` Benjamin Herrenschmidt 0 siblings, 2 replies; 17+ messages in thread From: Bill Gatliff @ 2010-04-10 13:35 UTC (permalink / raw) To: Benjamin Herrenschmidt; +Cc: Linux/PPC Development, linux-embedded Benjamin Herrenschmidt wrote: > On Fri, 2010-04-09 at 14:23 -0500, Bill Gatliff wrote: > >> My recent post, "Requesting a GPIO that hasn't been registered yet", and >> Anton's reply thereto (thanks, Anton!) on linuxppc-dev got me thinking >> about the problem of dependencies between devices in different classes, >> and/or between drivers/devices in general. I'd like to float an idea to >> see if it's worth pursuing. >> > > I'd rather do things a bit more explicitely and less prone to break > existing stuff... something along the lines of, first defining a variant > of the initcalls to enable that "multithreaded" stuff, along with an > explicit wait_for_service("subsys:hid"); for example. > > One could also expose service deps via the module info, thus delaying > module init, or things like that (in fact, initcalls could even come > with a list of dependencies). > The general problem with your approach is that the module in question might not know what services it needs to wait for. Specific to my situation, the gpio-led code doesn't have any way of knowing that it needs to wait until my pca953x i2c devices have all been installed so that the gpio pin I have specified even exists. And short of setting up some kind of table in the board-specific code (or device tree, actually), I don't know how to communicate such a dependency without touching the generic gpio-led code--- which I'm trying to avoid. I just want gpio-led to try again if the gpio pin it has been provided can't be requested yet. And I can see the need for similar behavior in several other of my drivers, hence the desire to generalize things a bit. I'm pretty sure my approach is only half-baked, but it does seem to avoid the need to touch a bunch of existing code--- especially to add board-specific dependencies. It just give the system a tool to sort things out on its own. I do think your overall criticism is valid, though. b.g. -- Bill Gatliff bgat@billgatliff.com ^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: A better way to sequence driver initialization? 2010-04-10 13:35 ` Bill Gatliff @ 2010-04-10 23:39 ` Paul Mundt 2010-04-10 23:47 ` Grant Likely ` (2 more replies) 2010-04-11 7:15 ` Benjamin Herrenschmidt 1 sibling, 3 replies; 17+ messages in thread From: Paul Mundt @ 2010-04-10 23:39 UTC (permalink / raw) To: Bill Gatliff Cc: Benjamin Herrenschmidt, Linux/PPC Development, linux-embedded On Sat, Apr 10, 2010 at 08:35:41AM -0500, Bill Gatliff wrote: > Benjamin Herrenschmidt wrote: > > On Fri, 2010-04-09 at 14:23 -0500, Bill Gatliff wrote: > > > >> My recent post, "Requesting a GPIO that hasn't been registered yet", and > >> Anton's reply thereto (thanks, Anton!) on linuxppc-dev got me thinking > >> about the problem of dependencies between devices in different classes, > >> and/or between drivers/devices in general. I'd like to float an idea to > >> see if it's worth pursuing. > >> > > > > I'd rather do things a bit more explicitely and less prone to break > > existing stuff... something along the lines of, first defining a variant > > of the initcalls to enable that "multithreaded" stuff, along with an > > explicit wait_for_service("subsys:hid"); for example. > > > > One could also expose service deps via the module info, thus delaying > > module init, or things like that (in fact, initcalls could even come > > with a list of dependencies). > > > > The general problem with your approach is that the module in question > might not know what services it needs to wait for. > > Specific to my situation, the gpio-led code doesn't have any way of > knowing that it needs to wait until my pca953x i2c devices have all been > installed so that the gpio pin I have specified even exists. And short > of setting up some kind of table in the board-specific code (or device > tree, actually), I don't know how to communicate such a dependency > without touching the generic gpio-led code--- which I'm trying to avoid. > This is a common problem for drivers that are all stuck on the same initcall level and as a result are entirely dependent on link order. Some more intelligent logic via the bus notifiers would help with some of this, but it wouldn't help with drivers that are effectively unable to probe for devices and that are entirely dependent on registration timing to make sure that their backing device has become available. You could also look at doing multi-threaded probing at the bus level where the semantics and implications are better understood, but that still doesn't necessarily help with ordering. (ie, registering a GPIO expander on a PCI MFD before being able to bring up gpio-leds or so). There has been past work for both multi-threading the probe routines as well as constraining it and only doing it for things like PCI. In cases where you can specifically note that dependencies, doing so will save you a world of pain. Despite that, it's simply not possible to do this as a free-for-all. Devices or busses that can tolerate multi-threaded probing need to be converted over one at a time, but even then you still need the dependency tracking for those that depend on link order today. Vendors often end up doing this sort of work for device-specific kernels where the underlying set of drivers is fixed, so there are also some alternative approaches you can investigate there (OLPC comes to mind). ^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: A better way to sequence driver initialization? 2010-04-10 23:39 ` Paul Mundt @ 2010-04-10 23:47 ` Grant Likely 2010-04-11 1:33 ` Bill Gatliff 2010-04-11 1:31 ` Bill Gatliff 2010-04-11 7:18 ` Benjamin Herrenschmidt 2 siblings, 1 reply; 17+ messages in thread From: Grant Likely @ 2010-04-10 23:47 UTC (permalink / raw) To: Paul Mundt Cc: Bill Gatliff, Benjamin Herrenschmidt, Linux/PPC Development, linux-embedded On Sat, Apr 10, 2010 at 5:39 PM, Paul Mundt <lethal@linux-sh.org> wrote: > In cases where you can specifically note that dependencies, doing so will > save you a world of pain. Despite that, it's simply not possible to do > this as a free-for-all. Devices or busses that can tolerate multi-threaded > probing need to be converted over one at a time, but even then you still > need the dependency tracking for those that depend on link order today. Well stated. g. ^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: A better way to sequence driver initialization? 2010-04-10 23:47 ` Grant Likely @ 2010-04-11 1:33 ` Bill Gatliff 2010-04-11 1:47 ` Paul Mundt 0 siblings, 1 reply; 17+ messages in thread From: Bill Gatliff @ 2010-04-11 1:33 UTC (permalink / raw) To: Grant Likely Cc: Paul Mundt, Benjamin Herrenschmidt, Linux/PPC Development, linux-embedded Grant Likely wrote: > On Sat, Apr 10, 2010 at 5:39 PM, Paul Mundt <lethal@linux-sh.org> wrote: > >> In cases where you can specifically note that dependencies, doing so will >> save you a world of pain. Despite that, it's simply not possible to do >> this as a free-for-all. Devices or busses that can tolerate multi-threaded >> probing need to be converted over one at a time, but even then you still >> need the dependency tracking for those that depend on link order today. >> Who's to say a function like gpio_request_wait_for_it(GPIO_NUMBER, "dependent-driver") isn't the way to do the dependency tracking? I can't even implement that without a context that can sleep... b.g. -- Bill Gatliff bgat@billgatliff.com ^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: A better way to sequence driver initialization? 2010-04-11 1:33 ` Bill Gatliff @ 2010-04-11 1:47 ` Paul Mundt 2010-04-11 3:30 ` Bill Gatliff 0 siblings, 1 reply; 17+ messages in thread From: Paul Mundt @ 2010-04-11 1:47 UTC (permalink / raw) To: Bill Gatliff Cc: Grant Likely, Benjamin Herrenschmidt, Linux/PPC Development, linux-embedded On Sat, Apr 10, 2010 at 08:33:53PM -0500, Bill Gatliff wrote: > Grant Likely wrote: > > On Sat, Apr 10, 2010 at 5:39 PM, Paul Mundt <lethal@linux-sh.org> wrote: > > > >> In cases where you can specifically note that dependencies, doing so will > >> save you a world of pain. Despite that, it's simply not possible to do > >> this as a free-for-all. Devices or busses that can tolerate multi-threaded > >> probing need to be converted over one at a time, but even then you still > >> need the dependency tracking for those that depend on link order today. > >> > > Who's to say a function like gpio_request_wait_for_it(GPIO_NUMBER, > "dependent-driver") isn't the way to do the dependency tracking? I > can't even implement that without a context that can sleep... > In some cases that might be valid, but there are many cases where drivers can reconfigure their capability sets based on which GPIOs are and aren't available. Just because a pin isn't available doesn't make it a show-stopper for the probe path.. ^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: A better way to sequence driver initialization? 2010-04-11 1:47 ` Paul Mundt @ 2010-04-11 3:30 ` Bill Gatliff 0 siblings, 0 replies; 17+ messages in thread From: Bill Gatliff @ 2010-04-11 3:30 UTC (permalink / raw) To: Paul Mundt Cc: Grant Likely, Benjamin Herrenschmidt, Linux/PPC Development, linux-embedded Paul Mundt wrote: > In some cases that might be valid, but there are many cases where drivers > can reconfigure their capability sets based on which GPIOs are and aren't > available. Just because a pin isn't available doesn't make it a > show-stopper for the probe path.. > Understood. I just tweaked my kernel to run all probe()s in their own kthreads. The results were a mixed bag, as expected. On the one hand, it's pretty cool to see everything running in parallel! On the other hand, I can see now yet another big reason why a probe free-for-all won't work. Busses are also devices, so there are plenty of places where a device for a particular bus type won't be able to probe because the target bus simply doesn't exist yet. That's yet another dependency that I hadn't thought about. Were I to rewrite Linux :), I would make probing parallel from the beginning. But I think I'm going to have to settle for now with kthreading my probes that might want to sleep, and adding a wait queue to gpio_request() and a few others. It ain't perfect, but it is achieveable. *sigh* b.g. -- Bill Gatliff bgat@billgatliff.com ^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: A better way to sequence driver initialization? 2010-04-10 23:39 ` Paul Mundt 2010-04-10 23:47 ` Grant Likely @ 2010-04-11 1:31 ` Bill Gatliff 2010-04-11 7:26 ` Benjamin Herrenschmidt 2010-04-11 7:18 ` Benjamin Herrenschmidt 2 siblings, 1 reply; 17+ messages in thread From: Bill Gatliff @ 2010-04-11 1:31 UTC (permalink / raw) To: Paul Mundt; +Cc: Benjamin Herrenschmidt, Linux/PPC Development, linux-embedded Paul Mundt wrote: > > In cases where you can specifically note that dependencies, doing so will > save you a world of pain. Despite that, it's simply not possible to do > this as a free-for-all. Devices or busses that can tolerate multi-threaded > probing need to be converted over one at a time, but even then you still > need the dependency tracking for those that depend on link order today. > Right now I'm thinking mostly about GPIO devices which need to register before things like gpio-leds can use them. Sometimes the GPIO expansion chip of interest is on i2c, other times it's spi, and still others it's a platform or USB device. Linking the gpio-led driver late helps that specific situation. But what about when I want to use a pin on a GPIO expansion device as the card-detect for an MMC slot? Or, as I've just recently noticed in one hardware platform I'm working on, using a pin on a SPI GPIO expander as a chip-select for another SPI device, but through gpiolib? Eventually, the dependencies don't become circular but changing the link order will break some and fix others. Ugh. Definitely, a free-for-all isn't going to work. But I don't think that having every driver do its own kthread_run() is a solution, either. I'll keep tinkering. :) b.g. -- Bill Gatliff bgat@billgatliff.com ^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: A better way to sequence driver initialization? 2010-04-11 1:31 ` Bill Gatliff @ 2010-04-11 7:26 ` Benjamin Herrenschmidt 0 siblings, 0 replies; 17+ messages in thread From: Benjamin Herrenschmidt @ 2010-04-11 7:26 UTC (permalink / raw) To: Bill Gatliff; +Cc: Paul Mundt, Linux/PPC Development, linux-embedded On Sat, 2010-04-10 at 20:31 -0500, Bill Gatliff wrote: > Right now I'm thinking mostly about GPIO devices which need to register > before things like gpio-leds can use them. Sometimes the GPIO expansion > chip of interest is on i2c, other times it's spi, and still others it's > a platform or USB device. Linking the gpio-led driver late helps that > specific situation. What it boils down to is that driver A depends on a service provided by driver B. At some stage, your dependency -has- to be expressed. Either using the device-tree, or by hard wiring a GPIO number, maybe by having the platform code figure out the GPIO number and shoving it into a platform_data structure, etc... but at -some- point, driver "A" needs some kind of "identifier" to the service provided by driver "B". In our case, let's say it's a GPIO number. That's when you can start kicking in a simple mechanism for exporting services. Let's say the GPIO layer does register_service("gpio", gpio_service_query); With something like int gpio_service_query(const char *query_string); Which can parse whatever arguments are passed after the service name and return success or failure (or even return a struct device *, whatever, this is just a rough sketch). From there, you can have for the drivers something like: request_service(const char *name, struct device *myself); Which takes a service name of the form "service:args", for example "gpio:5" for GPIO #5. That returns 0 if found, -EAGAIN if not found yet, -EINVAL if rejected (the service "gpio" can decide that there cannot be a GPIO 5 on the system, whatever) for example. In addition, it would attach "myself" (if non-NULL) to an internal list so that later, it's probe() routine can be called again. We then add a way for probe() to return -EAGAIN to put the driver "on hold" silently. And finally, maybe a way for services to re-run their query (new GPIOs were added for example) for all "pending" drivers. I haven't looked at the flip side here which is service -removal- of course. We may get away without dealing with it... tbd. > But what about when I want to use a pin on a GPIO expansion device as > the card-detect for an MMC slot? Or, as I've just recently noticed in > one hardware platform I'm working on, using a pin on a SPI GPIO expander > as a chip-select for another SPI device, but through gpiolib? > Eventually, the dependencies don't become circular but changing the link > order will break some and fix others. Ugh. As I said above, at some stage, -somebody- can identify the dependency, which ends up being translated into a GPIO number, an OF device path, or something .... That should be enough for the above to be made to fit no ? > Definitely, a free-for-all isn't going to work. But I don't think that > having every driver do its own kthread_run() is a solution, either. > I'll keep tinkering. :) I'd rather keep threads out of the picture for now. IE. Leave the decision as to do threaded probing or not at a different level. Cheers, Ben. ^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: A better way to sequence driver initialization? 2010-04-10 23:39 ` Paul Mundt 2010-04-10 23:47 ` Grant Likely 2010-04-11 1:31 ` Bill Gatliff @ 2010-04-11 7:18 ` Benjamin Herrenschmidt 2 siblings, 0 replies; 17+ messages in thread From: Benjamin Herrenschmidt @ 2010-04-11 7:18 UTC (permalink / raw) To: Paul Mundt; +Cc: Bill Gatliff, Linux/PPC Development, linux-embedded On Sun, 2010-04-11 at 08:39 +0900, Paul Mundt wrote: > This is a common problem for drivers that are all stuck on the same > initcall level and as a result are entirely dependent on link order. Some > more intelligent logic via the bus notifiers would help with some of > this, but it wouldn't help with drivers that are effectively unable to > probe for devices and that are entirely dependent on registration timing > to make sure that their backing device has become available. Right. Exactly my problem with EMAC for example. > You could also look at doing multi-threaded probing at the bus level > where the semantics and implications are better understood, but that > still doesn't necessarily help with ordering. (ie, registering a GPIO > expander on a PCI MFD before being able to bring up gpio-leds or > so). There has been past work for both multi-threading the probe routines > as well as constraining it and only doing it for things like PCI. I'd like to detatch the ordering problem from the threading feature, those are mostly orthogonal. We could solve the ordering problem with either some creative way of defining dependencies statically (but I personally think that's doomed) or a way for probe() to return -EAGAIN after the driver got a chance to attach itself to some kind of mechanism to re-trigger the probing when some condition is satisfied (bus notifier ? exported service names as in my previous example ? some combo of these ?). Then for archs like powerpc, we can add a layer to automate maybe the dependency resolution by using the device-tree, though the underlying mechanism doesn't need to be device-tree based. > In cases where you can specifically note that dependencies, doing so will > save you a world of pain. Despite that, it's simply not possible to do > this as a free-for-all. Devices or busses that can tolerate multi-threaded > probing need to be converted over one at a time, but even then you still > need the dependency tracking for those that depend on link order today. > > Vendors often end up doing this sort of work for device-specific kernels > where the underlying set of drivers is fixed, so there are also some > alternative approaches you can investigate there (OLPC comes to mind). As I said above, I think we should keep the dependency handling from the threading two separate things :-) ^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: A better way to sequence driver initialization? 2010-04-10 13:35 ` Bill Gatliff 2010-04-10 23:39 ` Paul Mundt @ 2010-04-11 7:15 ` Benjamin Herrenschmidt 1 sibling, 0 replies; 17+ messages in thread From: Benjamin Herrenschmidt @ 2010-04-11 7:15 UTC (permalink / raw) To: Bill Gatliff; +Cc: Linux/PPC Development, linux-embedded > The general problem with your approach is that the module in question > might not know what services it needs to wait for. The device-tree could provide a lot of help here, by providing a way to wait for a service attached to a given device-node since -that- at least contains the linkage we need. In fact, I could use something like that with the ibm_newemac driver where I have various bits and pieces probed separately (MAL - aka DMA engine, MII interface, core MAC, etc...) and right now I go through horrible hacks to ensure all the drivers have called home. I do have explicit links in the device-tree, so what I really want is for a driver attached to a device node to be able to say "I'm now operational" and for other drivers to wait on that. In fact, we don't necessarily need to use threads for that. We could have a way for a device to return something like -EAGAIN from probe(), maybe having called some kind of request_service(node,...) on all the dependencies, if any of them isn't satisfied. The core would then be able to finally call probe() again when they are. That has the advantage of leaving the amount of threading required to the core, rather than making it a driver decision, since we don't want -too- many probing threads in parallel. > Specific to my situation, the gpio-led code doesn't have any way of > knowing that it needs to wait until my pca953x i2c devices have all been > installed so that the gpio pin I have specified even exists. It could know that via the device-tree. Or on more paleolithic architectures, via a GPIO number though that sucks. Note that my wait_for_service() example takes a string. That string in my mind can be a compound, such as "gpio:#5" for example. > And short > of setting up some kind of table in the board-specific code (or device > tree, actually), I don't know how to communicate such a dependency > without touching the generic gpio-led code--- which I'm trying to avoid. > > I just want gpio-led to try again if the gpio pin it has been provided > can't be requested yet. And I can see the need for similar behavior in > several other of my drivers, hence the desire to generalize things a > bit. I'm pretty sure my approach is only half-baked, but it does seem > to avoid the need to touch a bunch of existing code--- especially to add > board-specific dependencies. It just give the system a tool to sort > things out on its own. > > I do think your overall criticism is valid, though. Cheers, Ben. ^ permalink raw reply [flat|nested] 17+ messages in thread
end of thread, other threads:[~2010-04-11 7:26 UTC | newest] Thread overview: 17+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2010-04-09 19:23 A better way to sequence driver initialization? Bill Gatliff 2010-04-10 3:54 ` Bill Gatliff 2010-04-10 3:59 ` Bill Gatliff 2010-04-10 4:19 ` Bill Gatliff 2010-04-10 5:29 ` Grant Likely 2010-04-10 13:56 ` Bill Gatliff 2010-04-10 8:53 ` Benjamin Herrenschmidt 2010-04-10 13:35 ` Bill Gatliff 2010-04-10 23:39 ` Paul Mundt 2010-04-10 23:47 ` Grant Likely 2010-04-11 1:33 ` Bill Gatliff 2010-04-11 1:47 ` Paul Mundt 2010-04-11 3:30 ` Bill Gatliff 2010-04-11 1:31 ` Bill Gatliff 2010-04-11 7:26 ` Benjamin Herrenschmidt 2010-04-11 7:18 ` Benjamin Herrenschmidt 2010-04-11 7:15 ` Benjamin Herrenschmidt
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).