summaryrefslogtreecommitdiff
path: root/meta-moblin/packages/linux/linux-moblin-2.6.27/0024-fastboot-create-a-asynchronous-initlevel.patch
diff options
context:
space:
mode:
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.patch133
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 000000000..db518b36e
--- /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