summaryrefslogtreecommitdiff
path: root/init
diff options
context:
space:
mode:
authorArjan van de Ven <arjan@linux.intel.com>2008-07-20 09:00:41 -0700
committerIngo Molnar <mingo@elte.hu>2008-07-20 18:21:20 +0200
commit660625fb93f2fc0e633da9cb71d13d895b385f64 (patch)
tree011e186d52c9e950ead06ed61f5e973707368437 /init
parent3e6558b693dd1e69e3177bc248977f067a769f14 (diff)
fastboot: sync the async execution before late_initcall and move level 6s (sync) first
Rene Herman points out several cases where it's basically needed to have all level 6/6a/6s calls done before the level 7 (late_initcall) code runs. This patch adds a sync point in the transition from the 6's to the 7's. Second, this patch makes sure that level 6s (sync) happens before the async code starts, and puts a user in driver/pci in this category that needs to happen before device init. Signed-off-by: Arjan van de Ven <arjan@linux.intel.com> Signed-off-by: Ingo Molnar <mingo@elte.hu>
Diffstat (limited to 'init')
-rw-r--r--init/main.c14
1 files changed, 13 insertions, 1 deletions
diff --git a/init/main.c b/init/main.c
index 9e2aee8ef7bf..6be17562e2b6 100644
--- a/init/main.c
+++ b/init/main.c
@@ -739,6 +739,7 @@ static void __init do_one_initcall(initcall_t fn)
extern initcall_t __initcall_start[], __initcall_end[];
extern initcall_t __async_initcall_start[], __async_initcall_end[];
+extern initcall_t __device_initcall_end[];
static void __init do_async_initcalls(struct work_struct *dummy)
{
@@ -762,7 +763,13 @@ static void __init do_initcalls(void)
{
initcall_t *call;
static DECLARE_WORK(async_work, do_async_initcalls);
- int phase = 0; /* 0 = levels 0 - 6, 1 = level 6a, 2 = after level 6a */
+ /*
+ * 0 = levels 0 - 6,
+ * 1 = level 6a,
+ * 2 = after level 6a,
+ * 3 = after level 6
+ */
+ int phase = 0;
async_init_wq = create_singlethread_workqueue("kasyncinit");
@@ -773,6 +780,11 @@ static void __init do_initcalls(void)
}
if (phase == 1 && call >= __async_initcall_end)
phase = 2;
+ if (phase == 2 && call >= __device_initcall_end) {
+ phase = 3;
+ /* make sure all async work is done before level 7 */
+ flush_workqueue(async_init_wq);
+ }
if (phase != 1)
do_one_initcall(*call);
}