diff options
-rw-r--r-- | arch/powerpc/mm/hugetlbpage.c | 3 | ||||
-rw-r--r-- | include/asm-generic/vmlinux.lds.h | 35 | ||||
-rw-r--r-- | include/linux/moduleparam.h | 51 | ||||
-rw-r--r-- | init/main.c | 65 | ||||
-rw-r--r-- | kernel/module.c | 3 | ||||
-rw-r--r-- | kernel/params.c | 16 |
6 files changed, 132 insertions, 41 deletions
diff --git a/arch/powerpc/mm/hugetlbpage.c b/arch/powerpc/mm/hugetlbpage.c index 57c7465e656e..a3e628727697 100644 --- a/arch/powerpc/mm/hugetlbpage.c +++ b/arch/powerpc/mm/hugetlbpage.c | |||
@@ -310,7 +310,8 @@ void __init reserve_hugetlb_gpages(void) | |||
310 | int i; | 310 | int i; |
311 | 311 | ||
312 | strlcpy(cmdline, boot_command_line, COMMAND_LINE_SIZE); | 312 | strlcpy(cmdline, boot_command_line, COMMAND_LINE_SIZE); |
313 | parse_args("hugetlb gpages", cmdline, NULL, 0, &do_gpage_early_setup); | 313 | parse_args("hugetlb gpages", cmdline, NULL, 0, 0, 0, |
314 | &do_gpage_early_setup); | ||
314 | 315 | ||
315 | /* | 316 | /* |
316 | * Walk gpage list in reverse, allocating larger page sizes first. | 317 | * Walk gpage list in reverse, allocating larger page sizes first. |
diff --git a/include/asm-generic/vmlinux.lds.h b/include/asm-generic/vmlinux.lds.h index 798603e8ec38..8aeadf6b553a 100644 --- a/include/asm-generic/vmlinux.lds.h +++ b/include/asm-generic/vmlinux.lds.h | |||
@@ -616,30 +616,23 @@ | |||
616 | *(.init.setup) \ | 616 | *(.init.setup) \ |
617 | VMLINUX_SYMBOL(__setup_end) = .; | 617 | VMLINUX_SYMBOL(__setup_end) = .; |
618 | 618 | ||
619 | #define INITCALLS \ | 619 | #define INIT_CALLS_LEVEL(level) \ |
620 | *(.initcallearly.init) \ | 620 | VMLINUX_SYMBOL(__initcall##level##_start) = .; \ |
621 | VMLINUX_SYMBOL(__early_initcall_end) = .; \ | 621 | *(.initcall##level##.init) \ |
622 | *(.initcall0.init) \ | 622 | *(.initcall##level##s.init) \ |
623 | *(.initcall0s.init) \ | ||
624 | *(.initcall1.init) \ | ||
625 | *(.initcall1s.init) \ | ||
626 | *(.initcall2.init) \ | ||
627 | *(.initcall2s.init) \ | ||
628 | *(.initcall3.init) \ | ||
629 | *(.initcall3s.init) \ | ||
630 | *(.initcall4.init) \ | ||
631 | *(.initcall4s.init) \ | ||
632 | *(.initcall5.init) \ | ||
633 | *(.initcall5s.init) \ | ||
634 | *(.initcallrootfs.init) \ | ||
635 | *(.initcall6.init) \ | ||
636 | *(.initcall6s.init) \ | ||
637 | *(.initcall7.init) \ | ||
638 | *(.initcall7s.init) | ||
639 | 623 | ||
640 | #define INIT_CALLS \ | 624 | #define INIT_CALLS \ |
641 | VMLINUX_SYMBOL(__initcall_start) = .; \ | 625 | VMLINUX_SYMBOL(__initcall_start) = .; \ |
642 | INITCALLS \ | 626 | *(.initcallearly.init) \ |
627 | INIT_CALLS_LEVEL(0) \ | ||
628 | INIT_CALLS_LEVEL(1) \ | ||
629 | INIT_CALLS_LEVEL(2) \ | ||
630 | INIT_CALLS_LEVEL(3) \ | ||
631 | INIT_CALLS_LEVEL(4) \ | ||
632 | INIT_CALLS_LEVEL(5) \ | ||
633 | INIT_CALLS_LEVEL(rootfs) \ | ||
634 | INIT_CALLS_LEVEL(6) \ | ||
635 | INIT_CALLS_LEVEL(7) \ | ||
643 | VMLINUX_SYMBOL(__initcall_end) = .; | 636 | VMLINUX_SYMBOL(__initcall_end) = .; |
644 | 637 | ||
645 | #define CON_INITCALL \ | 638 | #define CON_INITCALL \ |
diff --git a/include/linux/moduleparam.h b/include/linux/moduleparam.h index 4daa895648d9..ea36486378d8 100644 --- a/include/linux/moduleparam.h +++ b/include/linux/moduleparam.h | |||
@@ -51,7 +51,7 @@ struct kernel_param { | |||
51 | const char *name; | 51 | const char *name; |
52 | const struct kernel_param_ops *ops; | 52 | const struct kernel_param_ops *ops; |
53 | u16 perm; | 53 | u16 perm; |
54 | u16 flags; | 54 | s16 level; |
55 | union { | 55 | union { |
56 | void *arg; | 56 | void *arg; |
57 | const struct kparam_string *str; | 57 | const struct kparam_string *str; |
@@ -128,7 +128,40 @@ struct kparam_array | |||
128 | * The ops can have NULL set or get functions. | 128 | * The ops can have NULL set or get functions. |
129 | */ | 129 | */ |
130 | #define module_param_cb(name, ops, arg, perm) \ | 130 | #define module_param_cb(name, ops, arg, perm) \ |
131 | __module_param_call(MODULE_PARAM_PREFIX, name, ops, arg, perm) | 131 | __module_param_call(MODULE_PARAM_PREFIX, name, ops, arg, perm, 0) |
132 | |||
133 | /** | ||
134 | * <level>_param_cb - general callback for a module/cmdline parameter | ||
135 | * to be evaluated before certain initcall level | ||
136 | * @name: a valid C identifier which is the parameter name. | ||
137 | * @ops: the set & get operations for this parameter. | ||
138 | * @perm: visibility in sysfs. | ||
139 | * | ||
140 | * The ops can have NULL set or get functions. | ||
141 | */ | ||
142 | #define __level_param_cb(name, ops, arg, perm, level) \ | ||
143 | __module_param_call(MODULE_PARAM_PREFIX, name, ops, arg, perm, level) | ||
144 | |||
145 | #define core_param_cb(name, ops, arg, perm) \ | ||
146 | __level_param_cb(name, ops, arg, perm, 1) | ||
147 | |||
148 | #define postcore_param_cb(name, ops, arg, perm) \ | ||
149 | __level_param_cb(name, ops, arg, perm, 2) | ||
150 | |||
151 | #define arch_param_cb(name, ops, arg, perm) \ | ||
152 | __level_param_cb(name, ops, arg, perm, 3) | ||
153 | |||
154 | #define subsys_param_cb(name, ops, arg, perm) \ | ||
155 | __level_param_cb(name, ops, arg, perm, 4) | ||
156 | |||
157 | #define fs_param_cb(name, ops, arg, perm) \ | ||
158 | __level_param_cb(name, ops, arg, perm, 5) | ||
159 | |||
160 | #define device_param_cb(name, ops, arg, perm) \ | ||
161 | __level_param_cb(name, ops, arg, perm, 6) | ||
162 | |||
163 | #define late_param_cb(name, ops, arg, perm) \ | ||
164 | __level_param_cb(name, ops, arg, perm, 7) | ||
132 | 165 | ||
133 | /* On alpha, ia64 and ppc64 relocations to global data cannot go into | 166 | /* On alpha, ia64 and ppc64 relocations to global data cannot go into |
134 | read-only sections (which is part of respective UNIX ABI on these | 167 | read-only sections (which is part of respective UNIX ABI on these |
@@ -142,7 +175,7 @@ struct kparam_array | |||
142 | 175 | ||
143 | /* This is the fundamental function for registering boot/module | 176 | /* This is the fundamental function for registering boot/module |
144 | parameters. */ | 177 | parameters. */ |
145 | #define __module_param_call(prefix, name, ops, arg, perm) \ | 178 | #define __module_param_call(prefix, name, ops, arg, perm, level) \ |
146 | /* Default value instead of permissions? */ \ | 179 | /* Default value instead of permissions? */ \ |
147 | static int __param_perm_check_##name __attribute__((unused)) = \ | 180 | static int __param_perm_check_##name __attribute__((unused)) = \ |
148 | BUILD_BUG_ON_ZERO((perm) < 0 || (perm) > 0777 || ((perm) & 2)) \ | 181 | BUILD_BUG_ON_ZERO((perm) < 0 || (perm) > 0777 || ((perm) & 2)) \ |
@@ -151,7 +184,7 @@ struct kparam_array | |||
151 | static struct kernel_param __moduleparam_const __param_##name \ | 184 | static struct kernel_param __moduleparam_const __param_##name \ |
152 | __used \ | 185 | __used \ |
153 | __attribute__ ((unused,__section__ ("__param"),aligned(sizeof(void *)))) \ | 186 | __attribute__ ((unused,__section__ ("__param"),aligned(sizeof(void *)))) \ |
154 | = { __param_str_##name, ops, perm, 0, { arg } } | 187 | = { __param_str_##name, ops, perm, level, { arg } } |
155 | 188 | ||
156 | /* Obsolete - use module_param_cb() */ | 189 | /* Obsolete - use module_param_cb() */ |
157 | #define module_param_call(name, set, get, arg, perm) \ | 190 | #define module_param_call(name, set, get, arg, perm) \ |
@@ -159,7 +192,7 @@ struct kparam_array | |||
159 | { (void *)set, (void *)get }; \ | 192 | { (void *)set, (void *)get }; \ |
160 | __module_param_call(MODULE_PARAM_PREFIX, \ | 193 | __module_param_call(MODULE_PARAM_PREFIX, \ |
161 | name, &__param_ops_##name, arg, \ | 194 | name, &__param_ops_##name, arg, \ |
162 | (perm) + sizeof(__check_old_set_param(set))*0) | 195 | (perm) + sizeof(__check_old_set_param(set))*0, 0) |
163 | 196 | ||
164 | /* We don't get oldget: it's often a new-style param_get_uint, etc. */ | 197 | /* We don't get oldget: it's often a new-style param_get_uint, etc. */ |
165 | static inline int | 198 | static inline int |
@@ -239,7 +272,7 @@ static inline void __kernel_param_unlock(void) | |||
239 | */ | 272 | */ |
240 | #define core_param(name, var, type, perm) \ | 273 | #define core_param(name, var, type, perm) \ |
241 | param_check_##type(name, &(var)); \ | 274 | param_check_##type(name, &(var)); \ |
242 | __module_param_call("", name, ¶m_ops_##type, &var, perm) | 275 | __module_param_call("", name, ¶m_ops_##type, &var, perm, 0) |
243 | #endif /* !MODULE */ | 276 | #endif /* !MODULE */ |
244 | 277 | ||
245 | /** | 278 | /** |
@@ -257,7 +290,7 @@ static inline void __kernel_param_unlock(void) | |||
257 | = { len, string }; \ | 290 | = { len, string }; \ |
258 | __module_param_call(MODULE_PARAM_PREFIX, name, \ | 291 | __module_param_call(MODULE_PARAM_PREFIX, name, \ |
259 | ¶m_ops_string, \ | 292 | ¶m_ops_string, \ |
260 | .str = &__param_string_##name, perm); \ | 293 | .str = &__param_string_##name, perm, 0); \ |
261 | __MODULE_PARM_TYPE(name, "string") | 294 | __MODULE_PARM_TYPE(name, "string") |
262 | 295 | ||
263 | /** | 296 | /** |
@@ -285,6 +318,8 @@ extern int parse_args(const char *name, | |||
285 | char *args, | 318 | char *args, |
286 | const struct kernel_param *params, | 319 | const struct kernel_param *params, |
287 | unsigned num, | 320 | unsigned num, |
321 | s16 level_min, | ||
322 | s16 level_max, | ||
288 | int (*unknown)(char *param, char *val)); | 323 | int (*unknown)(char *param, char *val)); |
289 | 324 | ||
290 | /* Called by module remove. */ | 325 | /* Called by module remove. */ |
@@ -396,7 +431,7 @@ extern int param_set_bint(const char *val, const struct kernel_param *kp); | |||
396 | __module_param_call(MODULE_PARAM_PREFIX, name, \ | 431 | __module_param_call(MODULE_PARAM_PREFIX, name, \ |
397 | ¶m_array_ops, \ | 432 | ¶m_array_ops, \ |
398 | .arr = &__param_arr_##name, \ | 433 | .arr = &__param_arr_##name, \ |
399 | perm); \ | 434 | perm, 0); \ |
400 | __MODULE_PARM_TYPE(name, "array of " #type) | 435 | __MODULE_PARM_TYPE(name, "array of " #type) |
401 | 436 | ||
402 | extern struct kernel_param_ops param_array_ops; | 437 | extern struct kernel_param_ops param_array_ops; |
diff --git a/init/main.c b/init/main.c index c24805c824b9..439715858ba0 100644 --- a/init/main.c +++ b/init/main.c | |||
@@ -400,7 +400,7 @@ static int __init do_early_param(char *param, char *val) | |||
400 | 400 | ||
401 | void __init parse_early_options(char *cmdline) | 401 | void __init parse_early_options(char *cmdline) |
402 | { | 402 | { |
403 | parse_args("early options", cmdline, NULL, 0, do_early_param); | 403 | parse_args("early options", cmdline, NULL, 0, 0, 0, do_early_param); |
404 | } | 404 | } |
405 | 405 | ||
406 | /* Arch code calls this early on, or if not, just before other parsing. */ | 406 | /* Arch code calls this early on, or if not, just before other parsing. */ |
@@ -503,7 +503,7 @@ asmlinkage void __init start_kernel(void) | |||
503 | parse_early_param(); | 503 | parse_early_param(); |
504 | parse_args("Booting kernel", static_command_line, __start___param, | 504 | parse_args("Booting kernel", static_command_line, __start___param, |
505 | __stop___param - __start___param, | 505 | __stop___param - __start___param, |
506 | &unknown_bootoption); | 506 | 0, 0, &unknown_bootoption); |
507 | 507 | ||
508 | jump_label_init(); | 508 | jump_label_init(); |
509 | 509 | ||
@@ -699,16 +699,69 @@ int __init_or_module do_one_initcall(initcall_t fn) | |||
699 | } | 699 | } |
700 | 700 | ||
701 | 701 | ||
702 | extern initcall_t __initcall_start[], __initcall_end[], __early_initcall_end[]; | 702 | extern initcall_t __initcall_start[]; |
703 | extern initcall_t __initcall0_start[]; | ||
704 | extern initcall_t __initcall1_start[]; | ||
705 | extern initcall_t __initcall2_start[]; | ||
706 | extern initcall_t __initcall3_start[]; | ||
707 | extern initcall_t __initcall4_start[]; | ||
708 | extern initcall_t __initcall5_start[]; | ||
709 | extern initcall_t __initcall6_start[]; | ||
710 | extern initcall_t __initcall7_start[]; | ||
711 | extern initcall_t __initcall_end[]; | ||
712 | |||
713 | static initcall_t *initcall_levels[] __initdata = { | ||
714 | __initcall0_start, | ||
715 | __initcall1_start, | ||
716 | __initcall2_start, | ||
717 | __initcall3_start, | ||
718 | __initcall4_start, | ||
719 | __initcall5_start, | ||
720 | __initcall6_start, | ||
721 | __initcall7_start, | ||
722 | __initcall_end, | ||
723 | }; | ||
724 | |||
725 | static char *initcall_level_names[] __initdata = { | ||
726 | "early parameters", | ||
727 | "core parameters", | ||
728 | "postcore parameters", | ||
729 | "arch parameters", | ||
730 | "subsys parameters", | ||
731 | "fs parameters", | ||
732 | "device parameters", | ||
733 | "late parameters", | ||
734 | }; | ||
735 | |||
736 | static int __init ignore_unknown_bootoption(char *param, char *val) | ||
737 | { | ||
738 | return 0; | ||
739 | } | ||
703 | 740 | ||
704 | static void __init do_initcalls(void) | 741 | static void __init do_initcall_level(int level) |
705 | { | 742 | { |
743 | extern const struct kernel_param __start___param[], __stop___param[]; | ||
706 | initcall_t *fn; | 744 | initcall_t *fn; |
707 | 745 | ||
708 | for (fn = __early_initcall_end; fn < __initcall_end; fn++) | 746 | strcpy(static_command_line, saved_command_line); |
747 | parse_args(initcall_level_names[level], | ||
748 | static_command_line, __start___param, | ||
749 | __stop___param - __start___param, | ||
750 | level, level, | ||
751 | ignore_unknown_bootoption); | ||
752 | |||
753 | for (fn = initcall_levels[level]; fn < initcall_levels[level+1]; fn++) | ||
709 | do_one_initcall(*fn); | 754 | do_one_initcall(*fn); |
710 | } | 755 | } |
711 | 756 | ||
757 | static void __init do_initcalls(void) | ||
758 | { | ||
759 | int level; | ||
760 | |||
761 | for (level = 0; level < ARRAY_SIZE(initcall_levels) - 1; level++) | ||
762 | do_initcall_level(level); | ||
763 | } | ||
764 | |||
712 | /* | 765 | /* |
713 | * Ok, the machine is now initialized. None of the devices | 766 | * Ok, the machine is now initialized. None of the devices |
714 | * have been touched yet, but the CPU subsystem is up and | 767 | * have been touched yet, but the CPU subsystem is up and |
@@ -732,7 +785,7 @@ static void __init do_pre_smp_initcalls(void) | |||
732 | { | 785 | { |
733 | initcall_t *fn; | 786 | initcall_t *fn; |
734 | 787 | ||
735 | for (fn = __initcall_start; fn < __early_initcall_end; fn++) | 788 | for (fn = __initcall_start; fn < __initcall0_start; fn++) |
736 | do_one_initcall(*fn); | 789 | do_one_initcall(*fn); |
737 | } | 790 | } |
738 | 791 | ||
diff --git a/kernel/module.c b/kernel/module.c index 7e31da9750c0..6f6651a54590 100644 --- a/kernel/module.c +++ b/kernel/module.c | |||
@@ -2923,7 +2923,8 @@ static struct module *load_module(void __user *umod, | |||
2923 | mutex_unlock(&module_mutex); | 2923 | mutex_unlock(&module_mutex); |
2924 | 2924 | ||
2925 | /* Module is ready to execute: parsing args may do that. */ | 2925 | /* Module is ready to execute: parsing args may do that. */ |
2926 | err = parse_args(mod->name, mod->args, mod->kp, mod->num_kp, NULL); | 2926 | err = parse_args(mod->name, mod->args, mod->kp, mod->num_kp, |
2927 | -32768, 32767, NULL); | ||
2927 | if (err < 0) | 2928 | if (err < 0) |
2928 | goto unlink; | 2929 | goto unlink; |
2929 | 2930 | ||
diff --git a/kernel/params.c b/kernel/params.c index 508828afb874..f37d82631347 100644 --- a/kernel/params.c +++ b/kernel/params.c | |||
@@ -87,6 +87,8 @@ static int parse_one(char *param, | |||
87 | char *val, | 87 | char *val, |
88 | const struct kernel_param *params, | 88 | const struct kernel_param *params, |
89 | unsigned num_params, | 89 | unsigned num_params, |
90 | s16 min_level, | ||
91 | s16 max_level, | ||
90 | int (*handle_unknown)(char *param, char *val)) | 92 | int (*handle_unknown)(char *param, char *val)) |
91 | { | 93 | { |
92 | unsigned int i; | 94 | unsigned int i; |
@@ -95,6 +97,9 @@ static int parse_one(char *param, | |||
95 | /* Find parameter */ | 97 | /* Find parameter */ |
96 | for (i = 0; i < num_params; i++) { | 98 | for (i = 0; i < num_params; i++) { |
97 | if (parameq(param, params[i].name)) { | 99 | if (parameq(param, params[i].name)) { |
100 | if (params[i].level < min_level | ||
101 | || params[i].level > max_level) | ||
102 | return 0; | ||
98 | /* No one handled NULL, so do it here. */ | 103 | /* No one handled NULL, so do it here. */ |
99 | if (!val && params[i].ops->set != param_set_bool | 104 | if (!val && params[i].ops->set != param_set_bool |
100 | && params[i].ops->set != param_set_bint) | 105 | && params[i].ops->set != param_set_bint) |
@@ -174,6 +179,8 @@ int parse_args(const char *name, | |||
174 | char *args, | 179 | char *args, |
175 | const struct kernel_param *params, | 180 | const struct kernel_param *params, |
176 | unsigned num, | 181 | unsigned num, |
182 | s16 min_level, | ||
183 | s16 max_level, | ||
177 | int (*unknown)(char *param, char *val)) | 184 | int (*unknown)(char *param, char *val)) |
178 | { | 185 | { |
179 | char *param, *val; | 186 | char *param, *val; |
@@ -189,7 +196,8 @@ int parse_args(const char *name, | |||
189 | 196 | ||
190 | args = next_arg(args, ¶m, &val); | 197 | args = next_arg(args, ¶m, &val); |
191 | irq_was_disabled = irqs_disabled(); | 198 | irq_was_disabled = irqs_disabled(); |
192 | ret = parse_one(param, val, params, num, unknown); | 199 | ret = parse_one(param, val, params, num, |
200 | min_level, max_level, unknown); | ||
193 | if (irq_was_disabled && !irqs_disabled()) { | 201 | if (irq_was_disabled && !irqs_disabled()) { |
194 | printk(KERN_WARNING "parse_args(): option '%s' enabled " | 202 | printk(KERN_WARNING "parse_args(): option '%s' enabled " |
195 | "irq's!\n", param); | 203 | "irq's!\n", param); |
@@ -374,7 +382,7 @@ static int param_array(const char *name, | |||
374 | unsigned int min, unsigned int max, | 382 | unsigned int min, unsigned int max, |
375 | void *elem, int elemsize, | 383 | void *elem, int elemsize, |
376 | int (*set)(const char *, const struct kernel_param *kp), | 384 | int (*set)(const char *, const struct kernel_param *kp), |
377 | u16 flags, | 385 | s16 level, |
378 | unsigned int *num) | 386 | unsigned int *num) |
379 | { | 387 | { |
380 | int ret; | 388 | int ret; |
@@ -384,7 +392,7 @@ static int param_array(const char *name, | |||
384 | /* Get the name right for errors. */ | 392 | /* Get the name right for errors. */ |
385 | kp.name = name; | 393 | kp.name = name; |
386 | kp.arg = elem; | 394 | kp.arg = elem; |
387 | kp.flags = flags; | 395 | kp.level = level; |
388 | 396 | ||
389 | *num = 0; | 397 | *num = 0; |
390 | /* We expect a comma-separated list of values. */ | 398 | /* We expect a comma-separated list of values. */ |
@@ -425,7 +433,7 @@ static int param_array_set(const char *val, const struct kernel_param *kp) | |||
425 | unsigned int temp_num; | 433 | unsigned int temp_num; |
426 | 434 | ||
427 | return param_array(kp->name, val, 1, arr->max, arr->elem, | 435 | return param_array(kp->name, val, 1, arr->max, arr->elem, |
428 | arr->elemsize, arr->ops->set, kp->flags, | 436 | arr->elemsize, arr->ops->set, kp->level, |
429 | arr->num ?: &temp_num); | 437 | arr->num ?: &temp_num); |
430 | } | 438 | } |
431 | 439 | ||