| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | /* Helpers for initial module or kernel cmdline parsing
 | 
					
						
							|  |  |  |    Copyright (C) 2001 Rusty Russell. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     This program is free software; you can redistribute it and/or modify | 
					
						
							|  |  |  |     it under the terms of the GNU General Public License as published by | 
					
						
							|  |  |  |     the Free Software Foundation; either version 2 of the License, or | 
					
						
							|  |  |  |     (at your option) any later version. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     This program is distributed in the hope that it will be useful, | 
					
						
							|  |  |  |     but WITHOUT ANY WARRANTY; without even the implied warranty of | 
					
						
							|  |  |  |     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | 
					
						
							|  |  |  |     GNU General Public License for more details. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     You should have received a copy of the GNU General Public License | 
					
						
							|  |  |  |     along with this program; if not, write to the Free Software | 
					
						
							|  |  |  |     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA | 
					
						
							|  |  |  | */ | 
					
						
							|  |  |  | #include <linux/kernel.h>
 | 
					
						
							|  |  |  | #include <linux/string.h>
 | 
					
						
							|  |  |  | #include <linux/errno.h>
 | 
					
						
							|  |  |  | #include <linux/module.h>
 | 
					
						
							| 
									
										
										
										
											2014-10-13 15:55:44 -07:00
										 |  |  | #include <linux/moduleparam.h>
 | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | #include <linux/device.h>
 | 
					
						
							|  |  |  | #include <linux/err.h>
 | 
					
						
							| 
									
										
										
										
											2005-10-30 15:03:48 -08:00
										 |  |  | #include <linux/slab.h>
 | 
					
						
							| 
									
										
										
										
											2009-07-06 17:11:22 +02:00
										 |  |  | #include <linux/ctype.h>
 | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-08-11 23:04:19 -06:00
										 |  |  | /* Protects all parameters, and incidentally kmalloced_param list. */ | 
					
						
							|  |  |  | static DEFINE_MUTEX(param_lock); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-08-11 23:04:18 -06:00
										 |  |  | /* This just allows us to keep track of which parameters are kmalloced. */ | 
					
						
							|  |  |  | struct kmalloced_param { | 
					
						
							|  |  |  | 	struct list_head list; | 
					
						
							|  |  |  | 	char val[]; | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | static LIST_HEAD(kmalloced_params); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void *kmalloc_parameter(unsigned int size) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	struct kmalloced_param *p; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	p = kmalloc(sizeof(*p) + size, GFP_KERNEL); | 
					
						
							|  |  |  | 	if (!p) | 
					
						
							|  |  |  | 		return NULL; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	list_add(&p->list, &kmalloced_params); | 
					
						
							|  |  |  | 	return p->val; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* Does nothing if parameter wasn't kmalloced above. */ | 
					
						
							|  |  |  | static void maybe_kfree_parameter(void *param) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	struct kmalloced_param *p; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	list_for_each_entry(p, &kmalloced_params, list) { | 
					
						
							|  |  |  | 		if (p->val == param) { | 
					
						
							|  |  |  | 			list_del(&p->list); | 
					
						
							|  |  |  | 			kfree(p); | 
					
						
							|  |  |  | 			break; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-10-10 00:03:37 +02:00
										 |  |  | static char dash2underscore(char c) | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | { | 
					
						
							|  |  |  | 	if (c == '-') | 
					
						
							|  |  |  | 		return '_'; | 
					
						
							|  |  |  | 	return c; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-10-10 00:03:37 +02:00
										 |  |  | bool parameqn(const char *a, const char *b, size_t n) | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2011-10-10 00:03:37 +02:00
										 |  |  | 	size_t i; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	for (i = 0; i < n; i++) { | 
					
						
							|  |  |  | 		if (dash2underscore(a[i]) != dash2underscore(b[i])) | 
					
						
							|  |  |  | 			return false; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return true; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | bool parameq(const char *a, const char *b) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	return parameqn(a, b, strlen(a)+1); | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-08-27 06:25:23 +09:30
										 |  |  | static void param_check_unsafe(const struct kernel_param *kp) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	if (kp->flags & KERNEL_PARAM_FL_UNSAFE) { | 
					
						
							|  |  |  | 		pr_warn("Setting dangerous option %s - tainting kernel\n", | 
					
						
							|  |  |  | 			kp->name); | 
					
						
							|  |  |  | 		add_taint(TAINT_USER, LOCKDEP_STILL_OK); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | static int parse_one(char *param, | 
					
						
							|  |  |  | 		     char *val, | 
					
						
							| 
									
										
											  
											
												params: add 3rd arg to option handler callback signature
Add a 3rd arg, named "doing", to unknown-options callbacks invoked
from parse_args(). The arg is passed as:
  "Booting kernel" from start_kernel(),
  initcall_level_names[i] from do_initcall_level(),
  mod->name from load_module(), via parse_args(), parse_one()
parse_args() already has the "name" parameter, which is renamed to
"doing" to better reflect current uses 1,2 above.  parse_args() passes
it to an altered parse_one(), which now passes it down into the
unknown option handler callbacks.
The mod->name will be needed to handle dyndbg for loadable modules,
since params passed by modprobe are not qualified (they do not have a
"$modname." prefix), and by the time the unknown-param callback is
called, the module name is not otherwise available.
Minor tweaks:
Add param-name to parse_one's pr_debug(), current message doesnt
identify the param being handled, add it.
Add a pr_info to print current level and level_name of the initcall,
and number of registered initcalls at that level.  This adds 7 lines
to dmesg output, like:
   initlevel:6=device, 172 registered initcalls
Drop "parameters" from initcall_level_names[], its unhelpful in the
pr_info() added above.  This array is passed into parse_args() by
do_initcall_level().
CC: Rusty Russell <rusty@rustcorp.com.au>
Signed-off-by: Jim Cromie <jim.cromie@gmail.com>
Acked-by: Jason Baron <jbaron@redhat.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
											
										 
											2012-04-27 14:30:34 -06:00
										 |  |  | 		     const char *doing, | 
					
						
							| 
									
										
										
										
											2010-08-11 23:04:18 -06:00
										 |  |  | 		     const struct kernel_param *params, | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 		     unsigned num_params, | 
					
						
							| 
									
										
										
										
											2012-03-26 12:50:51 +10:30
										 |  |  | 		     s16 min_level, | 
					
						
							|  |  |  | 		     s16 max_level, | 
					
						
							| 
									
										
											  
											
												params: add 3rd arg to option handler callback signature
Add a 3rd arg, named "doing", to unknown-options callbacks invoked
from parse_args(). The arg is passed as:
  "Booting kernel" from start_kernel(),
  initcall_level_names[i] from do_initcall_level(),
  mod->name from load_module(), via parse_args(), parse_one()
parse_args() already has the "name" parameter, which is renamed to
"doing" to better reflect current uses 1,2 above.  parse_args() passes
it to an altered parse_one(), which now passes it down into the
unknown option handler callbacks.
The mod->name will be needed to handle dyndbg for loadable modules,
since params passed by modprobe are not qualified (they do not have a
"$modname." prefix), and by the time the unknown-param callback is
called, the module name is not otherwise available.
Minor tweaks:
Add param-name to parse_one's pr_debug(), current message doesnt
identify the param being handled, add it.
Add a pr_info to print current level and level_name of the initcall,
and number of registered initcalls at that level.  This adds 7 lines
to dmesg output, like:
   initlevel:6=device, 172 registered initcalls
Drop "parameters" from initcall_level_names[], its unhelpful in the
pr_info() added above.  This array is passed into parse_args() by
do_initcall_level().
CC: Rusty Russell <rusty@rustcorp.com.au>
Signed-off-by: Jim Cromie <jim.cromie@gmail.com>
Acked-by: Jason Baron <jbaron@redhat.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
											
										 
											2012-04-27 14:30:34 -06:00
										 |  |  | 		     int (*handle_unknown)(char *param, char *val, | 
					
						
							|  |  |  | 				     const char *doing)) | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | { | 
					
						
							|  |  |  | 	unsigned int i; | 
					
						
							| 
									
										
										
										
											2010-08-11 23:04:19 -06:00
										 |  |  | 	int err; | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	/* Find parameter */ | 
					
						
							|  |  |  | 	for (i = 0; i < num_params; i++) { | 
					
						
							|  |  |  | 		if (parameq(param, params[i].name)) { | 
					
						
							| 
									
										
										
										
											2012-03-26 12:50:51 +10:30
										 |  |  | 			if (params[i].level < min_level | 
					
						
							|  |  |  | 			    || params[i].level > max_level) | 
					
						
							|  |  |  | 				return 0; | 
					
						
							| 
									
										
										
										
											2011-03-30 22:57:33 -03:00
										 |  |  | 			/* No one handled NULL, so do it here. */ | 
					
						
							| 
									
										
										
										
											2013-08-20 15:33:19 +09:30
										 |  |  | 			if (!val && | 
					
						
							| 
									
										
										
										
											2014-08-27 06:21:23 +09:30
										 |  |  | 			    !(params[i].ops->flags & KERNEL_PARAM_OPS_FL_NOARG)) | 
					
						
							| 
									
										
										
										
											2010-08-11 23:04:10 -06:00
										 |  |  | 				return -EINVAL; | 
					
						
							| 
									
										
											  
											
												params: add 3rd arg to option handler callback signature
Add a 3rd arg, named "doing", to unknown-options callbacks invoked
from parse_args(). The arg is passed as:
  "Booting kernel" from start_kernel(),
  initcall_level_names[i] from do_initcall_level(),
  mod->name from load_module(), via parse_args(), parse_one()
parse_args() already has the "name" parameter, which is renamed to
"doing" to better reflect current uses 1,2 above.  parse_args() passes
it to an altered parse_one(), which now passes it down into the
unknown option handler callbacks.
The mod->name will be needed to handle dyndbg for loadable modules,
since params passed by modprobe are not qualified (they do not have a
"$modname." prefix), and by the time the unknown-param callback is
called, the module name is not otherwise available.
Minor tweaks:
Add param-name to parse_one's pr_debug(), current message doesnt
identify the param being handled, add it.
Add a pr_info to print current level and level_name of the initcall,
and number of registered initcalls at that level.  This adds 7 lines
to dmesg output, like:
   initlevel:6=device, 172 registered initcalls
Drop "parameters" from initcall_level_names[], its unhelpful in the
pr_info() added above.  This array is passed into parse_args() by
do_initcall_level().
CC: Rusty Russell <rusty@rustcorp.com.au>
Signed-off-by: Jim Cromie <jim.cromie@gmail.com>
Acked-by: Jason Baron <jbaron@redhat.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
											
										 
											2012-04-27 14:30:34 -06:00
										 |  |  | 			pr_debug("handling %s with %p\n", param, | 
					
						
							|  |  |  | 				params[i].ops->set); | 
					
						
							| 
									
										
										
										
											2010-08-11 23:04:19 -06:00
										 |  |  | 			mutex_lock(¶m_lock); | 
					
						
							| 
									
										
										
										
											2014-08-27 06:25:23 +09:30
										 |  |  | 			param_check_unsafe(¶ms[i]); | 
					
						
							| 
									
										
										
										
											2010-08-11 23:04:19 -06:00
										 |  |  | 			err = params[i].ops->set(val, ¶ms[i]); | 
					
						
							|  |  |  | 			mutex_unlock(¶m_lock); | 
					
						
							|  |  |  | 			return err; | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (handle_unknown) { | 
					
						
							| 
									
										
											  
											
												params: add 3rd arg to option handler callback signature
Add a 3rd arg, named "doing", to unknown-options callbacks invoked
from parse_args(). The arg is passed as:
  "Booting kernel" from start_kernel(),
  initcall_level_names[i] from do_initcall_level(),
  mod->name from load_module(), via parse_args(), parse_one()
parse_args() already has the "name" parameter, which is renamed to
"doing" to better reflect current uses 1,2 above.  parse_args() passes
it to an altered parse_one(), which now passes it down into the
unknown option handler callbacks.
The mod->name will be needed to handle dyndbg for loadable modules,
since params passed by modprobe are not qualified (they do not have a
"$modname." prefix), and by the time the unknown-param callback is
called, the module name is not otherwise available.
Minor tweaks:
Add param-name to parse_one's pr_debug(), current message doesnt
identify the param being handled, add it.
Add a pr_info to print current level and level_name of the initcall,
and number of registered initcalls at that level.  This adds 7 lines
to dmesg output, like:
   initlevel:6=device, 172 registered initcalls
Drop "parameters" from initcall_level_names[], its unhelpful in the
pr_info() added above.  This array is passed into parse_args() by
do_initcall_level().
CC: Rusty Russell <rusty@rustcorp.com.au>
Signed-off-by: Jim Cromie <jim.cromie@gmail.com>
Acked-by: Jason Baron <jbaron@redhat.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
											
										 
											2012-04-27 14:30:34 -06:00
										 |  |  | 		pr_debug("doing %s: %s='%s'\n", doing, param, val); | 
					
						
							|  |  |  | 		return handle_unknown(param, val, doing); | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
											  
											
												params: add 3rd arg to option handler callback signature
Add a 3rd arg, named "doing", to unknown-options callbacks invoked
from parse_args(). The arg is passed as:
  "Booting kernel" from start_kernel(),
  initcall_level_names[i] from do_initcall_level(),
  mod->name from load_module(), via parse_args(), parse_one()
parse_args() already has the "name" parameter, which is renamed to
"doing" to better reflect current uses 1,2 above.  parse_args() passes
it to an altered parse_one(), which now passes it down into the
unknown option handler callbacks.
The mod->name will be needed to handle dyndbg for loadable modules,
since params passed by modprobe are not qualified (they do not have a
"$modname." prefix), and by the time the unknown-param callback is
called, the module name is not otherwise available.
Minor tweaks:
Add param-name to parse_one's pr_debug(), current message doesnt
identify the param being handled, add it.
Add a pr_info to print current level and level_name of the initcall,
and number of registered initcalls at that level.  This adds 7 lines
to dmesg output, like:
   initlevel:6=device, 172 registered initcalls
Drop "parameters" from initcall_level_names[], its unhelpful in the
pr_info() added above.  This array is passed into parse_args() by
do_initcall_level().
CC: Rusty Russell <rusty@rustcorp.com.au>
Signed-off-by: Jim Cromie <jim.cromie@gmail.com>
Acked-by: Jason Baron <jbaron@redhat.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
											
										 
											2012-04-27 14:30:34 -06:00
										 |  |  | 	pr_debug("Unknown argument '%s'\n", param); | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 	return -ENOENT; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* You can use " around spaces, but can't escape ". */ | 
					
						
							|  |  |  | /* Hyphens and underscores equivalent in parameter names. */ | 
					
						
							|  |  |  | static char *next_arg(char *args, char **param, char **val) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	unsigned int i, equals = 0; | 
					
						
							|  |  |  | 	int in_quote = 0, quoted = 0; | 
					
						
							|  |  |  | 	char *next; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (*args == '"') { | 
					
						
							|  |  |  | 		args++; | 
					
						
							|  |  |  | 		in_quote = 1; | 
					
						
							|  |  |  | 		quoted = 1; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	for (i = 0; args[i]; i++) { | 
					
						
							| 
									
										
										
										
											2009-07-06 17:11:22 +02:00
										 |  |  | 		if (isspace(args[i]) && !in_quote) | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 			break; | 
					
						
							|  |  |  | 		if (equals == 0) { | 
					
						
							|  |  |  | 			if (args[i] == '=') | 
					
						
							|  |  |  | 				equals = i; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		if (args[i] == '"') | 
					
						
							|  |  |  | 			in_quote = !in_quote; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	*param = args; | 
					
						
							|  |  |  | 	if (!equals) | 
					
						
							|  |  |  | 		*val = NULL; | 
					
						
							|  |  |  | 	else { | 
					
						
							|  |  |  | 		args[equals] = '\0'; | 
					
						
							|  |  |  | 		*val = args + equals + 1; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		/* Don't include quotes in value. */ | 
					
						
							|  |  |  | 		if (**val == '"') { | 
					
						
							|  |  |  | 			(*val)++; | 
					
						
							|  |  |  | 			if (args[i-1] == '"') | 
					
						
							|  |  |  | 				args[i-1] = '\0'; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		if (quoted && args[i-1] == '"') | 
					
						
							|  |  |  | 			args[i-1] = '\0'; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (args[i]) { | 
					
						
							|  |  |  | 		args[i] = '\0'; | 
					
						
							|  |  |  | 		next = args + i + 1; | 
					
						
							|  |  |  | 	} else | 
					
						
							|  |  |  | 		next = args + i; | 
					
						
							| 
									
										
										
										
											2005-09-27 21:45:34 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	/* Chew up trailing spaces. */ | 
					
						
							| 
									
										
										
										
											2009-12-14 18:01:06 -08:00
										 |  |  | 	return skip_spaces(next); | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* Args looks like "foo=bar,bar2 baz=fuz wiz". */ | 
					
						
							| 
									
										
										
										
											2014-04-28 11:34:33 +09:30
										 |  |  | char *parse_args(const char *doing, | 
					
						
							|  |  |  | 		 char *args, | 
					
						
							|  |  |  | 		 const struct kernel_param *params, | 
					
						
							|  |  |  | 		 unsigned num, | 
					
						
							|  |  |  | 		 s16 min_level, | 
					
						
							|  |  |  | 		 s16 max_level, | 
					
						
							|  |  |  | 		 int (*unknown)(char *param, char *val, const char *doing)) | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | { | 
					
						
							|  |  |  | 	char *param, *val; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-09-27 21:45:34 -07:00
										 |  |  | 	/* Chew leading spaces */ | 
					
						
							| 
									
										
										
										
											2009-12-14 18:01:06 -08:00
										 |  |  | 	args = skip_spaces(args); | 
					
						
							| 
									
										
										
										
											2005-09-27 21:45:34 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-05-03 11:57:37 -06:00
										 |  |  | 	if (*args) | 
					
						
							| 
									
										
											  
											
												params: add 3rd arg to option handler callback signature
Add a 3rd arg, named "doing", to unknown-options callbacks invoked
from parse_args(). The arg is passed as:
  "Booting kernel" from start_kernel(),
  initcall_level_names[i] from do_initcall_level(),
  mod->name from load_module(), via parse_args(), parse_one()
parse_args() already has the "name" parameter, which is renamed to
"doing" to better reflect current uses 1,2 above.  parse_args() passes
it to an altered parse_one(), which now passes it down into the
unknown option handler callbacks.
The mod->name will be needed to handle dyndbg for loadable modules,
since params passed by modprobe are not qualified (they do not have a
"$modname." prefix), and by the time the unknown-param callback is
called, the module name is not otherwise available.
Minor tweaks:
Add param-name to parse_one's pr_debug(), current message doesnt
identify the param being handled, add it.
Add a pr_info to print current level and level_name of the initcall,
and number of registered initcalls at that level.  This adds 7 lines
to dmesg output, like:
   initlevel:6=device, 172 registered initcalls
Drop "parameters" from initcall_level_names[], its unhelpful in the
pr_info() added above.  This array is passed into parse_args() by
do_initcall_level().
CC: Rusty Russell <rusty@rustcorp.com.au>
Signed-off-by: Jim Cromie <jim.cromie@gmail.com>
Acked-by: Jason Baron <jbaron@redhat.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
											
										 
											2012-04-27 14:30:34 -06:00
										 |  |  | 		pr_debug("doing %s, parsing ARGS: '%s'\n", doing, args); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 	while (*args) { | 
					
						
							|  |  |  | 		int ret; | 
					
						
							| 
									
										
										
										
											2007-01-05 16:36:20 -08:00
										 |  |  | 		int irq_was_disabled; | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		args = next_arg(args, ¶m, &val); | 
					
						
							| 
									
										
										
										
											2014-04-28 11:34:33 +09:30
										 |  |  | 		/* Stop at -- */ | 
					
						
							|  |  |  | 		if (!val && strcmp(param, "--") == 0) | 
					
						
							|  |  |  | 			return args; | 
					
						
							| 
									
										
										
										
											2007-01-05 16:36:20 -08:00
										 |  |  | 		irq_was_disabled = irqs_disabled(); | 
					
						
							| 
									
										
											  
											
												params: add 3rd arg to option handler callback signature
Add a 3rd arg, named "doing", to unknown-options callbacks invoked
from parse_args(). The arg is passed as:
  "Booting kernel" from start_kernel(),
  initcall_level_names[i] from do_initcall_level(),
  mod->name from load_module(), via parse_args(), parse_one()
parse_args() already has the "name" parameter, which is renamed to
"doing" to better reflect current uses 1,2 above.  parse_args() passes
it to an altered parse_one(), which now passes it down into the
unknown option handler callbacks.
The mod->name will be needed to handle dyndbg for loadable modules,
since params passed by modprobe are not qualified (they do not have a
"$modname." prefix), and by the time the unknown-param callback is
called, the module name is not otherwise available.
Minor tweaks:
Add param-name to parse_one's pr_debug(), current message doesnt
identify the param being handled, add it.
Add a pr_info to print current level and level_name of the initcall,
and number of registered initcalls at that level.  This adds 7 lines
to dmesg output, like:
   initlevel:6=device, 172 registered initcalls
Drop "parameters" from initcall_level_names[], its unhelpful in the
pr_info() added above.  This array is passed into parse_args() by
do_initcall_level().
CC: Rusty Russell <rusty@rustcorp.com.au>
Signed-off-by: Jim Cromie <jim.cromie@gmail.com>
Acked-by: Jason Baron <jbaron@redhat.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
											
										 
											2012-04-27 14:30:34 -06:00
										 |  |  | 		ret = parse_one(param, val, doing, params, num, | 
					
						
							| 
									
										
										
										
											2012-03-26 12:50:51 +10:30
										 |  |  | 				min_level, max_level, unknown); | 
					
						
							| 
									
										
										
										
											2012-05-03 18:22:44 -06:00
										 |  |  | 		if (irq_was_disabled && !irqs_disabled()) | 
					
						
							|  |  |  | 			pr_warn("%s: option '%s' enabled irq's!\n", | 
					
						
							|  |  |  | 				doing, param); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 		switch (ret) { | 
					
						
							|  |  |  | 		case -ENOENT: | 
					
						
							| 
									
										
										
										
											2012-05-03 18:22:44 -06:00
										 |  |  | 			pr_err("%s: Unknown parameter `%s'\n", doing, param); | 
					
						
							| 
									
										
										
										
											2014-04-28 11:34:33 +09:30
										 |  |  | 			return ERR_PTR(ret); | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 		case -ENOSPC: | 
					
						
							| 
									
										
										
										
											2012-05-03 18:22:44 -06:00
										 |  |  | 			pr_err("%s: `%s' too large for parameter `%s'\n", | 
					
						
							| 
									
										
											  
											
												params: add 3rd arg to option handler callback signature
Add a 3rd arg, named "doing", to unknown-options callbacks invoked
from parse_args(). The arg is passed as:
  "Booting kernel" from start_kernel(),
  initcall_level_names[i] from do_initcall_level(),
  mod->name from load_module(), via parse_args(), parse_one()
parse_args() already has the "name" parameter, which is renamed to
"doing" to better reflect current uses 1,2 above.  parse_args() passes
it to an altered parse_one(), which now passes it down into the
unknown option handler callbacks.
The mod->name will be needed to handle dyndbg for loadable modules,
since params passed by modprobe are not qualified (they do not have a
"$modname." prefix), and by the time the unknown-param callback is
called, the module name is not otherwise available.
Minor tweaks:
Add param-name to parse_one's pr_debug(), current message doesnt
identify the param being handled, add it.
Add a pr_info to print current level and level_name of the initcall,
and number of registered initcalls at that level.  This adds 7 lines
to dmesg output, like:
   initlevel:6=device, 172 registered initcalls
Drop "parameters" from initcall_level_names[], its unhelpful in the
pr_info() added above.  This array is passed into parse_args() by
do_initcall_level().
CC: Rusty Russell <rusty@rustcorp.com.au>
Signed-off-by: Jim Cromie <jim.cromie@gmail.com>
Acked-by: Jason Baron <jbaron@redhat.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
											
										 
											2012-04-27 14:30:34 -06:00
										 |  |  | 			       doing, val ?: "", param); | 
					
						
							| 
									
										
										
										
											2014-04-28 11:34:33 +09:30
										 |  |  | 			return ERR_PTR(ret); | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 		case 0: | 
					
						
							|  |  |  | 			break; | 
					
						
							|  |  |  | 		default: | 
					
						
							| 
									
										
										
										
											2012-05-03 18:22:44 -06:00
										 |  |  | 			pr_err("%s: `%s' invalid for parameter `%s'\n", | 
					
						
							| 
									
										
											  
											
												params: add 3rd arg to option handler callback signature
Add a 3rd arg, named "doing", to unknown-options callbacks invoked
from parse_args(). The arg is passed as:
  "Booting kernel" from start_kernel(),
  initcall_level_names[i] from do_initcall_level(),
  mod->name from load_module(), via parse_args(), parse_one()
parse_args() already has the "name" parameter, which is renamed to
"doing" to better reflect current uses 1,2 above.  parse_args() passes
it to an altered parse_one(), which now passes it down into the
unknown option handler callbacks.
The mod->name will be needed to handle dyndbg for loadable modules,
since params passed by modprobe are not qualified (they do not have a
"$modname." prefix), and by the time the unknown-param callback is
called, the module name is not otherwise available.
Minor tweaks:
Add param-name to parse_one's pr_debug(), current message doesnt
identify the param being handled, add it.
Add a pr_info to print current level and level_name of the initcall,
and number of registered initcalls at that level.  This adds 7 lines
to dmesg output, like:
   initlevel:6=device, 172 registered initcalls
Drop "parameters" from initcall_level_names[], its unhelpful in the
pr_info() added above.  This array is passed into parse_args() by
do_initcall_level().
CC: Rusty Russell <rusty@rustcorp.com.au>
Signed-off-by: Jim Cromie <jim.cromie@gmail.com>
Acked-by: Jason Baron <jbaron@redhat.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
											
										 
											2012-04-27 14:30:34 -06:00
										 |  |  | 			       doing, val ?: "", param); | 
					
						
							| 
									
										
										
										
											2014-04-28 11:34:33 +09:30
										 |  |  | 			return ERR_PTR(ret); | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* All parsed OK. */ | 
					
						
							| 
									
										
										
										
											2014-04-28 11:34:33 +09:30
										 |  |  | 	return NULL; | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* Lazy bastard, eh? */ | 
					
						
							| 
									
										
										
										
											2013-12-04 14:09:38 +10:30
										 |  |  | #define STANDARD_PARAM_DEF(name, type, format, strtolfn)      		\
 | 
					
						
							| 
									
										
										
										
											2010-08-11 23:04:12 -06:00
										 |  |  | 	int param_set_##name(const char *val, const struct kernel_param *kp) \ | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 	{								\ | 
					
						
							| 
									
										
										
										
											2013-12-04 14:09:38 +10:30
										 |  |  | 		return strtolfn(val, 0, (type *)kp->arg);		\ | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 	}								\ | 
					
						
							| 
									
										
										
										
											2010-08-11 23:04:12 -06:00
										 |  |  | 	int param_get_##name(char *buffer, const struct kernel_param *kp) \ | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 	{								\ | 
					
						
							| 
									
										
										
										
											2013-08-20 15:35:04 +09:30
										 |  |  | 		return scnprintf(buffer, PAGE_SIZE, format,		\ | 
					
						
							|  |  |  | 				*((type *)kp->arg));			\ | 
					
						
							| 
									
										
										
										
											2010-08-11 23:04:11 -06:00
										 |  |  | 	}								\ | 
					
						
							| 
									
										
										
										
											2010-08-11 23:04:12 -06:00
										 |  |  | 	struct kernel_param_ops param_ops_##name = {			\ | 
					
						
							|  |  |  | 		.set = param_set_##name,				\ | 
					
						
							|  |  |  | 		.get = param_get_##name,				\ | 
					
						
							|  |  |  | 	};								\ | 
					
						
							| 
									
										
										
										
											2010-08-11 23:04:11 -06:00
										 |  |  | 	EXPORT_SYMBOL(param_set_##name);				\ | 
					
						
							| 
									
										
										
										
											2010-08-11 23:04:12 -06:00
										 |  |  | 	EXPORT_SYMBOL(param_get_##name);				\ | 
					
						
							|  |  |  | 	EXPORT_SYMBOL(param_ops_##name) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-12-04 14:09:38 +10:30
										 |  |  | STANDARD_PARAM_DEF(byte, unsigned char, "%hhu", kstrtou8); | 
					
						
							|  |  |  | STANDARD_PARAM_DEF(short, short, "%hi", kstrtos16); | 
					
						
							|  |  |  | STANDARD_PARAM_DEF(ushort, unsigned short, "%hu", kstrtou16); | 
					
						
							|  |  |  | STANDARD_PARAM_DEF(int, int, "%i", kstrtoint); | 
					
						
							|  |  |  | STANDARD_PARAM_DEF(uint, unsigned int, "%u", kstrtouint); | 
					
						
							|  |  |  | STANDARD_PARAM_DEF(long, long, "%li", kstrtol); | 
					
						
							|  |  |  | STANDARD_PARAM_DEF(ulong, unsigned long, "%lu", kstrtoul); | 
					
						
							| 
									
										
										
										
											2014-06-25 15:27:37 +02:00
										 |  |  | STANDARD_PARAM_DEF(ullong, unsigned long long, "%llu", kstrtoull); | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-08-11 23:04:12 -06:00
										 |  |  | int param_set_charp(const char *val, const struct kernel_param *kp) | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | { | 
					
						
							|  |  |  | 	if (strlen(val) > 1024) { | 
					
						
							| 
									
										
										
										
											2012-05-03 18:22:44 -06:00
										 |  |  | 		pr_err("%s: string parameter too long\n", kp->name); | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 		return -ENOSPC; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-08-11 23:04:18 -06:00
										 |  |  | 	maybe_kfree_parameter(*(char **)kp->arg); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* This is a hack.  We can't kmalloc in early boot, and we
 | 
					
						
							| 
									
										
										
										
											2009-03-31 13:05:29 -06:00
										 |  |  | 	 * don't need to; this mangled commandline is preserved. */ | 
					
						
							|  |  |  | 	if (slab_is_available()) { | 
					
						
							| 
									
										
										
										
											2010-08-11 23:04:18 -06:00
										 |  |  | 		*(char **)kp->arg = kmalloc_parameter(strlen(val)+1); | 
					
						
							| 
									
										
										
										
											2009-10-29 08:56:17 -06:00
										 |  |  | 		if (!*(char **)kp->arg) | 
					
						
							| 
									
										
										
										
											2009-03-31 13:05:29 -06:00
										 |  |  | 			return -ENOMEM; | 
					
						
							| 
									
										
										
										
											2010-08-11 23:04:18 -06:00
										 |  |  | 		strcpy(*(char **)kp->arg, val); | 
					
						
							| 
									
										
										
										
											2009-03-31 13:05:29 -06:00
										 |  |  | 	} else | 
					
						
							|  |  |  | 		*(const char **)kp->arg = val; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 	return 0; | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2010-08-11 23:04:11 -06:00
										 |  |  | EXPORT_SYMBOL(param_set_charp); | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-08-11 23:04:12 -06:00
										 |  |  | int param_get_charp(char *buffer, const struct kernel_param *kp) | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2013-08-20 15:35:04 +09:30
										 |  |  | 	return scnprintf(buffer, PAGE_SIZE, "%s", *((char **)kp->arg)); | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2010-08-11 23:04:11 -06:00
										 |  |  | EXPORT_SYMBOL(param_get_charp); | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-08-11 23:04:18 -06:00
										 |  |  | static void param_free_charp(void *arg) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	maybe_kfree_parameter(*((char **)arg)); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-08-11 23:04:12 -06:00
										 |  |  | struct kernel_param_ops param_ops_charp = { | 
					
						
							|  |  |  | 	.set = param_set_charp, | 
					
						
							|  |  |  | 	.get = param_get_charp, | 
					
						
							| 
									
										
										
										
											2010-08-11 23:04:18 -06:00
										 |  |  | 	.free = param_free_charp, | 
					
						
							| 
									
										
										
										
											2010-08-11 23:04:12 -06:00
										 |  |  | }; | 
					
						
							|  |  |  | EXPORT_SYMBOL(param_ops_charp); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-06-12 21:46:57 -06:00
										 |  |  | /* Actually could be a bool or an int, for historical reasons. */ | 
					
						
							| 
									
										
										
										
											2010-08-11 23:04:12 -06:00
										 |  |  | int param_set_bool(const char *val, const struct kernel_param *kp) | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | { | 
					
						
							|  |  |  | 	/* No equals means "set"... */ | 
					
						
							|  |  |  | 	if (!val) val = "1"; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* One of =[yYnN01] */ | 
					
						
							| 
									
										
										
										
											2012-03-26 12:50:51 +10:30
										 |  |  | 	return strtobool(val, kp->arg); | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2010-08-11 23:04:11 -06:00
										 |  |  | EXPORT_SYMBOL(param_set_bool); | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-08-11 23:04:12 -06:00
										 |  |  | int param_get_bool(char *buffer, const struct kernel_param *kp) | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | { | 
					
						
							|  |  |  | 	/* Y and N chosen as being relatively non-coder friendly */ | 
					
						
							| 
									
										
										
										
											2012-03-26 12:50:51 +10:30
										 |  |  | 	return sprintf(buffer, "%c", *(bool *)kp->arg ? 'Y' : 'N'); | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2010-08-11 23:04:11 -06:00
										 |  |  | EXPORT_SYMBOL(param_get_bool); | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-08-11 23:04:12 -06:00
										 |  |  | struct kernel_param_ops param_ops_bool = { | 
					
						
							| 
									
										
										
										
											2014-08-27 06:21:23 +09:30
										 |  |  | 	.flags = KERNEL_PARAM_OPS_FL_NOARG, | 
					
						
							| 
									
										
										
										
											2010-08-11 23:04:12 -06:00
										 |  |  | 	.set = param_set_bool, | 
					
						
							|  |  |  | 	.get = param_get_bool, | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | EXPORT_SYMBOL(param_ops_bool); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-06-12 21:46:57 -06:00
										 |  |  | /* This one must be bool. */ | 
					
						
							| 
									
										
										
										
											2010-08-11 23:04:12 -06:00
										 |  |  | int param_set_invbool(const char *val, const struct kernel_param *kp) | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2009-06-12 21:46:57 -06:00
										 |  |  | 	int ret; | 
					
						
							|  |  |  | 	bool boolval; | 
					
						
							| 
									
										
										
										
											2007-10-16 23:29:34 -07:00
										 |  |  | 	struct kernel_param dummy; | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-10-16 23:29:34 -07:00
										 |  |  | 	dummy.arg = &boolval; | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 	ret = param_set_bool(val, &dummy); | 
					
						
							|  |  |  | 	if (ret == 0) | 
					
						
							| 
									
										
										
										
											2009-06-12 21:46:53 -06:00
										 |  |  | 		*(bool *)kp->arg = !boolval; | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 	return ret; | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2010-08-11 23:04:11 -06:00
										 |  |  | EXPORT_SYMBOL(param_set_invbool); | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-08-11 23:04:12 -06:00
										 |  |  | int param_get_invbool(char *buffer, const struct kernel_param *kp) | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2009-06-12 21:46:53 -06:00
										 |  |  | 	return sprintf(buffer, "%c", (*(bool *)kp->arg) ? 'N' : 'Y'); | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2010-08-11 23:04:11 -06:00
										 |  |  | EXPORT_SYMBOL(param_get_invbool); | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-08-11 23:04:12 -06:00
										 |  |  | struct kernel_param_ops param_ops_invbool = { | 
					
						
							|  |  |  | 	.set = param_set_invbool, | 
					
						
							|  |  |  | 	.get = param_get_invbool, | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | EXPORT_SYMBOL(param_ops_invbool); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-01-13 09:32:17 +10:30
										 |  |  | int param_set_bint(const char *val, const struct kernel_param *kp) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	struct kernel_param boolkp; | 
					
						
							|  |  |  | 	bool v; | 
					
						
							|  |  |  | 	int ret; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* Match bool exactly, by re-using it. */ | 
					
						
							|  |  |  | 	boolkp = *kp; | 
					
						
							|  |  |  | 	boolkp.arg = &v; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	ret = param_set_bool(val, &boolkp); | 
					
						
							|  |  |  | 	if (ret == 0) | 
					
						
							|  |  |  | 		*(int *)kp->arg = v; | 
					
						
							|  |  |  | 	return ret; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | EXPORT_SYMBOL(param_set_bint); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | struct kernel_param_ops param_ops_bint = { | 
					
						
							| 
									
										
										
										
											2014-08-27 06:21:23 +09:30
										 |  |  | 	.flags = KERNEL_PARAM_OPS_FL_NOARG, | 
					
						
							| 
									
										
										
										
											2012-01-13 09:32:17 +10:30
										 |  |  | 	.set = param_set_bint, | 
					
						
							|  |  |  | 	.get = param_get_int, | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | EXPORT_SYMBOL(param_ops_bint); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-05-08 00:28:50 -07:00
										 |  |  | /* We break the rule and mangle the string. */ | 
					
						
							| 
									
										
										
										
											2006-03-25 03:07:06 -08:00
										 |  |  | static int param_array(const char *name, | 
					
						
							|  |  |  | 		       const char *val, | 
					
						
							|  |  |  | 		       unsigned int min, unsigned int max, | 
					
						
							|  |  |  | 		       void *elem, int elemsize, | 
					
						
							| 
									
										
										
										
											2010-08-11 23:04:12 -06:00
										 |  |  | 		       int (*set)(const char *, const struct kernel_param *kp), | 
					
						
							| 
									
										
										
										
											2012-03-26 12:50:51 +10:30
										 |  |  | 		       s16 level, | 
					
						
							| 
									
										
										
										
											2008-02-06 01:37:50 -08:00
										 |  |  | 		       unsigned int *num) | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | { | 
					
						
							|  |  |  | 	int ret; | 
					
						
							|  |  |  | 	struct kernel_param kp; | 
					
						
							|  |  |  | 	char save; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* Get the name right for errors. */ | 
					
						
							|  |  |  | 	kp.name = name; | 
					
						
							|  |  |  | 	kp.arg = elem; | 
					
						
							| 
									
										
										
										
											2012-03-26 12:50:51 +10:30
										 |  |  | 	kp.level = level; | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	*num = 0; | 
					
						
							|  |  |  | 	/* We expect a comma-separated list of values. */ | 
					
						
							|  |  |  | 	do { | 
					
						
							|  |  |  | 		int len; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		if (*num == max) { | 
					
						
							| 
									
										
										
										
											2012-05-03 18:22:44 -06:00
										 |  |  | 			pr_err("%s: can only take %i arguments\n", name, max); | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 			return -EINVAL; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		len = strcspn(val, ","); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		/* nul-terminate and parse */ | 
					
						
							|  |  |  | 		save = val[len]; | 
					
						
							|  |  |  | 		((char *)val)[len] = '\0'; | 
					
						
							| 
									
										
										
										
											2010-08-11 23:04:19 -06:00
										 |  |  | 		BUG_ON(!mutex_is_locked(¶m_lock)); | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 		ret = set(val, &kp); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		if (ret != 0) | 
					
						
							|  |  |  | 			return ret; | 
					
						
							|  |  |  | 		kp.arg += elemsize; | 
					
						
							|  |  |  | 		val += len+1; | 
					
						
							|  |  |  | 		(*num)++; | 
					
						
							|  |  |  | 	} while (save == ','); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (*num < min) { | 
					
						
							| 
									
										
										
										
											2012-05-03 18:22:44 -06:00
										 |  |  | 		pr_err("%s: needs at least %i arguments\n", name, min); | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 		return -EINVAL; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-08-11 23:04:12 -06:00
										 |  |  | static int param_array_set(const char *val, const struct kernel_param *kp) | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2007-10-16 23:29:34 -07:00
										 |  |  | 	const struct kparam_array *arr = kp->arr; | 
					
						
							| 
									
										
										
											
												[PATCH] kernel/param.c: don't use .max when .num is NULL in param_array_set()
there seems to be a bug, at least for me, in kernel/param.c for arrays with
.num == NULL.  If .num == NULL, the function param_array_set() uses &.max
for the call to param_array(), wich alters the .max value to the number of
arguments.  The result is, you can't set more array arguments as the last
time you set the parameter.
example:
# a module 'example' with
# static int array[10] = { 0, };
# module_param_array(array, int, NULL, 0644);
$ insmod example.ko array=1,2,3
$ cat /sys/module/example/parameters/array
1,2,3
$ echo "4,3,2,1" > /sys/module/example/parameters/array
$ dmesg | tail -n 1
kernel: array: can take only 3 arguments
Signed-off-by: Bert Wesarg <wesarg@informatik.uni-halle.de>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
											
										 
											2005-04-16 15:25:42 -07:00
										 |  |  | 	unsigned int temp_num; | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	return param_array(kp->name, val, 1, arr->max, arr->elem, | 
					
						
							| 
									
										
										
										
											2012-03-26 12:50:51 +10:30
										 |  |  | 			   arr->elemsize, arr->ops->set, kp->level, | 
					
						
							| 
									
										
										
										
											2009-10-29 08:56:19 -06:00
										 |  |  | 			   arr->num ?: &temp_num); | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-08-11 23:04:12 -06:00
										 |  |  | static int param_array_get(char *buffer, const struct kernel_param *kp) | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | { | 
					
						
							|  |  |  | 	int i, off, ret; | 
					
						
							| 
									
										
										
										
											2007-10-16 23:29:34 -07:00
										 |  |  | 	const struct kparam_array *arr = kp->arr; | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 	struct kernel_param p; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	p = *kp; | 
					
						
							|  |  |  | 	for (i = off = 0; i < (arr->num ? *arr->num : arr->max); i++) { | 
					
						
							|  |  |  | 		if (i) | 
					
						
							|  |  |  | 			buffer[off++] = ','; | 
					
						
							|  |  |  | 		p.arg = arr->elem + arr->elemsize * i; | 
					
						
							| 
									
										
										
										
											2010-08-11 23:04:19 -06:00
										 |  |  | 		BUG_ON(!mutex_is_locked(¶m_lock)); | 
					
						
							| 
									
										
										
										
											2010-08-11 23:04:12 -06:00
										 |  |  | 		ret = arr->ops->get(buffer + off, &p); | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 		if (ret < 0) | 
					
						
							|  |  |  | 			return ret; | 
					
						
							|  |  |  | 		off += ret; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	buffer[off] = '\0'; | 
					
						
							|  |  |  | 	return off; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-08-11 23:04:17 -06:00
										 |  |  | static void param_array_free(void *arg) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	unsigned int i; | 
					
						
							|  |  |  | 	const struct kparam_array *arr = arg; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (arr->ops->free) | 
					
						
							|  |  |  | 		for (i = 0; i < (arr->num ? *arr->num : arr->max); i++) | 
					
						
							|  |  |  | 			arr->ops->free(arr->elem + arr->elemsize * i); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-08-11 23:04:12 -06:00
										 |  |  | struct kernel_param_ops param_array_ops = { | 
					
						
							|  |  |  | 	.set = param_array_set, | 
					
						
							|  |  |  | 	.get = param_array_get, | 
					
						
							| 
									
										
										
										
											2010-08-11 23:04:17 -06:00
										 |  |  | 	.free = param_array_free, | 
					
						
							| 
									
										
										
										
											2010-08-11 23:04:12 -06:00
										 |  |  | }; | 
					
						
							|  |  |  | EXPORT_SYMBOL(param_array_ops); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | int param_set_copystring(const char *val, const struct kernel_param *kp) | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2007-10-16 23:29:34 -07:00
										 |  |  | 	const struct kparam_string *kps = kp->str; | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	if (strlen(val)+1 > kps->maxlen) { | 
					
						
							| 
									
										
										
										
											2012-05-03 18:22:44 -06:00
										 |  |  | 		pr_err("%s: string doesn't fit in %u chars.\n", | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 		       kp->name, kps->maxlen-1); | 
					
						
							|  |  |  | 		return -ENOSPC; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	strcpy(kps->string, val); | 
					
						
							|  |  |  | 	return 0; | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2010-08-11 23:04:11 -06:00
										 |  |  | EXPORT_SYMBOL(param_set_copystring); | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-08-11 23:04:12 -06:00
										 |  |  | int param_get_string(char *buffer, const struct kernel_param *kp) | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2007-10-16 23:29:34 -07:00
										 |  |  | 	const struct kparam_string *kps = kp->str; | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 	return strlcpy(buffer, kps->string, kps->maxlen); | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2010-08-11 23:04:11 -06:00
										 |  |  | EXPORT_SYMBOL(param_get_string); | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-08-11 23:04:12 -06:00
										 |  |  | struct kernel_param_ops param_ops_string = { | 
					
						
							|  |  |  | 	.set = param_set_copystring, | 
					
						
							|  |  |  | 	.get = param_get_string, | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | EXPORT_SYMBOL(param_ops_string); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | /* sysfs output in /sys/modules/XYZ/parameters/ */ | 
					
						
							| 
									
										
										
										
											2010-02-01 18:26:59 -05:00
										 |  |  | #define to_module_attr(n) container_of(n, struct module_attribute, attr)
 | 
					
						
							|  |  |  | #define to_module_kobject(n) container_of(n, struct module_kobject, kobj)
 | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  | struct param_attribute | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	struct module_attribute mattr; | 
					
						
							| 
									
										
										
										
											2010-08-11 23:04:12 -06:00
										 |  |  | 	const struct kernel_param *param; | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | struct module_param_attrs | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2008-10-22 10:00:22 -05:00
										 |  |  | 	unsigned int num; | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 	struct attribute_group grp; | 
					
						
							|  |  |  | 	struct param_attribute attrs[0]; | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-02-13 15:19:06 -08:00
										 |  |  | #ifdef CONFIG_SYSFS
 | 
					
						
							| 
									
										
										
										
											2010-02-01 18:26:59 -05:00
										 |  |  | #define to_param_attr(n) container_of(n, struct param_attribute, mattr)
 | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  | static ssize_t param_attr_show(struct module_attribute *mattr, | 
					
						
							| 
									
										
										
										
											2011-07-24 22:06:04 +09:30
										 |  |  | 			       struct module_kobject *mk, char *buf) | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | { | 
					
						
							|  |  |  | 	int count; | 
					
						
							|  |  |  | 	struct param_attribute *attribute = to_param_attr(mattr); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-08-11 23:04:12 -06:00
										 |  |  | 	if (!attribute->param->ops->get) | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 		return -EPERM; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-08-11 23:04:19 -06:00
										 |  |  | 	mutex_lock(¶m_lock); | 
					
						
							| 
									
										
										
										
											2010-08-11 23:04:12 -06:00
										 |  |  | 	count = attribute->param->ops->get(buf, attribute->param); | 
					
						
							| 
									
										
										
										
											2010-08-11 23:04:19 -06:00
										 |  |  | 	mutex_unlock(¶m_lock); | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 	if (count > 0) { | 
					
						
							|  |  |  | 		strcat(buf, "\n"); | 
					
						
							|  |  |  | 		++count; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return count; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* sysfs always hands a nul-terminated string in buf.  We rely on that. */ | 
					
						
							|  |  |  | static ssize_t param_attr_store(struct module_attribute *mattr, | 
					
						
							| 
									
										
										
										
											2011-07-24 22:06:04 +09:30
										 |  |  | 				struct module_kobject *km, | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 				const char *buf, size_t len) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |  	int err; | 
					
						
							|  |  |  | 	struct param_attribute *attribute = to_param_attr(mattr); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-08-11 23:04:12 -06:00
										 |  |  | 	if (!attribute->param->ops->set) | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 		return -EPERM; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-08-11 23:04:19 -06:00
										 |  |  | 	mutex_lock(¶m_lock); | 
					
						
							| 
									
										
										
										
											2014-08-27 06:25:23 +09:30
										 |  |  | 	param_check_unsafe(attribute->param); | 
					
						
							| 
									
										
										
										
											2010-08-11 23:04:12 -06:00
										 |  |  | 	err = attribute->param->ops->set(buf, attribute->param); | 
					
						
							| 
									
										
										
										
											2010-08-11 23:04:19 -06:00
										 |  |  | 	mutex_unlock(¶m_lock); | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 	if (!err) | 
					
						
							|  |  |  | 		return len; | 
					
						
							|  |  |  | 	return err; | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2007-02-13 15:19:06 -08:00
										 |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  | #ifdef CONFIG_MODULES
 | 
					
						
							|  |  |  | #define __modinit
 | 
					
						
							|  |  |  | #else
 | 
					
						
							|  |  |  | #define __modinit __init
 | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-02-13 15:19:06 -08:00
										 |  |  | #ifdef CONFIG_SYSFS
 | 
					
						
							| 
									
										
										
										
											2010-08-11 23:04:19 -06:00
										 |  |  | void __kernel_param_lock(void) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	mutex_lock(¶m_lock); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | EXPORT_SYMBOL(__kernel_param_lock); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void __kernel_param_unlock(void) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	mutex_unlock(¶m_lock); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | EXPORT_SYMBOL(__kernel_param_unlock); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | /*
 | 
					
						
							| 
									
										
										
										
											2008-10-22 10:00:22 -05:00
										 |  |  |  * add_sysfs_param - add a parameter to sysfs | 
					
						
							|  |  |  |  * @mk: struct module_kobject | 
					
						
							|  |  |  |  * @kparam: the actual parameter definition to add to sysfs | 
					
						
							|  |  |  |  * @name: name of parameter | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  |  * | 
					
						
							| 
									
										
										
										
											2008-10-22 10:00:22 -05:00
										 |  |  |  * Create a kobject if for a (per-module) parameter if mp NULL, and | 
					
						
							|  |  |  |  * create file in sysfs.  Returns an error on out of memory.  Always cleans up | 
					
						
							|  |  |  |  * if there's an error. | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  |  */ | 
					
						
							| 
									
										
										
										
											2008-10-22 10:00:22 -05:00
										 |  |  | static __modinit int add_sysfs_param(struct module_kobject *mk, | 
					
						
							| 
									
										
										
										
											2010-08-11 23:04:12 -06:00
										 |  |  | 				     const struct kernel_param *kp, | 
					
						
							| 
									
										
										
										
											2008-10-22 10:00:22 -05:00
										 |  |  | 				     const char *name) | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2014-11-10 09:32:29 +10:30
										 |  |  | 	struct module_param_attrs *new_mp; | 
					
						
							|  |  |  | 	struct attribute **new_attrs; | 
					
						
							|  |  |  | 	unsigned int i; | 
					
						
							| 
									
										
										
										
											2008-10-22 10:00:22 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	/* We don't bother calling this with invisible parameters. */ | 
					
						
							|  |  |  | 	BUG_ON(!kp->perm); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (!mk->mp) { | 
					
						
							| 
									
										
										
										
											2014-11-10 09:32:29 +10:30
										 |  |  | 		/* First allocation. */ | 
					
						
							|  |  |  | 		mk->mp = kzalloc(sizeof(*mk->mp), GFP_KERNEL); | 
					
						
							|  |  |  | 		if (!mk->mp) | 
					
						
							|  |  |  | 			return -ENOMEM; | 
					
						
							|  |  |  | 		mk->mp->grp.name = "parameters"; | 
					
						
							|  |  |  | 		/* NULL-terminated attribute array. */ | 
					
						
							|  |  |  | 		mk->mp->grp.attrs = kzalloc(sizeof(mk->mp->grp.attrs[0]), | 
					
						
							|  |  |  | 					    GFP_KERNEL); | 
					
						
							|  |  |  | 		/* Caller will cleanup via free_module_param_attrs */ | 
					
						
							|  |  |  | 		if (!mk->mp->grp.attrs) | 
					
						
							|  |  |  | 			return -ENOMEM; | 
					
						
							| 
									
										
										
										
											2008-10-22 10:00:22 -05:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-11-10 09:32:29 +10:30
										 |  |  | 	/* Enlarge allocations. */ | 
					
						
							|  |  |  | 	new_mp = krealloc(mk->mp, | 
					
						
							|  |  |  | 			  sizeof(*mk->mp) + | 
					
						
							|  |  |  | 			  sizeof(mk->mp->attrs[0]) * (mk->mp->num + 1), | 
					
						
							|  |  |  | 			  GFP_KERNEL); | 
					
						
							|  |  |  | 	if (!new_mp) | 
					
						
							|  |  |  | 		return -ENOMEM; | 
					
						
							|  |  |  | 	mk->mp = new_mp; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* Extra pointer for NULL terminator */ | 
					
						
							|  |  |  | 	new_attrs = krealloc(mk->mp->grp.attrs, | 
					
						
							|  |  |  | 			     sizeof(mk->mp->grp.attrs[0]) * (mk->mp->num + 2), | 
					
						
							|  |  |  | 			     GFP_KERNEL); | 
					
						
							|  |  |  | 	if (!new_attrs) | 
					
						
							|  |  |  | 		return -ENOMEM; | 
					
						
							|  |  |  | 	mk->mp->grp.attrs = new_attrs; | 
					
						
							| 
									
										
										
										
											2008-10-22 10:00:22 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	/* Tack new one on the end. */ | 
					
						
							| 
									
										
										
										
											2015-01-20 09:07:04 +10:30
										 |  |  | 	memset(&mk->mp->attrs[mk->mp->num], 0, sizeof(mk->mp->attrs[0])); | 
					
						
							| 
									
										
										
										
											2014-11-10 09:32:29 +10:30
										 |  |  | 	sysfs_attr_init(&mk->mp->attrs[mk->mp->num].mattr.attr); | 
					
						
							|  |  |  | 	mk->mp->attrs[mk->mp->num].param = kp; | 
					
						
							|  |  |  | 	mk->mp->attrs[mk->mp->num].mattr.show = param_attr_show; | 
					
						
							| 
									
										
										
										
											2014-12-12 13:36:49 +10:30
										 |  |  | 	/* Do not allow runtime DAC changes to make param writable. */ | 
					
						
							|  |  |  | 	if ((kp->perm & (S_IWUSR | S_IWGRP | S_IWOTH)) != 0) | 
					
						
							|  |  |  | 		mk->mp->attrs[mk->mp->num].mattr.store = param_attr_store; | 
					
						
							| 
									
										
										
										
											2014-12-23 15:05:36 +10:30
										 |  |  | 	else | 
					
						
							|  |  |  | 		mk->mp->attrs[mk->mp->num].mattr.store = NULL; | 
					
						
							| 
									
										
										
										
											2014-11-10 09:32:29 +10:30
										 |  |  | 	mk->mp->attrs[mk->mp->num].mattr.attr.name = (char *)name; | 
					
						
							|  |  |  | 	mk->mp->attrs[mk->mp->num].mattr.attr.mode = kp->perm; | 
					
						
							|  |  |  | 	mk->mp->num++; | 
					
						
							| 
									
										
										
										
											2008-10-22 10:00:22 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	/* Fix up all the pointers, since krealloc can move us */ | 
					
						
							| 
									
										
										
										
											2014-11-10 09:32:29 +10:30
										 |  |  | 	for (i = 0; i < mk->mp->num; i++) | 
					
						
							|  |  |  | 		mk->mp->grp.attrs[i] = &mk->mp->attrs[i].mattr.attr; | 
					
						
							|  |  |  | 	mk->mp->grp.attrs[mk->mp->num] = NULL; | 
					
						
							| 
									
										
										
										
											2008-10-22 10:00:22 -05:00
										 |  |  | 	return 0; | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-10-23 12:07:17 -07:00
										 |  |  | #ifdef CONFIG_MODULES
 | 
					
						
							| 
									
										
										
										
											2008-10-22 10:00:22 -05:00
										 |  |  | static void free_module_param_attrs(struct module_kobject *mk) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2014-11-10 09:32:29 +10:30
										 |  |  | 	if (mk->mp) | 
					
						
							|  |  |  | 		kfree(mk->mp->grp.attrs); | 
					
						
							| 
									
										
										
										
											2008-10-22 10:00:22 -05:00
										 |  |  | 	kfree(mk->mp); | 
					
						
							|  |  |  | 	mk->mp = NULL; | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /*
 | 
					
						
							|  |  |  |  * module_param_sysfs_setup - setup sysfs support for one module | 
					
						
							|  |  |  |  * @mod: module | 
					
						
							|  |  |  |  * @kparam: module parameters (array) | 
					
						
							|  |  |  |  * @num_params: number of module parameters | 
					
						
							|  |  |  |  * | 
					
						
							| 
									
										
										
										
											2008-10-22 10:00:22 -05:00
										 |  |  |  * Adds sysfs entries for module parameters under | 
					
						
							|  |  |  |  * /sys/module/[mod->name]/parameters/ | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  |  */ | 
					
						
							|  |  |  | int module_param_sysfs_setup(struct module *mod, | 
					
						
							| 
									
										
										
										
											2010-08-11 23:04:12 -06:00
										 |  |  | 			     const struct kernel_param *kparam, | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 			     unsigned int num_params) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2008-10-22 10:00:22 -05:00
										 |  |  | 	int i, err; | 
					
						
							|  |  |  | 	bool params = false; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	for (i = 0; i < num_params; i++) { | 
					
						
							|  |  |  | 		if (kparam[i].perm == 0) | 
					
						
							|  |  |  | 			continue; | 
					
						
							|  |  |  | 		err = add_sysfs_param(&mod->mkobj, &kparam[i], kparam[i].name); | 
					
						
							| 
									
										
										
										
											2014-11-10 09:32:29 +10:30
										 |  |  | 		if (err) { | 
					
						
							|  |  |  | 			free_module_param_attrs(&mod->mkobj); | 
					
						
							| 
									
										
										
										
											2008-10-22 10:00:22 -05:00
										 |  |  | 			return err; | 
					
						
							| 
									
										
										
										
											2014-11-10 09:32:29 +10:30
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2008-10-22 10:00:22 -05:00
										 |  |  | 		params = true; | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-10-22 10:00:22 -05:00
										 |  |  | 	if (!params) | 
					
						
							|  |  |  | 		return 0; | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-10-22 10:00:22 -05:00
										 |  |  | 	/* Create the param group. */ | 
					
						
							|  |  |  | 	err = sysfs_create_group(&mod->mkobj.kobj, &mod->mkobj.mp->grp); | 
					
						
							|  |  |  | 	if (err) | 
					
						
							|  |  |  | 		free_module_param_attrs(&mod->mkobj); | 
					
						
							|  |  |  | 	return err; | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /*
 | 
					
						
							|  |  |  |  * module_param_sysfs_remove - remove sysfs support for one module | 
					
						
							|  |  |  |  * @mod: module | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * Remove sysfs entries for module parameters and the corresponding | 
					
						
							|  |  |  |  * kobject. | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | void module_param_sysfs_remove(struct module *mod) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2008-10-22 10:00:22 -05:00
										 |  |  | 	if (mod->mkobj.mp) { | 
					
						
							|  |  |  | 		sysfs_remove_group(&mod->mkobj.kobj, &mod->mkobj.mp->grp); | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 		/* We are positive that no one is using any param
 | 
					
						
							|  |  |  | 		 * attrs at this point.  Deallocate immediately. */ | 
					
						
							| 
									
										
										
										
											2008-10-22 10:00:22 -05:00
										 |  |  | 		free_module_param_attrs(&mod->mkobj); | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-03-31 13:05:29 -06:00
										 |  |  | void destroy_params(const struct kernel_param *params, unsigned num) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2010-08-11 23:04:17 -06:00
										 |  |  | 	unsigned int i; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	for (i = 0; i < num; i++) | 
					
						
							|  |  |  | 		if (params[i].ops->free) | 
					
						
							|  |  |  | 			params[i].ops->free(params[i].arg); | 
					
						
							| 
									
										
										
										
											2009-03-31 13:05:29 -06:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-12-15 14:00:19 -08:00
										 |  |  | static struct module_kobject * __init locate_module_kobject(const char *name) | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | { | 
					
						
							|  |  |  | 	struct module_kobject *mk; | 
					
						
							| 
									
										
										
										
											2008-10-22 10:00:22 -05:00
										 |  |  | 	struct kobject *kobj; | 
					
						
							|  |  |  | 	int err; | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-10-22 10:00:22 -05:00
										 |  |  | 	kobj = kset_find_obj(module_kset, name); | 
					
						
							|  |  |  | 	if (kobj) { | 
					
						
							|  |  |  | 		mk = to_module_kobject(kobj); | 
					
						
							|  |  |  | 	} else { | 
					
						
							|  |  |  | 		mk = kzalloc(sizeof(struct module_kobject), GFP_KERNEL); | 
					
						
							|  |  |  | 		BUG_ON(!mk); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		mk->mod = THIS_MODULE; | 
					
						
							|  |  |  | 		mk->kobj.kset = module_kset; | 
					
						
							|  |  |  | 		err = kobject_init_and_add(&mk->kobj, &module_ktype, NULL, | 
					
						
							|  |  |  | 					   "%s", name); | 
					
						
							| 
									
										
										
										
											2011-07-24 22:06:04 +09:30
										 |  |  | #ifdef CONFIG_MODULES
 | 
					
						
							|  |  |  | 		if (!err) | 
					
						
							|  |  |  | 			err = sysfs_create_file(&mk->kobj, &module_uevent.attr); | 
					
						
							|  |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2008-10-22 10:00:22 -05:00
										 |  |  | 		if (err) { | 
					
						
							|  |  |  | 			kobject_put(&mk->kobj); | 
					
						
							| 
									
										
										
										
											2012-05-03 18:22:44 -06:00
										 |  |  | 			pr_crit("Adding module '%s' to sysfs failed (%d), the system may be unstable.\n", | 
					
						
							| 
									
										
										
										
											2010-12-15 14:00:19 -08:00
										 |  |  | 				name, err); | 
					
						
							|  |  |  | 			return NULL; | 
					
						
							| 
									
										
										
										
											2008-10-22 10:00:22 -05:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2010-12-15 14:00:19 -08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		/* So that we hold reference in both cases. */ | 
					
						
							| 
									
										
										
										
											2008-10-22 10:00:22 -05:00
										 |  |  | 		kobject_get(&mk->kobj); | 
					
						
							| 
									
										
										
										
											2007-07-30 11:26:38 -07:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2008-10-22 10:00:22 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-12-15 14:00:19 -08:00
										 |  |  | 	return mk; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void __init kernel_add_sysfs_param(const char *name, | 
					
						
							| 
									
										
										
										
											2014-10-13 15:55:44 -07:00
										 |  |  | 					  const struct kernel_param *kparam, | 
					
						
							| 
									
										
										
										
											2010-12-15 14:00:19 -08:00
										 |  |  | 					  unsigned int name_skip) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	struct module_kobject *mk; | 
					
						
							|  |  |  | 	int err; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	mk = locate_module_kobject(name); | 
					
						
							|  |  |  | 	if (!mk) | 
					
						
							|  |  |  | 		return; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* We need to remove old parameters before adding more. */ | 
					
						
							|  |  |  | 	if (mk->mp) | 
					
						
							|  |  |  | 		sysfs_remove_group(&mk->kobj, &mk->mp->grp); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-10-22 10:00:22 -05:00
										 |  |  | 	/* These should not fail at boot. */ | 
					
						
							|  |  |  | 	err = add_sysfs_param(mk, kparam, kparam->name + name_skip); | 
					
						
							|  |  |  | 	BUG_ON(err); | 
					
						
							|  |  |  | 	err = sysfs_create_group(&mk->kobj, &mk->mp->grp); | 
					
						
							|  |  |  | 	BUG_ON(err); | 
					
						
							| 
									
										
										
										
											2007-01-15 20:22:02 +01:00
										 |  |  | 	kobject_uevent(&mk->kobj, KOBJ_ADD); | 
					
						
							| 
									
										
										
										
											2008-10-22 10:00:22 -05:00
										 |  |  | 	kobject_put(&mk->kobj); | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /*
 | 
					
						
							| 
									
										
										
										
											2013-07-02 15:35:11 +09:30
										 |  |  |  * param_sysfs_builtin - add sysfs parameters for built-in modules | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  |  * | 
					
						
							|  |  |  |  * Add module_parameters to sysfs for "modules" built into the kernel. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * The "module" name (KBUILD_MODNAME) is stored before a dot, the | 
					
						
							|  |  |  |  * "parameter" name is stored behind a dot in kernel_param->name. So, | 
					
						
							|  |  |  |  * extract the "module" name for all built-in kernel_param-eters, | 
					
						
							| 
									
										
										
										
											2008-10-22 10:00:22 -05:00
										 |  |  |  * and for all who have the same, call kernel_add_sysfs_param. | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  |  */ | 
					
						
							|  |  |  | static void __init param_sysfs_builtin(void) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2014-10-13 15:55:44 -07:00
										 |  |  | 	const struct kernel_param *kp; | 
					
						
							| 
									
										
										
										
											2008-10-22 10:00:22 -05:00
										 |  |  | 	unsigned int name_len; | 
					
						
							|  |  |  | 	char modname[MODULE_NAME_LEN]; | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-10-22 10:00:22 -05:00
										 |  |  | 	for (kp = __start___param; kp < __stop___param; kp++) { | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 		char *dot; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-10-22 10:00:22 -05:00
										 |  |  | 		if (kp->perm == 0) | 
					
						
							|  |  |  | 			continue; | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-10-22 10:00:22 -05:00
										 |  |  | 		dot = strchr(kp->name, '.'); | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 		if (!dot) { | 
					
						
							| 
									
										
										
										
											2008-10-22 10:00:23 -05:00
										 |  |  | 			/* This happens for core_param() */ | 
					
						
							|  |  |  | 			strcpy(modname, "kernel"); | 
					
						
							|  |  |  | 			name_len = 0; | 
					
						
							|  |  |  | 		} else { | 
					
						
							|  |  |  | 			name_len = dot - kp->name + 1; | 
					
						
							|  |  |  | 			strlcpy(modname, kp->name, name_len); | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2008-10-22 10:00:23 -05:00
										 |  |  | 		kernel_add_sysfs_param(modname, kp, name_len); | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-12-15 14:00:19 -08:00
										 |  |  | ssize_t __modver_version_show(struct module_attribute *mattr, | 
					
						
							| 
									
										
										
										
											2011-07-24 22:06:04 +09:30
										 |  |  | 			      struct module_kobject *mk, char *buf) | 
					
						
							| 
									
										
										
										
											2010-12-15 14:00:19 -08:00
										 |  |  | { | 
					
						
							|  |  |  | 	struct module_version_attribute *vattr = | 
					
						
							|  |  |  | 		container_of(mattr, struct module_version_attribute, mattr); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-08-20 15:35:04 +09:30
										 |  |  | 	return scnprintf(buf, PAGE_SIZE, "%s\n", vattr->version); | 
					
						
							| 
									
										
										
										
											2010-12-15 14:00:19 -08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-02-07 16:02:25 -08:00
										 |  |  | extern const struct module_version_attribute *__start___modver[]; | 
					
						
							|  |  |  | extern const struct module_version_attribute *__stop___modver[]; | 
					
						
							| 
									
										
										
										
											2010-12-15 14:00:19 -08:00
										 |  |  | 
 | 
					
						
							|  |  |  | static void __init version_sysfs_builtin(void) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2011-02-07 16:02:25 -08:00
										 |  |  | 	const struct module_version_attribute **p; | 
					
						
							| 
									
										
										
										
											2010-12-15 14:00:19 -08:00
										 |  |  | 	struct module_kobject *mk; | 
					
						
							|  |  |  | 	int err; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-02-07 16:02:25 -08:00
										 |  |  | 	for (p = __start___modver; p < __stop___modver; p++) { | 
					
						
							|  |  |  | 		const struct module_version_attribute *vattr = *p; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-12-15 14:00:19 -08:00
										 |  |  | 		mk = locate_module_kobject(vattr->module_name); | 
					
						
							|  |  |  | 		if (mk) { | 
					
						
							|  |  |  | 			err = sysfs_create_file(&mk->kobj, &vattr->mattr.attr); | 
					
						
							|  |  |  | 			kobject_uevent(&mk->kobj, KOBJ_ADD); | 
					
						
							|  |  |  | 			kobject_put(&mk->kobj); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  | /* module-related sysfs stuff */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static ssize_t module_attr_show(struct kobject *kobj, | 
					
						
							|  |  |  | 				struct attribute *attr, | 
					
						
							|  |  |  | 				char *buf) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	struct module_attribute *attribute; | 
					
						
							|  |  |  | 	struct module_kobject *mk; | 
					
						
							|  |  |  | 	int ret; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	attribute = to_module_attr(attr); | 
					
						
							|  |  |  | 	mk = to_module_kobject(kobj); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (!attribute->show) | 
					
						
							| 
									
										
										
										
											2005-04-29 01:27:34 -05:00
										 |  |  | 		return -EIO; | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-07-24 22:06:04 +09:30
										 |  |  | 	ret = attribute->show(attribute, mk, buf); | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	return ret; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static ssize_t module_attr_store(struct kobject *kobj, | 
					
						
							|  |  |  | 				struct attribute *attr, | 
					
						
							|  |  |  | 				const char *buf, size_t len) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	struct module_attribute *attribute; | 
					
						
							|  |  |  | 	struct module_kobject *mk; | 
					
						
							|  |  |  | 	int ret; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	attribute = to_module_attr(attr); | 
					
						
							|  |  |  | 	mk = to_module_kobject(kobj); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (!attribute->store) | 
					
						
							| 
									
										
										
										
											2005-04-29 01:27:34 -05:00
										 |  |  | 		return -EIO; | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-07-24 22:06:04 +09:30
										 |  |  | 	ret = attribute->store(attribute, mk, buf, len); | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	return ret; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-01-19 02:58:23 +01:00
										 |  |  | static const struct sysfs_ops module_sysfs_ops = { | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 	.show = module_attr_show, | 
					
						
							|  |  |  | 	.store = module_attr_store, | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-01-18 13:26:15 +01:00
										 |  |  | static int uevent_filter(struct kset *kset, struct kobject *kobj) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	struct kobj_type *ktype = get_ktype(kobj); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (ktype == &module_ktype) | 
					
						
							|  |  |  | 		return 1; | 
					
						
							|  |  |  | 	return 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-12-31 14:52:51 +01:00
										 |  |  | static const struct kset_uevent_ops module_uevent_ops = { | 
					
						
							| 
									
										
										
										
											2007-01-18 13:26:15 +01:00
										 |  |  | 	.filter = uevent_filter, | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-11-01 10:39:50 -07:00
										 |  |  | struct kset *module_kset; | 
					
						
							| 
									
										
										
										
											2007-04-13 13:15:19 -07:00
										 |  |  | int module_sysfs_initialized; | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-09-03 16:33:57 +09:30
										 |  |  | static void module_kobj_release(struct kobject *kobj) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	struct module_kobject *mk = to_module_kobject(kobj); | 
					
						
							|  |  |  | 	complete(mk->kobj_completion); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-11-01 10:39:50 -07:00
										 |  |  | struct kobj_type module_ktype = { | 
					
						
							| 
									
										
										
										
											2013-09-03 16:33:57 +09:30
										 |  |  | 	.release   =	module_kobj_release, | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 	.sysfs_ops =	&module_sysfs_ops, | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /*
 | 
					
						
							|  |  |  |  * param_sysfs_init - wrapper for built-in params support | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | static int __init param_sysfs_init(void) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2007-11-01 10:39:50 -07:00
										 |  |  | 	module_kset = kset_create_and_add("module", &module_uevent_ops, NULL); | 
					
						
							|  |  |  | 	if (!module_kset) { | 
					
						
							|  |  |  | 		printk(KERN_WARNING "%s (%d): error creating kset\n", | 
					
						
							|  |  |  | 			__FILE__, __LINE__); | 
					
						
							|  |  |  | 		return -ENOMEM; | 
					
						
							| 
									
										
										
										
											2006-09-29 01:58:55 -07:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2007-04-13 13:15:19 -07:00
										 |  |  | 	module_sysfs_initialized = 1; | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-12-15 14:00:19 -08:00
										 |  |  | 	version_sysfs_builtin(); | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 	param_sysfs_builtin(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return 0; | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2006-09-29 01:59:34 -07:00
										 |  |  | subsys_initcall(param_sysfs_init); | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-11-01 10:39:50 -07:00
										 |  |  | #endif /* CONFIG_SYSFS */
 |