diff options
Diffstat (limited to 'meta-moblin/packages/linux/linux-moblin-2.6.27/0024-fastboot-create-a-asynchronous-initlevel.patch')
-rw-r--r-- | meta-moblin/packages/linux/linux-moblin-2.6.27/0024-fastboot-create-a-asynchronous-initlevel.patch | 133 |
1 files changed, 133 insertions, 0 deletions
diff --git a/meta-moblin/packages/linux/linux-moblin-2.6.27/0024-fastboot-create-a-asynchronous-initlevel.patch b/meta-moblin/packages/linux/linux-moblin-2.6.27/0024-fastboot-create-a-asynchronous-initlevel.patch new file mode 100644 index 0000000000..db518b36eb --- /dev/null +++ b/meta-moblin/packages/linux/linux-moblin-2.6.27/0024-fastboot-create-a-asynchronous-initlevel.patch @@ -0,0 +1,133 @@ +From ac9103dd8e4dc65c110d6cba9a3380c6c617ffa7 Mon Sep 17 00:00:00 2001 +From: Arjan van de Ven <arjan@linux.intel.com> +Date: Fri, 18 Jul 2008 15:16:08 -0700 +Subject: [PATCH] fastboot: create a "asynchronous" initlevel + +This patch creates an asynchronous initlevel (6a) which is at the same +level as the normal device initcalls, but with the difference that they +are run asynchronous from all the other initcalls. The purpose of this +*selective* level is that we can move long waiting inits that are not +boot-critical to this level one at a time. + +To keep things not totally insane, the asynchronous initcalls are async +to the other initcalls, but are still ordered to themselves; think of it +as "bottom-half-not-softirq". This has the benefit that async drivers +still have stable device ordering between them. + +Signed-off-by: Arjan van de Ven <arjan@linux.intel.com> +Signed-off-by: Ingo Molnar <mingo@elte.hu> +--- + include/asm-generic/vmlinux.lds.h | 3 +++ + include/linux/init.h | 6 ++++++ + init/main.c | 35 ++++++++++++++++++++++++++++++++--- + 3 files changed, 41 insertions(+), 3 deletions(-) + +Index: linux-2.6.27/include/asm-generic/vmlinux.lds.h +=================================================================== +--- linux-2.6.27.orig/include/asm-generic/vmlinux.lds.h 2008-10-14 16:55:43.000000000 +0200 ++++ linux-2.6.27/include/asm-generic/vmlinux.lds.h 2008-10-14 17:00:59.000000000 +0200 +@@ -376,6 +376,9 @@ + *(.initcall5.init) \ + *(.initcall5s.init) \ + *(.initcallrootfs.init) \ ++ __async_initcall_start = .; \ ++ *(.initcall6a.init) \ ++ __async_initcall_end = .; \ + *(.initcall6.init) \ + *(.initcall6s.init) \ + *(.initcall7.init) \ +Index: linux-2.6.27/include/linux/init.h +=================================================================== +--- linux-2.6.27.orig/include/linux/init.h 2008-10-14 16:55:45.000000000 +0200 ++++ linux-2.6.27/include/linux/init.h 2008-10-14 17:00:59.000000000 +0200 +@@ -197,11 +197,13 @@ extern void (*late_time_init)(void); + #define fs_initcall_sync(fn) __define_initcall("5s",fn,5s) + #define rootfs_initcall(fn) __define_initcall("rootfs",fn,rootfs) + #define device_initcall(fn) __define_initcall("6",fn,6) ++#define device_initcall_async(fn) __define_initcall("6a", fn, 6a) + #define device_initcall_sync(fn) __define_initcall("6s",fn,6s) + #define late_initcall(fn) __define_initcall("7",fn,7) + #define late_initcall_sync(fn) __define_initcall("7s",fn,7s) + + #define __initcall(fn) device_initcall(fn) ++#define __initcall_async(fn) device_initcall_async(fn) + + #define __exitcall(fn) \ + static exitcall_t __exitcall_##fn __exit_call = fn +@@ -257,6 +259,7 @@ void __init parse_early_param(void); + * be one per module. + */ + #define module_init(x) __initcall(x); ++#define module_init_async(x) __initcall_async(x); + + /** + * module_exit() - driver exit entry point +@@ -279,10 +282,13 @@ void __init parse_early_param(void); + #define subsys_initcall(fn) module_init(fn) + #define fs_initcall(fn) module_init(fn) + #define device_initcall(fn) module_init(fn) ++#define device_initcall_async(fn) module_init(fn) + #define late_initcall(fn) module_init(fn) + + #define security_initcall(fn) module_init(fn) + ++#define module_init_async(fn) module_init(fn) ++ + /* Each module must use one module_init(). */ + #define module_init(initfn) \ + static inline initcall_t __inittest(void) \ +Index: linux-2.6.27/init/main.c +=================================================================== +--- linux-2.6.27.orig/init/main.c 2008-10-14 16:55:47.000000000 +0200 ++++ linux-2.6.27/init/main.c 2008-10-14 17:00:59.000000000 +0200 +@@ -745,18 +745,47 @@ int do_one_initcall(initcall_t fn) + + + extern initcall_t __initcall_start[], __initcall_end[], __early_initcall_end[]; ++extern initcall_t __async_initcall_start[], __async_initcall_end[]; + +-static void __init do_initcalls(void) ++static void __init do_async_initcalls(struct work_struct *dummy) + { + initcall_t *call; + +- for (call = __early_initcall_end; call < __initcall_end; call++) ++ for (call = __async_initcall_start; call < __async_initcall_end; call++) + do_one_initcall(*call); ++} ++ ++static struct workqueue_struct *async_init_wq; ++ ++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 */ ++ ++ async_init_wq = create_singlethread_workqueue("kasyncinit"); ++ ++ for (call = __early_initcall_end; call < __initcall_end; call++) { ++ if (phase == 0 && call >= __async_initcall_start) { ++ phase = 1; ++ queue_work(async_init_wq, &async_work); ++ } ++ if (phase == 1 && call >= __async_initcall_end) ++ phase = 2; ++ if (phase != 1) ++ do_one_initcall(*call); ++ } + +- /* Make sure there is no pending stuff from the initcall sequence */ ++ /* ++ * Make sure there is no pending stuff from the initcall sequence, ++ * including the async initcalls ++ */ + flush_scheduled_work(); ++ flush_workqueue(async_init_wq); ++ destroy_workqueue(async_init_wq); + } + ++ + /* + * Ok, the machine is now initialized. None of the devices + * have been touched yet, but the CPU subsystem is up and |