1 From 660625fb93f2fc0e633da9cb71d13d895b385f64 Mon Sep 17 00:00:00 2001
2 From: Arjan van de Ven <arjan@linux.intel.com>
3 Date: Sun, 20 Jul 2008 09:00:41 -0700
4 Subject: [PATCH] fastboot: sync the async execution before late_initcall and move level 6s (sync) first
6 Rene Herman points out several cases where it's basically needed to have
7 all level 6/6a/6s calls done before the level 7 (late_initcall) code
8 runs. This patch adds a sync point in the transition from the 6's to the
11 Second, this patch makes sure that level 6s (sync) happens before the
12 async code starts, and puts a user in driver/pci in this category that
13 needs to happen before device init.
15 Signed-off-by: Arjan van de Ven <arjan@linux.intel.com>
16 Signed-off-by: Ingo Molnar <mingo@elte.hu>
18 drivers/pci/pci.c | 2 +-
19 include/asm-generic/vmlinux.lds.h | 3 ++-
20 init/main.c | 14 +++++++++++++-
21 3 files changed, 16 insertions(+), 3 deletions(-)
23 diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c
24 index 44a46c9..d75295d 100644
25 --- a/drivers/pci/pci.c
26 +++ b/drivers/pci/pci.c
27 @@ -1889,7 +1889,7 @@ static int __devinit pci_setup(char *str)
29 early_param("pci", pci_setup);
31 -device_initcall(pci_init);
32 +device_initcall_sync(pci_init);
34 EXPORT_SYMBOL(pci_reenable_device);
35 EXPORT_SYMBOL(pci_enable_device_io);
36 diff --git a/include/asm-generic/vmlinux.lds.h b/include/asm-generic/vmlinux.lds.h
37 index 39c1afc..020c641 100644
38 --- a/include/asm-generic/vmlinux.lds.h
39 +++ b/include/asm-generic/vmlinux.lds.h
43 *(.initcallrootfs.init) \
44 + *(.initcall6s.init) \
45 __async_initcall_start = .; \
47 __async_initcall_end = .; \
49 - *(.initcall6s.init) \
50 + __device_initcall_end = .; \
54 diff --git a/init/main.c b/init/main.c
55 index 9e2aee8..6be1756 100644
58 @@ -739,6 +739,7 @@ static void __init do_one_initcall(initcall_t fn)
60 extern initcall_t __initcall_start[], __initcall_end[];
61 extern initcall_t __async_initcall_start[], __async_initcall_end[];
62 +extern initcall_t __device_initcall_end[];
64 static void __init do_async_initcalls(struct work_struct *dummy)
66 @@ -762,7 +763,13 @@ static void __init do_initcalls(void)
69 static DECLARE_WORK(async_work, do_async_initcalls);
70 - int phase = 0; /* 0 = levels 0 - 6, 1 = level 6a, 2 = after level 6a */
74 + * 2 = after level 6a,
79 async_init_wq = create_singlethread_workqueue("kasyncinit");
81 @@ -773,6 +780,11 @@ static void __init do_initcalls(void)
83 if (phase == 1 && call >= __async_initcall_end)
85 + if (phase == 2 && call >= __device_initcall_end) {
87 + /* make sure all async work is done before level 7 */
88 + flush_workqueue(async_init_wq);
91 do_one_initcall(*call);