From: Grant Likely <grant.likely@secretlab.ca>
To: Haojian Zhuang <haojian.zhuang@linaro.org>
Cc: Andrew Morton <akpm@linux-foundation.org>,
Greg Kroah-Hartman <gregkh@linuxfoundation.org>,
viro@zeniv.linux.org.uk, rusty@rustcorp.com.au,
hpa@linux.intel.com, jim.cromie@gmail.com,
linux-kernel@vger.kernel.org,
Russell King - ARM Linux <linux@arm.linux.org.uk>,
Linus Walleij <linus.walleij@linaro.org>,
arnd@arndb.de, broonie@opensource.wolfsonmicro.com,
Patch Tracking <patches@linaro.org>
Subject: Re: [PATCH] driver core: add wait event for deferred probe
Date: Thu, 14 Feb 2013 17:38:05 +0000 [thread overview]
Message-ID: <20130214173805.61AA73E12FB@localhost> (raw)
In-Reply-To: <CAD6h2NT73-af1Hgx0hCBkg8z1hQukK0XPESvrEcrUFv_VKGWjA@mail.gmail.com>
On Thu, 14 Feb 2013 23:52:14 +0800, Haojian Zhuang <haojian.zhuang@linaro.org> wrote:
> On 14 February 2013 05:36, Grant Likely <grant.likely@secretlab.ca> wrote:
> > On Tue, 12 Feb 2013 10:52:10 +0800, Haojian Zhuang <haojian.zhuang@linaro.org> wrote:
> >> On 12 February 2013 07:10, Andrew Morton <akpm@linux-foundation.org> wrote:
> >> > On Sun, 10 Feb 2013 00:57:57 +0800
> >> > Haojian Zhuang <haojian.zhuang@linaro.org> wrote:
> >> >
> >> >> do_initcalls() could call all driver initialization code in kernel_init
> >> >> thread. It means that probe() function will be also called from that
> >> >> time. After this, kernel could access console & release __init section
> >> >> in the same thread.
> >> >>
> >> >> But if device probe fails and moves into deferred probe list, a new
> >> >> thread is created to reinvoke probe. If the device is serial console,
> >> >> kernel has to open console failure & release __init section before
> >> >> reinvoking failure. Because there's no synchronization mechanism.
> >> >> Now add wait event to synchronize after do_initcalls().
> >> >
> >> > It sounds like this:
> >> >
> >> > static int __ref kernel_init(void *unused)
> >> > {
> >> > kernel_init_freeable();
> >> > /* need to finish all async __init code before freeing the memory */
> >> > async_synchronize_full();
> >> >
> >> > is designed to prevent the problem you describe?
> >> >
> >> It can't prevent the problem that I described. Because deferred_probe()
> >> is introduced recently.
> >>
> >> All synchronization should be finished just after do_initcalls(). Since
> >> load_default_modules() is also called in the end of kernel_init_freeable(),
> >> I'm not sure that whether I could remove async_synchronize_full()
> >> here. So I didn't touch it.
> >>
> >> >> --- a/init/main.c
> >> >> +++ b/init/main.c
> >> >> @@ -786,6 +786,7 @@ static void __init do_basic_setup(void)
> >> >> do_ctors();
> >> >> usermodehelper_enable();
> >> >> do_initcalls();
> >> >> + wait_for_device_probe();
> >> >> }
> >> >
> >> > Needs a nice comment here explaining what's going on.
> >>
> >> No problem. I'll add comment here.
> >
> > Actually, this approach will create new problems. There is no guarantee
> > that a given device will be able to initialize before exiting
> > do_basic_setup(). If, for instance, a device depends on a resource
> > provided by a module, then it will just keep deferring. In that case
> > you've got a hung kernel.
> >
> > I think what you really want is the following:
> >
> > static int deferred_probe_initcall(void)
> > {
> > deferred_wq = create_singlethread_workqueue("deferwq");
> > if (WARN_ON(!deferred_wq))
> > return -ENOMEM;
> >
> > driver_deferred_probe_enable = true;
> > + deferred_probe_work_func(NULL);
> > - driver_deferred_probe_trigger();
>
> If you can change it into code in below, it could work. Otherwise, it
> always fails.
> driver_deferred_probe_enable = true;
> driver_deferred_probe_trigger();
> + deferred_probe_work_func(NULL);
> return 0;
>
> Because deferred_probe_work_func() depends on that deferred_probe is added
> into deferred_probe_active_list. If driver_deferred_probe_trigger() isn't called
> first, the deferred uart probe can't be added into active list. So even you call
> work_func at here, it doesn't help.
>
> Would you send it again? If so, you can add tested-by with my signature.
Hmmm, that works, but it isn't very elegant. With that solution both the
workqueue and the initcall are processing the deferred devices at the
same time. It quite possibly could result in missed devices when walking
the deferred list. Consider the scenario:
B depends on A, C and D depend on B
1) Inital conditions pending:A-B-C-D active:empty WQ:idle IC:idle
2) Trigger pending:empty active:A-B-C-D
3) WQ: pop device pending:empty active:B-C-D WQ:A IC:idle
4) IC: pop device pending:empty active:C-D WQ:A IC:B
5) WQ: A probed & pop pending:empty active:D WQ:C IC:B
6) IC: B defers & pop pending:B active:empty WQ:C IC:D
/* B defers because A wasn't ready, but when A did complete B wasn't
* onthe pending list - this is bad */
7) WQ: C defers pending:B-C active:empty WQ:idle IC:D
8) IC: D defers pending:B-C-D active:empty WQ:idle IC:idle
When A successfully probes, everthing in the pending list gets appended
to the active one, but if there are multiple threads poping devices off
the list, then there can be devices that /should/ be moved to the active
list but don't because they've been popped off by a separate thread.
With the current code there really should only be one processor of the
deferred list at a time. Try this instead:
driver_deferred_probe_enable = true;
driver_deferred_probe_trigger();
+ flush_workqueue(deferred_wq);
return 0;
I had tried to keep the first pass of the list within the initcall
context, but it created a lot of special cases in the code that I wasn't
happy with. This is a lot simpler and has exactly the same visible
behaviour.
Let me know if that works for you and I'll send a proper patch to Linus
with your Tested-by. He may yell at me for sending something so
incredibly late in the v3.8 stablization, but this really is a bug fix.
If he won't take it then I'll ask Greg to put it into v3.8.1.
g.
prev parent reply other threads:[~2013-02-14 17:38 UTC|newest]
Thread overview: 18+ messages / expand[flat|nested] mbox.gz Atom feed top
2013-02-09 16:57 [PATCH] driver core: add wait event for deferred probe Haojian Zhuang
2013-02-11 23:10 ` Andrew Morton
2013-02-12 2:52 ` Haojian Zhuang
2013-02-13 21:36 ` Grant Likely
2013-02-14 3:27 ` anish singh
2013-02-14 9:56 ` Arnd Bergmann
2013-02-14 10:04 ` Russell King - ARM Linux
2013-02-14 11:08 ` Arnd Bergmann
2013-02-14 16:33 ` Grant Likely
2013-02-14 17:42 ` anish kumar
2013-02-14 15:52 ` Haojian Zhuang
2013-02-14 15:57 ` Arnd Bergmann
2013-02-14 16:04 ` Haojian Zhuang
2013-02-14 16:50 ` Arnd Bergmann
2013-02-14 16:58 ` Haojian Zhuang
2013-02-14 17:54 ` Grant Likely
2013-02-14 17:42 ` Grant Likely
2013-02-14 17:38 ` Grant Likely [this message]
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=20130214173805.61AA73E12FB@localhost \
--to=grant.likely@secretlab.ca \
--cc=akpm@linux-foundation.org \
--cc=arnd@arndb.de \
--cc=broonie@opensource.wolfsonmicro.com \
--cc=gregkh@linuxfoundation.org \
--cc=haojian.zhuang@linaro.org \
--cc=hpa@linux.intel.com \
--cc=jim.cromie@gmail.com \
--cc=linus.walleij@linaro.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux@arm.linux.org.uk \
--cc=patches@linaro.org \
--cc=rusty@rustcorp.com.au \
--cc=viro@zeniv.linux.org.uk \
/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