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 57c7465e656..a3e62872769 100644 --- a/arch/powerpc/mm/hugetlbpage.c +++ b/arch/powerpc/mm/hugetlbpage.c @@ -310,7 +310,8 @@ void __init reserve_hugetlb_gpages(void)  	int i;  	strlcpy(cmdline, boot_command_line, COMMAND_LINE_SIZE); -	parse_args("hugetlb gpages", cmdline, NULL, 0, &do_gpage_early_setup); +	parse_args("hugetlb gpages", cmdline, NULL, 0, 0, 0, +			&do_gpage_early_setup);  	/*  	 * 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 798603e8ec3..8aeadf6b553 100644 --- a/include/asm-generic/vmlinux.lds.h +++ b/include/asm-generic/vmlinux.lds.h @@ -616,30 +616,23 @@  		*(.init.setup)						\  		VMLINUX_SYMBOL(__setup_end) = .; -#define INITCALLS							\ -	*(.initcallearly.init)						\ -	VMLINUX_SYMBOL(__early_initcall_end) = .;			\ -  	*(.initcall0.init)						\ -  	*(.initcall0s.init)						\ -  	*(.initcall1.init)						\ -  	*(.initcall1s.init)						\ -  	*(.initcall2.init)						\ -  	*(.initcall2s.init)						\ -  	*(.initcall3.init)						\ -  	*(.initcall3s.init)						\ -  	*(.initcall4.init)						\ -  	*(.initcall4s.init)						\ -  	*(.initcall5.init)						\ -  	*(.initcall5s.init)						\ -	*(.initcallrootfs.init)						\ -  	*(.initcall6.init)						\ -  	*(.initcall6s.init)						\ -  	*(.initcall7.init)						\ -  	*(.initcall7s.init) +#define INIT_CALLS_LEVEL(level)						\ +		VMLINUX_SYMBOL(__initcall##level##_start) = .;		\ +		*(.initcall##level##.init)				\ +		*(.initcall##level##s.init)				\  #define INIT_CALLS							\  		VMLINUX_SYMBOL(__initcall_start) = .;			\ -		INITCALLS						\ +		*(.initcallearly.init)					\ +		INIT_CALLS_LEVEL(0)					\ +		INIT_CALLS_LEVEL(1)					\ +		INIT_CALLS_LEVEL(2)					\ +		INIT_CALLS_LEVEL(3)					\ +		INIT_CALLS_LEVEL(4)					\ +		INIT_CALLS_LEVEL(5)					\ +		INIT_CALLS_LEVEL(rootfs)				\ +		INIT_CALLS_LEVEL(6)					\ +		INIT_CALLS_LEVEL(7)					\  		VMLINUX_SYMBOL(__initcall_end) = .;  #define CON_INITCALL							\ diff --git a/include/linux/moduleparam.h b/include/linux/moduleparam.h index 4daa895648d..ea36486378d 100644 --- a/include/linux/moduleparam.h +++ b/include/linux/moduleparam.h @@ -51,7 +51,7 @@ struct kernel_param {  	const char *name;  	const struct kernel_param_ops *ops;  	u16 perm; -	u16 flags; +	s16 level;  	union {  		void *arg;  		const struct kparam_string *str; @@ -128,7 +128,40 @@ struct kparam_array   * The ops can have NULL set or get functions.   */  #define module_param_cb(name, ops, arg, perm)				      \ -	__module_param_call(MODULE_PARAM_PREFIX, name, ops, arg, perm) +	__module_param_call(MODULE_PARAM_PREFIX, name, ops, arg, perm, 0) + +/** + * <level>_param_cb - general callback for a module/cmdline parameter + *                    to be evaluated before certain initcall level + * @name: a valid C identifier which is the parameter name. + * @ops: the set & get operations for this parameter. + * @perm: visibility in sysfs. + * + * The ops can have NULL set or get functions. + */ +#define __level_param_cb(name, ops, arg, perm, level)			\ +	__module_param_call(MODULE_PARAM_PREFIX, name, ops, arg, perm, level) + +#define core_param_cb(name, ops, arg, perm)		\ +	__level_param_cb(name, ops, arg, perm, 1) + +#define postcore_param_cb(name, ops, arg, perm)		\ +	__level_param_cb(name, ops, arg, perm, 2) + +#define arch_param_cb(name, ops, arg, perm)		\ +	__level_param_cb(name, ops, arg, perm, 3) + +#define subsys_param_cb(name, ops, arg, perm)		\ +	__level_param_cb(name, ops, arg, perm, 4) + +#define fs_param_cb(name, ops, arg, perm)		\ +	__level_param_cb(name, ops, arg, perm, 5) + +#define device_param_cb(name, ops, arg, perm)		\ +	__level_param_cb(name, ops, arg, perm, 6) + +#define late_param_cb(name, ops, arg, perm)		\ +	__level_param_cb(name, ops, arg, perm, 7)  /* On alpha, ia64 and ppc64 relocations to global data cannot go into     read-only sections (which is part of respective UNIX ABI on these @@ -142,7 +175,7 @@ struct kparam_array  /* This is the fundamental function for registering boot/module     parameters. */ -#define __module_param_call(prefix, name, ops, arg, perm)		\ +#define __module_param_call(prefix, name, ops, arg, perm, level)	\  	/* Default value instead of permissions? */			\  	static int __param_perm_check_##name __attribute__((unused)) =	\  	BUILD_BUG_ON_ZERO((perm) < 0 || (perm) > 0777 || ((perm) & 2))	\ @@ -151,7 +184,7 @@ struct kparam_array  	static struct kernel_param __moduleparam_const __param_##name	\  	__used								\      __attribute__ ((unused,__section__ ("__param"),aligned(sizeof(void *)))) \ -	= { __param_str_##name, ops, perm, 0, { arg } } +	= { __param_str_##name, ops, perm, level, { arg } }  /* Obsolete - use module_param_cb() */  #define module_param_call(name, set, get, arg, perm)			\ @@ -159,7 +192,7 @@ struct kparam_array  		 { (void *)set, (void *)get };				\  	__module_param_call(MODULE_PARAM_PREFIX,			\  			    name, &__param_ops_##name, arg,		\ -			    (perm) + sizeof(__check_old_set_param(set))*0) +			    (perm) + sizeof(__check_old_set_param(set))*0, 0)  /* We don't get oldget: it's often a new-style param_get_uint, etc. */  static inline int @@ -239,7 +272,7 @@ static inline void __kernel_param_unlock(void)   */  #define core_param(name, var, type, perm)				\  	param_check_##type(name, &(var));				\ -	__module_param_call("", name, ¶m_ops_##type, &var, perm) +	__module_param_call("", name, ¶m_ops_##type, &var, perm, 0)  #endif /* !MODULE */  /** @@ -257,7 +290,7 @@ static inline void __kernel_param_unlock(void)  		= { len, string };					\  	__module_param_call(MODULE_PARAM_PREFIX, name,			\  			    ¶m_ops_string,				\ -			    .str = &__param_string_##name, perm);	\ +			    .str = &__param_string_##name, perm, 0);	\  	__MODULE_PARM_TYPE(name, "string")  /** @@ -285,6 +318,8 @@ extern int parse_args(const char *name,  		      char *args,  		      const struct kernel_param *params,  		      unsigned num, +		      s16 level_min, +		      s16 level_max,  		      int (*unknown)(char *param, char *val));  /* Called by module remove. */ @@ -396,7 +431,7 @@ extern int param_set_bint(const char *val, const struct kernel_param *kp);  	__module_param_call(MODULE_PARAM_PREFIX, name,			\  			    ¶m_array_ops,				\  			    .arr = &__param_arr_##name,			\ -			    perm);					\ +			    perm, 0);					\  	__MODULE_PARM_TYPE(name, "array of " #type)  extern struct kernel_param_ops param_array_ops; diff --git a/init/main.c b/init/main.c index c24805c824b..439715858ba 100644 --- a/init/main.c +++ b/init/main.c @@ -400,7 +400,7 @@ static int __init do_early_param(char *param, char *val)  void __init parse_early_options(char *cmdline)  { -	parse_args("early options", cmdline, NULL, 0, do_early_param); +	parse_args("early options", cmdline, NULL, 0, 0, 0, do_early_param);  }  /* Arch code calls this early on, or if not, just before other parsing. */ @@ -503,7 +503,7 @@ asmlinkage void __init start_kernel(void)  	parse_early_param();  	parse_args("Booting kernel", static_command_line, __start___param,  		   __stop___param - __start___param, -		   &unknown_bootoption); +		   0, 0, &unknown_bootoption);  	jump_label_init(); @@ -699,16 +699,69 @@ int __init_or_module do_one_initcall(initcall_t fn)  } -extern initcall_t __initcall_start[], __initcall_end[], __early_initcall_end[]; +extern initcall_t __initcall_start[]; +extern initcall_t __initcall0_start[]; +extern initcall_t __initcall1_start[]; +extern initcall_t __initcall2_start[]; +extern initcall_t __initcall3_start[]; +extern initcall_t __initcall4_start[]; +extern initcall_t __initcall5_start[]; +extern initcall_t __initcall6_start[]; +extern initcall_t __initcall7_start[]; +extern initcall_t __initcall_end[]; -static void __init do_initcalls(void) +static initcall_t *initcall_levels[] __initdata = { +	__initcall0_start, +	__initcall1_start, +	__initcall2_start, +	__initcall3_start, +	__initcall4_start, +	__initcall5_start, +	__initcall6_start, +	__initcall7_start, +	__initcall_end, +}; + +static char *initcall_level_names[] __initdata = { +	"early parameters", +	"core parameters", +	"postcore parameters", +	"arch parameters", +	"subsys parameters", +	"fs parameters", +	"device parameters", +	"late parameters", +}; + +static int __init ignore_unknown_bootoption(char *param, char *val) +{ +	return 0; +} + +static void __init do_initcall_level(int level)  { +	extern const struct kernel_param __start___param[], __stop___param[];  	initcall_t *fn; -	for (fn = __early_initcall_end; fn < __initcall_end; fn++) +	strcpy(static_command_line, saved_command_line); +	parse_args(initcall_level_names[level], +		   static_command_line, __start___param, +		   __stop___param - __start___param, +		   level, level, +		   ignore_unknown_bootoption); + +	for (fn = initcall_levels[level]; fn < initcall_levels[level+1]; fn++)  		do_one_initcall(*fn);  } +static void __init do_initcalls(void) +{ +	int level; + +	for (level = 0; level < ARRAY_SIZE(initcall_levels) - 1; level++) +		do_initcall_level(level); +} +  /*   * Ok, the machine is now initialized. None of the devices   * have been touched yet, but the CPU subsystem is up and @@ -732,7 +785,7 @@ static void __init do_pre_smp_initcalls(void)  {  	initcall_t *fn; -	for (fn = __initcall_start; fn < __early_initcall_end; fn++) +	for (fn = __initcall_start; fn < __initcall0_start; fn++)  		do_one_initcall(*fn);  } diff --git a/kernel/module.c b/kernel/module.c index 7e31da9750c..6f6651a5459 100644 --- a/kernel/module.c +++ b/kernel/module.c @@ -2923,7 +2923,8 @@ static struct module *load_module(void __user *umod,  	mutex_unlock(&module_mutex);  	/* Module is ready to execute: parsing args may do that. */ -	err = parse_args(mod->name, mod->args, mod->kp, mod->num_kp, NULL); +	err = parse_args(mod->name, mod->args, mod->kp, mod->num_kp, +			 -32768, 32767, NULL);  	if (err < 0)  		goto unlink; diff --git a/kernel/params.c b/kernel/params.c index 508828afb87..f37d8263134 100644 --- a/kernel/params.c +++ b/kernel/params.c @@ -87,6 +87,8 @@ static int parse_one(char *param,  		     char *val,  		     const struct kernel_param *params,  		     unsigned num_params, +		     s16 min_level, +		     s16 max_level,  		     int (*handle_unknown)(char *param, char *val))  {  	unsigned int i; @@ -95,6 +97,9 @@ static int parse_one(char *param,  	/* Find parameter */  	for (i = 0; i < num_params; i++) {  		if (parameq(param, params[i].name)) { +			if (params[i].level < min_level +			    || params[i].level > max_level) +				return 0;  			/* No one handled NULL, so do it here. */  			if (!val && params[i].ops->set != param_set_bool  			    && params[i].ops->set != param_set_bint) @@ -174,6 +179,8 @@ int parse_args(const char *name,  	       char *args,  	       const struct kernel_param *params,  	       unsigned num, +	       s16 min_level, +	       s16 max_level,  	       int (*unknown)(char *param, char *val))  {  	char *param, *val; @@ -189,7 +196,8 @@ int parse_args(const char *name,  		args = next_arg(args, ¶m, &val);  		irq_was_disabled = irqs_disabled(); -		ret = parse_one(param, val, params, num, unknown); +		ret = parse_one(param, val, params, num, +				min_level, max_level, unknown);  		if (irq_was_disabled && !irqs_disabled()) {  			printk(KERN_WARNING "parse_args(): option '%s' enabled "  					"irq's!\n", param); @@ -374,7 +382,7 @@ static int param_array(const char *name,  		       unsigned int min, unsigned int max,  		       void *elem, int elemsize,  		       int (*set)(const char *, const struct kernel_param *kp), -		       u16 flags, +		       s16 level,  		       unsigned int *num)  {  	int ret; @@ -384,7 +392,7 @@ static int param_array(const char *name,  	/* Get the name right for errors. */  	kp.name = name;  	kp.arg = elem; -	kp.flags = flags; +	kp.level = level;  	*num = 0;  	/* 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)  	unsigned int temp_num;  	return param_array(kp->name, val, 1, arr->max, arr->elem, -			   arr->elemsize, arr->ops->set, kp->flags, +			   arr->elemsize, arr->ops->set, kp->level,  			   arr->num ?: &temp_num);  }  |