diff options
30 files changed, 658 insertions, 253 deletions
diff --git a/Documentation/cpu-hotplug.txt b/Documentation/cpu-hotplug.txt index a99d7031cdf9..45d5a217484f 100644 --- a/Documentation/cpu-hotplug.txt +++ b/Documentation/cpu-hotplug.txt | |||
@@ -2,7 +2,7 @@ | |||
2 | 2 | ||
3 | Maintainers: | 3 | Maintainers: |
4 | CPU Hotplug Core: | 4 | CPU Hotplug Core: |
5 | Rusty Russell <rusty@rustycorp.com.au> | 5 | Rusty Russell <rusty@rustcorp.com.au> |
6 | Srivatsa Vaddagiri <vatsa@in.ibm.com> | 6 | Srivatsa Vaddagiri <vatsa@in.ibm.com> |
7 | i386: | 7 | i386: |
8 | Zwane Mwaikambo <zwane@arm.linux.org.uk> | 8 | Zwane Mwaikambo <zwane@arm.linux.org.uk> |
diff --git a/arch/um/drivers/hostaudio_kern.c b/arch/um/drivers/hostaudio_kern.c index 68142df76608..0c46e398cd8f 100644 --- a/arch/um/drivers/hostaudio_kern.c +++ b/arch/um/drivers/hostaudio_kern.c | |||
@@ -187,7 +187,9 @@ static int hostaudio_open(struct inode *inode, struct file *file) | |||
187 | int ret; | 187 | int ret; |
188 | 188 | ||
189 | #ifdef DEBUG | 189 | #ifdef DEBUG |
190 | kparam_block_sysfs_write(dsp); | ||
190 | printk(KERN_DEBUG "hostaudio: open called (host: %s)\n", dsp); | 191 | printk(KERN_DEBUG "hostaudio: open called (host: %s)\n", dsp); |
192 | kparam_unblock_sysfs_write(dsp); | ||
191 | #endif | 193 | #endif |
192 | 194 | ||
193 | state = kmalloc(sizeof(struct hostaudio_state), GFP_KERNEL); | 195 | state = kmalloc(sizeof(struct hostaudio_state), GFP_KERNEL); |
@@ -199,9 +201,11 @@ static int hostaudio_open(struct inode *inode, struct file *file) | |||
199 | if (file->f_mode & FMODE_WRITE) | 201 | if (file->f_mode & FMODE_WRITE) |
200 | w = 1; | 202 | w = 1; |
201 | 203 | ||
204 | kparam_block_sysfs_write(dsp); | ||
202 | lock_kernel(); | 205 | lock_kernel(); |
203 | ret = os_open_file(dsp, of_set_rw(OPENFLAGS(), r, w), 0); | 206 | ret = os_open_file(dsp, of_set_rw(OPENFLAGS(), r, w), 0); |
204 | unlock_kernel(); | 207 | unlock_kernel(); |
208 | kparam_unblock_sysfs_write(dsp); | ||
205 | 209 | ||
206 | if (ret < 0) { | 210 | if (ret < 0) { |
207 | kfree(state); | 211 | kfree(state); |
@@ -258,13 +262,17 @@ static int hostmixer_open_mixdev(struct inode *inode, struct file *file) | |||
258 | if (file->f_mode & FMODE_WRITE) | 262 | if (file->f_mode & FMODE_WRITE) |
259 | w = 1; | 263 | w = 1; |
260 | 264 | ||
265 | kparam_block_sysfs_write(mixer); | ||
261 | lock_kernel(); | 266 | lock_kernel(); |
262 | ret = os_open_file(mixer, of_set_rw(OPENFLAGS(), r, w), 0); | 267 | ret = os_open_file(mixer, of_set_rw(OPENFLAGS(), r, w), 0); |
263 | unlock_kernel(); | 268 | unlock_kernel(); |
269 | kparam_unblock_sysfs_write(mixer); | ||
264 | 270 | ||
265 | if (ret < 0) { | 271 | if (ret < 0) { |
272 | kparam_block_sysfs_write(dsp); | ||
266 | printk(KERN_ERR "hostaudio_open_mixdev failed to open '%s', " | 273 | printk(KERN_ERR "hostaudio_open_mixdev failed to open '%s', " |
267 | "err = %d\n", dsp, -ret); | 274 | "err = %d\n", dsp, -ret); |
275 | kparam_unblock_sysfs_write(dsp); | ||
268 | kfree(state); | 276 | kfree(state); |
269 | return ret; | 277 | return ret; |
270 | } | 278 | } |
@@ -320,8 +328,10 @@ MODULE_LICENSE("GPL"); | |||
320 | 328 | ||
321 | static int __init hostaudio_init_module(void) | 329 | static int __init hostaudio_init_module(void) |
322 | { | 330 | { |
331 | __kernel_param_lock(); | ||
323 | printk(KERN_INFO "UML Audio Relay (host dsp = %s, host mixer = %s)\n", | 332 | printk(KERN_INFO "UML Audio Relay (host dsp = %s, host mixer = %s)\n", |
324 | dsp, mixer); | 333 | dsp, mixer); |
334 | __kernel_param_unlock(); | ||
325 | 335 | ||
326 | module_data.dev_audio = register_sound_dsp(&hostaudio_fops, -1); | 336 | module_data.dev_audio = register_sound_dsp(&hostaudio_fops, -1); |
327 | if (module_data.dev_audio < 0) { | 337 | if (module_data.dev_audio < 0) { |
diff --git a/drivers/acpi/debug.c b/drivers/acpi/debug.c index 146135e7a6a1..295dbfa2db9c 100644 --- a/drivers/acpi/debug.c +++ b/drivers/acpi/debug.c | |||
@@ -96,7 +96,8 @@ static const struct acpi_dlevel acpi_debug_levels[] = { | |||
96 | /* -------------------------------------------------------------------------- | 96 | /* -------------------------------------------------------------------------- |
97 | FS Interface (/sys) | 97 | FS Interface (/sys) |
98 | -------------------------------------------------------------------------- */ | 98 | -------------------------------------------------------------------------- */ |
99 | static int param_get_debug_layer(char *buffer, struct kernel_param *kp) { | 99 | static int param_get_debug_layer(char *buffer, const struct kernel_param *kp) |
100 | { | ||
100 | int result = 0; | 101 | int result = 0; |
101 | int i; | 102 | int i; |
102 | 103 | ||
@@ -118,7 +119,8 @@ static int param_get_debug_layer(char *buffer, struct kernel_param *kp) { | |||
118 | return result; | 119 | return result; |
119 | } | 120 | } |
120 | 121 | ||
121 | static int param_get_debug_level(char *buffer, struct kernel_param *kp) { | 122 | static int param_get_debug_level(char *buffer, const struct kernel_param *kp) |
123 | { | ||
122 | int result = 0; | 124 | int result = 0; |
123 | int i; | 125 | int i; |
124 | 126 | ||
@@ -137,8 +139,18 @@ static int param_get_debug_level(char *buffer, struct kernel_param *kp) { | |||
137 | return result; | 139 | return result; |
138 | } | 140 | } |
139 | 141 | ||
140 | module_param_call(debug_layer, param_set_uint, param_get_debug_layer, &acpi_dbg_layer, 0644); | 142 | static struct kernel_param_ops acpi_debug_layer_ops = { |
141 | module_param_call(debug_level, param_set_uint, param_get_debug_level, &acpi_dbg_level, 0644); | 143 | .set = param_set_uint, |
144 | .get = param_get_debug_layer, | ||
145 | }; | ||
146 | |||
147 | static struct kernel_param_ops acpi_debug_level_ops = { | ||
148 | .set = param_set_uint, | ||
149 | .get = param_get_debug_level, | ||
150 | }; | ||
151 | |||
152 | module_param_cb(debug_layer, &acpi_debug_layer_ops, &acpi_dbg_layer, 0644); | ||
153 | module_param_cb(debug_level, &acpi_debug_level_ops, &acpi_dbg_level, 0644); | ||
142 | 154 | ||
143 | static char trace_method_name[6]; | 155 | static char trace_method_name[6]; |
144 | module_param_string(trace_method_name, trace_method_name, 6, 0644); | 156 | module_param_string(trace_method_name, trace_method_name, 6, 0644); |
@@ -147,7 +159,7 @@ module_param(trace_debug_layer, uint, 0644); | |||
147 | static unsigned int trace_debug_level; | 159 | static unsigned int trace_debug_level; |
148 | module_param(trace_debug_level, uint, 0644); | 160 | module_param(trace_debug_level, uint, 0644); |
149 | 161 | ||
150 | static int param_set_trace_state(const char *val, struct kernel_param *kp) | 162 | static int param_set_trace_state(const char *val, const struct kernel_param *kp) |
151 | { | 163 | { |
152 | int result = 0; | 164 | int result = 0; |
153 | 165 | ||
@@ -181,7 +193,7 @@ exit: | |||
181 | return result; | 193 | return result; |
182 | } | 194 | } |
183 | 195 | ||
184 | static int param_get_trace_state(char *buffer, struct kernel_param *kp) | 196 | static int param_get_trace_state(char *buffer, const struct kernel_param *kp) |
185 | { | 197 | { |
186 | if (!acpi_gbl_trace_method_name) | 198 | if (!acpi_gbl_trace_method_name) |
187 | return sprintf(buffer, "disable"); | 199 | return sprintf(buffer, "disable"); |
@@ -194,8 +206,12 @@ static int param_get_trace_state(char *buffer, struct kernel_param *kp) | |||
194 | return 0; | 206 | return 0; |
195 | } | 207 | } |
196 | 208 | ||
197 | module_param_call(trace_state, param_set_trace_state, param_get_trace_state, | 209 | static struct kernel_param_ops param_ops_trace_state = { |
198 | NULL, 0644); | 210 | .set = param_set_trace_state, |
211 | .get = param_get_trace_state, | ||
212 | }; | ||
213 | |||
214 | module_param_cb(trace_state, ¶m_ops_trace_state, NULL, 0644); | ||
199 | 215 | ||
200 | /* -------------------------------------------------------------------------- | 216 | /* -------------------------------------------------------------------------- |
201 | DebugFS Interface | 217 | DebugFS Interface |
diff --git a/drivers/char/hvc_iucv.c b/drivers/char/hvc_iucv.c index 5a80ad68ef22..7b01bc609de3 100644 --- a/drivers/char/hvc_iucv.c +++ b/drivers/char/hvc_iucv.c | |||
@@ -1149,7 +1149,7 @@ out_err: | |||
1149 | * Note: If it is called early in the boot process, @val is stored and | 1149 | * Note: If it is called early in the boot process, @val is stored and |
1150 | * parsed later in hvc_iucv_init(). | 1150 | * parsed later in hvc_iucv_init(). |
1151 | */ | 1151 | */ |
1152 | static int param_set_vmidfilter(const char *val, struct kernel_param *kp) | 1152 | static int param_set_vmidfilter(const char *val, const struct kernel_param *kp) |
1153 | { | 1153 | { |
1154 | int rc; | 1154 | int rc; |
1155 | 1155 | ||
@@ -1176,7 +1176,7 @@ static int param_set_vmidfilter(const char *val, struct kernel_param *kp) | |||
1176 | * The function stores the filter as a comma-separated list of z/VM user IDs | 1176 | * The function stores the filter as a comma-separated list of z/VM user IDs |
1177 | * in @buffer. Typically, sysfs routines call this function for attr show. | 1177 | * in @buffer. Typically, sysfs routines call this function for attr show. |
1178 | */ | 1178 | */ |
1179 | static int param_get_vmidfilter(char *buffer, struct kernel_param *kp) | 1179 | static int param_get_vmidfilter(char *buffer, const struct kernel_param *kp) |
1180 | { | 1180 | { |
1181 | int rc; | 1181 | int rc; |
1182 | size_t index, len; | 1182 | size_t index, len; |
@@ -1203,6 +1203,11 @@ static int param_get_vmidfilter(char *buffer, struct kernel_param *kp) | |||
1203 | 1203 | ||
1204 | #define param_check_vmidfilter(name, p) __param_check(name, p, void) | 1204 | #define param_check_vmidfilter(name, p) __param_check(name, p, void) |
1205 | 1205 | ||
1206 | static struct kernel_param_ops param_ops_vmidfilter = { | ||
1207 | .set = param_set_vmidfilter, | ||
1208 | .get = param_get_vmidfilter, | ||
1209 | }; | ||
1210 | |||
1206 | /** | 1211 | /** |
1207 | * hvc_iucv_init() - z/VM IUCV HVC device driver initialization | 1212 | * hvc_iucv_init() - z/VM IUCV HVC device driver initialization |
1208 | */ | 1213 | */ |
diff --git a/drivers/char/ipmi/ipmi_watchdog.c b/drivers/char/ipmi/ipmi_watchdog.c index 82bcdb262a3a..654d566ca57c 100644 --- a/drivers/char/ipmi/ipmi_watchdog.c +++ b/drivers/char/ipmi/ipmi_watchdog.c | |||
@@ -196,7 +196,7 @@ static void ipmi_unregister_watchdog(int ipmi_intf); | |||
196 | */ | 196 | */ |
197 | static int start_now; | 197 | static int start_now; |
198 | 198 | ||
199 | static int set_param_int(const char *val, struct kernel_param *kp) | 199 | static int set_param_timeout(const char *val, const struct kernel_param *kp) |
200 | { | 200 | { |
201 | char *endp; | 201 | char *endp; |
202 | int l; | 202 | int l; |
@@ -215,10 +215,11 @@ static int set_param_int(const char *val, struct kernel_param *kp) | |||
215 | return rv; | 215 | return rv; |
216 | } | 216 | } |
217 | 217 | ||
218 | static int get_param_int(char *buffer, struct kernel_param *kp) | 218 | static struct kernel_param_ops param_ops_timeout = { |
219 | { | 219 | .set = set_param_timeout, |
220 | return sprintf(buffer, "%i", *((int *)kp->arg)); | 220 | .get = param_get_int, |
221 | } | 221 | }; |
222 | #define param_check_timeout param_check_int | ||
222 | 223 | ||
223 | typedef int (*action_fn)(const char *intval, char *outval); | 224 | typedef int (*action_fn)(const char *intval, char *outval); |
224 | 225 | ||
@@ -227,7 +228,7 @@ static int preaction_op(const char *inval, char *outval); | |||
227 | static int preop_op(const char *inval, char *outval); | 228 | static int preop_op(const char *inval, char *outval); |
228 | static void check_parms(void); | 229 | static void check_parms(void); |
229 | 230 | ||
230 | static int set_param_str(const char *val, struct kernel_param *kp) | 231 | static int set_param_str(const char *val, const struct kernel_param *kp) |
231 | { | 232 | { |
232 | action_fn fn = (action_fn) kp->arg; | 233 | action_fn fn = (action_fn) kp->arg; |
233 | int rv = 0; | 234 | int rv = 0; |
@@ -251,7 +252,7 @@ static int set_param_str(const char *val, struct kernel_param *kp) | |||
251 | return rv; | 252 | return rv; |
252 | } | 253 | } |
253 | 254 | ||
254 | static int get_param_str(char *buffer, struct kernel_param *kp) | 255 | static int get_param_str(char *buffer, const struct kernel_param *kp) |
255 | { | 256 | { |
256 | action_fn fn = (action_fn) kp->arg; | 257 | action_fn fn = (action_fn) kp->arg; |
257 | int rv; | 258 | int rv; |
@@ -263,7 +264,7 @@ static int get_param_str(char *buffer, struct kernel_param *kp) | |||
263 | } | 264 | } |
264 | 265 | ||
265 | 266 | ||
266 | static int set_param_wdog_ifnum(const char *val, struct kernel_param *kp) | 267 | static int set_param_wdog_ifnum(const char *val, const struct kernel_param *kp) |
267 | { | 268 | { |
268 | int rv = param_set_int(val, kp); | 269 | int rv = param_set_int(val, kp); |
269 | if (rv) | 270 | if (rv) |
@@ -276,27 +277,38 @@ static int set_param_wdog_ifnum(const char *val, struct kernel_param *kp) | |||
276 | return 0; | 277 | return 0; |
277 | } | 278 | } |
278 | 279 | ||
279 | module_param_call(ifnum_to_use, set_param_wdog_ifnum, get_param_int, | 280 | static struct kernel_param_ops param_ops_wdog_ifnum = { |
280 | &ifnum_to_use, 0644); | 281 | .set = set_param_wdog_ifnum, |
282 | .get = param_get_int, | ||
283 | }; | ||
284 | |||
285 | #define param_check_wdog_ifnum param_check_int | ||
286 | |||
287 | static struct kernel_param_ops param_ops_str = { | ||
288 | .set = set_param_str, | ||
289 | .get = get_param_str, | ||
290 | }; | ||
291 | |||
292 | module_param(ifnum_to_use, wdog_ifnum, 0644); | ||
281 | MODULE_PARM_DESC(ifnum_to_use, "The interface number to use for the watchdog " | 293 | MODULE_PARM_DESC(ifnum_to_use, "The interface number to use for the watchdog " |
282 | "timer. Setting to -1 defaults to the first registered " | 294 | "timer. Setting to -1 defaults to the first registered " |
283 | "interface"); | 295 | "interface"); |
284 | 296 | ||
285 | module_param_call(timeout, set_param_int, get_param_int, &timeout, 0644); | 297 | module_param(timeout, timeout, 0644); |
286 | MODULE_PARM_DESC(timeout, "Timeout value in seconds."); | 298 | MODULE_PARM_DESC(timeout, "Timeout value in seconds."); |
287 | 299 | ||
288 | module_param_call(pretimeout, set_param_int, get_param_int, &pretimeout, 0644); | 300 | module_param(pretimeout, timeout, 0644); |
289 | MODULE_PARM_DESC(pretimeout, "Pretimeout value in seconds."); | 301 | MODULE_PARM_DESC(pretimeout, "Pretimeout value in seconds."); |
290 | 302 | ||
291 | module_param_call(action, set_param_str, get_param_str, action_op, 0644); | 303 | module_param_cb(action, ¶m_ops_str, action_op, 0644); |
292 | MODULE_PARM_DESC(action, "Timeout action. One of: " | 304 | MODULE_PARM_DESC(action, "Timeout action. One of: " |
293 | "reset, none, power_cycle, power_off."); | 305 | "reset, none, power_cycle, power_off."); |
294 | 306 | ||
295 | module_param_call(preaction, set_param_str, get_param_str, preaction_op, 0644); | 307 | module_param_cb(preaction, ¶m_ops_str, preaction_op, 0644); |
296 | MODULE_PARM_DESC(preaction, "Pretimeout action. One of: " | 308 | MODULE_PARM_DESC(preaction, "Pretimeout action. One of: " |
297 | "pre_none, pre_smi, pre_nmi, pre_int."); | 309 | "pre_none, pre_smi, pre_nmi, pre_int."); |
298 | 310 | ||
299 | module_param_call(preop, set_param_str, get_param_str, preop_op, 0644); | 311 | module_param_cb(preop, ¶m_ops_str, preop_op, 0644); |
300 | MODULE_PARM_DESC(preop, "Pretimeout driver operation. One of: " | 312 | MODULE_PARM_DESC(preop, "Pretimeout driver operation. One of: " |
301 | "preop_none, preop_panic, preop_give_data."); | 313 | "preop_none, preop_panic, preop_give_data."); |
302 | 314 | ||
diff --git a/drivers/ide/ide.c b/drivers/ide/ide.c index 3cb9c4e056ff..fa896210ed7b 100644 --- a/drivers/ide/ide.c +++ b/drivers/ide/ide.c | |||
@@ -177,7 +177,7 @@ EXPORT_SYMBOL_GPL(ide_pci_clk); | |||
177 | module_param_named(pci_clock, ide_pci_clk, int, 0); | 177 | module_param_named(pci_clock, ide_pci_clk, int, 0); |
178 | MODULE_PARM_DESC(pci_clock, "PCI bus clock frequency (in MHz)"); | 178 | MODULE_PARM_DESC(pci_clock, "PCI bus clock frequency (in MHz)"); |
179 | 179 | ||
180 | static int ide_set_dev_param_mask(const char *s, struct kernel_param *kp) | 180 | static int ide_set_dev_param_mask(const char *s, const struct kernel_param *kp) |
181 | { | 181 | { |
182 | int a, b, i, j = 1; | 182 | int a, b, i, j = 1; |
183 | unsigned int *dev_param_mask = (unsigned int *)kp->arg; | 183 | unsigned int *dev_param_mask = (unsigned int *)kp->arg; |
@@ -200,34 +200,40 @@ static int ide_set_dev_param_mask(const char *s, struct kernel_param *kp) | |||
200 | return 0; | 200 | return 0; |
201 | } | 201 | } |
202 | 202 | ||
203 | static struct kernel_param_ops param_ops_ide_dev_mask = { | ||
204 | .set = ide_set_dev_param_mask | ||
205 | }; | ||
206 | |||
207 | #define param_check_ide_dev_mask(name, p) param_check_uint(name, p) | ||
208 | |||
203 | static unsigned int ide_nodma; | 209 | static unsigned int ide_nodma; |
204 | 210 | ||
205 | module_param_call(nodma, ide_set_dev_param_mask, NULL, &ide_nodma, 0); | 211 | module_param_named(nodma, ide_nodma, ide_dev_mask, 0); |
206 | MODULE_PARM_DESC(nodma, "disallow DMA for a device"); | 212 | MODULE_PARM_DESC(nodma, "disallow DMA for a device"); |
207 | 213 | ||
208 | static unsigned int ide_noflush; | 214 | static unsigned int ide_noflush; |
209 | 215 | ||
210 | module_param_call(noflush, ide_set_dev_param_mask, NULL, &ide_noflush, 0); | 216 | module_param_named(noflush, ide_noflush, ide_dev_mask, 0); |
211 | MODULE_PARM_DESC(noflush, "disable flush requests for a device"); | 217 | MODULE_PARM_DESC(noflush, "disable flush requests for a device"); |
212 | 218 | ||
213 | static unsigned int ide_nohpa; | 219 | static unsigned int ide_nohpa; |
214 | 220 | ||
215 | module_param_call(nohpa, ide_set_dev_param_mask, NULL, &ide_nohpa, 0); | 221 | module_param_named(nohpa, ide_nohpa, ide_dev_mask, 0); |
216 | MODULE_PARM_DESC(nohpa, "disable Host Protected Area for a device"); | 222 | MODULE_PARM_DESC(nohpa, "disable Host Protected Area for a device"); |
217 | 223 | ||
218 | static unsigned int ide_noprobe; | 224 | static unsigned int ide_noprobe; |
219 | 225 | ||
220 | module_param_call(noprobe, ide_set_dev_param_mask, NULL, &ide_noprobe, 0); | 226 | module_param_named(noprobe, ide_noprobe, ide_dev_mask, 0); |
221 | MODULE_PARM_DESC(noprobe, "skip probing for a device"); | 227 | MODULE_PARM_DESC(noprobe, "skip probing for a device"); |
222 | 228 | ||
223 | static unsigned int ide_nowerr; | 229 | static unsigned int ide_nowerr; |
224 | 230 | ||
225 | module_param_call(nowerr, ide_set_dev_param_mask, NULL, &ide_nowerr, 0); | 231 | module_param_named(nowerr, ide_nowerr, ide_dev_mask, 0); |
226 | MODULE_PARM_DESC(nowerr, "ignore the ATA_DF bit for a device"); | 232 | MODULE_PARM_DESC(nowerr, "ignore the ATA_DF bit for a device"); |
227 | 233 | ||
228 | static unsigned int ide_cdroms; | 234 | static unsigned int ide_cdroms; |
229 | 235 | ||
230 | module_param_call(cdrom, ide_set_dev_param_mask, NULL, &ide_cdroms, 0); | 236 | module_param_named(cdrom, ide_cdroms, ide_dev_mask, 0); |
231 | MODULE_PARM_DESC(cdrom, "force device as a CD-ROM"); | 237 | MODULE_PARM_DESC(cdrom, "force device as a CD-ROM"); |
232 | 238 | ||
233 | struct chs_geom { | 239 | struct chs_geom { |
diff --git a/drivers/input/misc/ati_remote2.c b/drivers/input/misc/ati_remote2.c index e148749b5851..23257652b8e8 100644 --- a/drivers/input/misc/ati_remote2.c +++ b/drivers/input/misc/ati_remote2.c | |||
@@ -38,7 +38,8 @@ enum { | |||
38 | }; | 38 | }; |
39 | 39 | ||
40 | static int ati_remote2_set_mask(const char *val, | 40 | static int ati_remote2_set_mask(const char *val, |
41 | struct kernel_param *kp, unsigned int max) | 41 | const struct kernel_param *kp, |
42 | unsigned int max) | ||
42 | { | 43 | { |
43 | unsigned long mask; | 44 | unsigned long mask; |
44 | int ret; | 45 | int ret; |
@@ -59,28 +60,31 @@ static int ati_remote2_set_mask(const char *val, | |||
59 | } | 60 | } |
60 | 61 | ||
61 | static int ati_remote2_set_channel_mask(const char *val, | 62 | static int ati_remote2_set_channel_mask(const char *val, |
62 | struct kernel_param *kp) | 63 | const struct kernel_param *kp) |
63 | { | 64 | { |
64 | pr_debug("%s()\n", __func__); | 65 | pr_debug("%s()\n", __func__); |
65 | 66 | ||
66 | return ati_remote2_set_mask(val, kp, ATI_REMOTE2_MAX_CHANNEL_MASK); | 67 | return ati_remote2_set_mask(val, kp, ATI_REMOTE2_MAX_CHANNEL_MASK); |
67 | } | 68 | } |
68 | 69 | ||
69 | static int ati_remote2_get_channel_mask(char *buffer, struct kernel_param *kp) | 70 | static int ati_remote2_get_channel_mask(char *buffer, |
71 | const struct kernel_param *kp) | ||
70 | { | 72 | { |
71 | pr_debug("%s()\n", __func__); | 73 | pr_debug("%s()\n", __func__); |
72 | 74 | ||
73 | return sprintf(buffer, "0x%04x", *(unsigned int *)kp->arg); | 75 | return sprintf(buffer, "0x%04x", *(unsigned int *)kp->arg); |
74 | } | 76 | } |
75 | 77 | ||
76 | static int ati_remote2_set_mode_mask(const char *val, struct kernel_param *kp) | 78 | static int ati_remote2_set_mode_mask(const char *val, |
79 | const struct kernel_param *kp) | ||
77 | { | 80 | { |
78 | pr_debug("%s()\n", __func__); | 81 | pr_debug("%s()\n", __func__); |
79 | 82 | ||
80 | return ati_remote2_set_mask(val, kp, ATI_REMOTE2_MAX_MODE_MASK); | 83 | return ati_remote2_set_mask(val, kp, ATI_REMOTE2_MAX_MODE_MASK); |
81 | } | 84 | } |
82 | 85 | ||
83 | static int ati_remote2_get_mode_mask(char *buffer, struct kernel_param *kp) | 86 | static int ati_remote2_get_mode_mask(char *buffer, |
87 | const struct kernel_param *kp) | ||
84 | { | 88 | { |
85 | pr_debug("%s()\n", __func__); | 89 | pr_debug("%s()\n", __func__); |
86 | 90 | ||
@@ -89,15 +93,19 @@ static int ati_remote2_get_mode_mask(char *buffer, struct kernel_param *kp) | |||
89 | 93 | ||
90 | static unsigned int channel_mask = ATI_REMOTE2_MAX_CHANNEL_MASK; | 94 | static unsigned int channel_mask = ATI_REMOTE2_MAX_CHANNEL_MASK; |
91 | #define param_check_channel_mask(name, p) __param_check(name, p, unsigned int) | 95 | #define param_check_channel_mask(name, p) __param_check(name, p, unsigned int) |
92 | #define param_set_channel_mask ati_remote2_set_channel_mask | 96 | static struct kernel_param_ops param_ops_channel_mask = { |
93 | #define param_get_channel_mask ati_remote2_get_channel_mask | 97 | .set = ati_remote2_set_channel_mask, |
98 | .get = ati_remote2_get_channel_mask, | ||
99 | }; | ||
94 | module_param(channel_mask, channel_mask, 0644); | 100 | module_param(channel_mask, channel_mask, 0644); |
95 | MODULE_PARM_DESC(channel_mask, "Bitmask of channels to accept <15:Channel16>...<1:Channel2><0:Channel1>"); | 101 | MODULE_PARM_DESC(channel_mask, "Bitmask of channels to accept <15:Channel16>...<1:Channel2><0:Channel1>"); |
96 | 102 | ||
97 | static unsigned int mode_mask = ATI_REMOTE2_MAX_MODE_MASK; | 103 | static unsigned int mode_mask = ATI_REMOTE2_MAX_MODE_MASK; |
98 | #define param_check_mode_mask(name, p) __param_check(name, p, unsigned int) | 104 | #define param_check_mode_mask(name, p) __param_check(name, p, unsigned int) |
99 | #define param_set_mode_mask ati_remote2_set_mode_mask | 105 | static struct kernel_param_ops param_ops_mode_mask = { |
100 | #define param_get_mode_mask ati_remote2_get_mode_mask | 106 | .set = ati_remote2_set_mode_mask, |
107 | .get = ati_remote2_get_mode_mask, | ||
108 | }; | ||
101 | module_param(mode_mask, mode_mask, 0644); | 109 | module_param(mode_mask, mode_mask, 0644); |
102 | MODULE_PARM_DESC(mode_mask, "Bitmask of modes to accept <4:PC><3:AUX4><2:AUX3><1:AUX2><0:AUX1>"); | 110 | MODULE_PARM_DESC(mode_mask, "Bitmask of modes to accept <4:PC><3:AUX4><2:AUX3><1:AUX2><0:AUX1>"); |
103 | 111 | ||
diff --git a/drivers/input/mouse/psmouse-base.c b/drivers/input/mouse/psmouse-base.c index 979c50215282..73a7af2542a8 100644 --- a/drivers/input/mouse/psmouse-base.c +++ b/drivers/input/mouse/psmouse-base.c | |||
@@ -39,11 +39,13 @@ MODULE_DESCRIPTION(DRIVER_DESC); | |||
39 | MODULE_LICENSE("GPL"); | 39 | MODULE_LICENSE("GPL"); |
40 | 40 | ||
41 | static unsigned int psmouse_max_proto = PSMOUSE_AUTO; | 41 | static unsigned int psmouse_max_proto = PSMOUSE_AUTO; |
42 | static int psmouse_set_maxproto(const char *val, struct kernel_param *kp); | 42 | static int psmouse_set_maxproto(const char *val, const struct kernel_param *); |
43 | static int psmouse_get_maxproto(char *buffer, struct kernel_param *kp); | 43 | static int psmouse_get_maxproto(char *buffer, const struct kernel_param *kp); |
44 | static struct kernel_param_ops param_ops_proto_abbrev = { | ||
45 | .set = psmouse_set_maxproto, | ||
46 | .get = psmouse_get_maxproto, | ||
47 | }; | ||
44 | #define param_check_proto_abbrev(name, p) __param_check(name, p, unsigned int) | 48 | #define param_check_proto_abbrev(name, p) __param_check(name, p, unsigned int) |
45 | #define param_set_proto_abbrev psmouse_set_maxproto | ||
46 | #define param_get_proto_abbrev psmouse_get_maxproto | ||
47 | module_param_named(proto, psmouse_max_proto, proto_abbrev, 0644); | 49 | module_param_named(proto, psmouse_max_proto, proto_abbrev, 0644); |
48 | MODULE_PARM_DESC(proto, "Highest protocol extension to probe (bare, imps, exps, any). Useful for KVM switches."); | 50 | MODULE_PARM_DESC(proto, "Highest protocol extension to probe (bare, imps, exps, any). Useful for KVM switches."); |
49 | 51 | ||
@@ -1679,7 +1681,7 @@ static ssize_t psmouse_attr_set_resolution(struct psmouse *psmouse, void *data, | |||
1679 | } | 1681 | } |
1680 | 1682 | ||
1681 | 1683 | ||
1682 | static int psmouse_set_maxproto(const char *val, struct kernel_param *kp) | 1684 | static int psmouse_set_maxproto(const char *val, const struct kernel_param *kp) |
1683 | { | 1685 | { |
1684 | const struct psmouse_protocol *proto; | 1686 | const struct psmouse_protocol *proto; |
1685 | 1687 | ||
@@ -1696,7 +1698,7 @@ static int psmouse_set_maxproto(const char *val, struct kernel_param *kp) | |||
1696 | return 0; | 1698 | return 0; |
1697 | } | 1699 | } |
1698 | 1700 | ||
1699 | static int psmouse_get_maxproto(char *buffer, struct kernel_param *kp) | 1701 | static int psmouse_get_maxproto(char *buffer, const struct kernel_param *kp) |
1700 | { | 1702 | { |
1701 | int type = *((unsigned int *)kp->arg); | 1703 | int type = *((unsigned int *)kp->arg); |
1702 | 1704 | ||
diff --git a/drivers/message/fusion/mptbase.c b/drivers/message/fusion/mptbase.c index c54674c482c7..b8f1719d7c02 100644 --- a/drivers/message/fusion/mptbase.c +++ b/drivers/message/fusion/mptbase.c | |||
@@ -110,8 +110,7 @@ MODULE_PARM_DESC(mpt_debug_level, " debug level - refer to mptdebug.h \ | |||
110 | 110 | ||
111 | int mpt_fwfault_debug; | 111 | int mpt_fwfault_debug; |
112 | EXPORT_SYMBOL(mpt_fwfault_debug); | 112 | EXPORT_SYMBOL(mpt_fwfault_debug); |
113 | module_param_call(mpt_fwfault_debug, param_set_int, param_get_int, | 113 | module_param(mpt_fwfault_debug, int, 0600); |
114 | &mpt_fwfault_debug, 0600); | ||
115 | MODULE_PARM_DESC(mpt_fwfault_debug, "Enable detection of Firmware fault" | 114 | MODULE_PARM_DESC(mpt_fwfault_debug, "Enable detection of Firmware fault" |
116 | " and halt Firmware on fault - (default=0)"); | 115 | " and halt Firmware on fault - (default=0)"); |
117 | 116 | ||
diff --git a/drivers/misc/lkdtm.c b/drivers/misc/lkdtm.c index 5bfb2a2041b8..ef34de7a8026 100644 --- a/drivers/misc/lkdtm.c +++ b/drivers/misc/lkdtm.c | |||
@@ -124,9 +124,9 @@ static int count = DEFAULT_COUNT; | |||
124 | module_param(recur_count, int, 0644); | 124 | module_param(recur_count, int, 0644); |
125 | MODULE_PARM_DESC(recur_count, " Recursion level for the stack overflow test, "\ | 125 | MODULE_PARM_DESC(recur_count, " Recursion level for the stack overflow test, "\ |
126 | "default is 10"); | 126 | "default is 10"); |
127 | module_param(cpoint_name, charp, 0644); | 127 | module_param(cpoint_name, charp, 0444); |
128 | MODULE_PARM_DESC(cpoint_name, " Crash Point, where kernel is to be crashed"); | 128 | MODULE_PARM_DESC(cpoint_name, " Crash Point, where kernel is to be crashed"); |
129 | module_param(cpoint_type, charp, 0644); | 129 | module_param(cpoint_type, charp, 0444); |
130 | MODULE_PARM_DESC(cpoint_type, " Crash Point Type, action to be taken on "\ | 130 | MODULE_PARM_DESC(cpoint_type, " Crash Point Type, action to be taken on "\ |
131 | "hitting the crash point"); | 131 | "hitting the crash point"); |
132 | module_param(cpoint_count, int, 0644); | 132 | module_param(cpoint_count, int, 0644); |
diff --git a/drivers/net/myri10ge/myri10ge.c b/drivers/net/myri10ge/myri10ge.c index d771d1650d60..fb2c0927d3cc 100644 --- a/drivers/net/myri10ge/myri10ge.c +++ b/drivers/net/myri10ge/myri10ge.c | |||
@@ -239,6 +239,7 @@ struct myri10ge_priv { | |||
239 | int watchdog_resets; | 239 | int watchdog_resets; |
240 | int watchdog_pause; | 240 | int watchdog_pause; |
241 | int pause; | 241 | int pause; |
242 | bool fw_name_allocated; | ||
242 | char *fw_name; | 243 | char *fw_name; |
243 | char eeprom_strings[MYRI10GE_EEPROM_STRINGS_SIZE]; | 244 | char eeprom_strings[MYRI10GE_EEPROM_STRINGS_SIZE]; |
244 | char *product_code_string; | 245 | char *product_code_string; |
@@ -271,6 +272,7 @@ MODULE_FIRMWARE("myri10ge_eth_z8e.dat"); | |||
271 | MODULE_FIRMWARE("myri10ge_rss_ethp_z8e.dat"); | 272 | MODULE_FIRMWARE("myri10ge_rss_ethp_z8e.dat"); |
272 | MODULE_FIRMWARE("myri10ge_rss_eth_z8e.dat"); | 273 | MODULE_FIRMWARE("myri10ge_rss_eth_z8e.dat"); |
273 | 274 | ||
275 | /* Careful: must be accessed under kparam_block_sysfs_write */ | ||
274 | static char *myri10ge_fw_name = NULL; | 276 | static char *myri10ge_fw_name = NULL; |
275 | module_param(myri10ge_fw_name, charp, S_IRUGO | S_IWUSR); | 277 | module_param(myri10ge_fw_name, charp, S_IRUGO | S_IWUSR); |
276 | MODULE_PARM_DESC(myri10ge_fw_name, "Firmware image name"); | 278 | MODULE_PARM_DESC(myri10ge_fw_name, "Firmware image name"); |
@@ -376,6 +378,14 @@ static inline void put_be32(__be32 val, __be32 __iomem * p) | |||
376 | 378 | ||
377 | static struct net_device_stats *myri10ge_get_stats(struct net_device *dev); | 379 | static struct net_device_stats *myri10ge_get_stats(struct net_device *dev); |
378 | 380 | ||
381 | static void set_fw_name(struct myri10ge_priv *mgp, char *name, bool allocated) | ||
382 | { | ||
383 | if (mgp->fw_name_allocated) | ||
384 | kfree(mgp->fw_name); | ||
385 | mgp->fw_name = name; | ||
386 | mgp->fw_name_allocated = allocated; | ||
387 | } | ||
388 | |||
379 | static int | 389 | static int |
380 | myri10ge_send_cmd(struct myri10ge_priv *mgp, u32 cmd, | 390 | myri10ge_send_cmd(struct myri10ge_priv *mgp, u32 cmd, |
381 | struct myri10ge_cmd *data, int atomic) | 391 | struct myri10ge_cmd *data, int atomic) |
@@ -747,7 +757,7 @@ static int myri10ge_load_firmware(struct myri10ge_priv *mgp, int adopt) | |||
747 | dev_warn(&mgp->pdev->dev, "via hotplug\n"); | 757 | dev_warn(&mgp->pdev->dev, "via hotplug\n"); |
748 | } | 758 | } |
749 | 759 | ||
750 | mgp->fw_name = "adopted"; | 760 | set_fw_name(mgp, "adopted", false); |
751 | mgp->tx_boundary = 2048; | 761 | mgp->tx_boundary = 2048; |
752 | myri10ge_dummy_rdma(mgp, 1); | 762 | myri10ge_dummy_rdma(mgp, 1); |
753 | status = myri10ge_get_firmware_capabilities(mgp); | 763 | status = myri10ge_get_firmware_capabilities(mgp); |
@@ -3233,7 +3243,7 @@ static void myri10ge_firmware_probe(struct myri10ge_priv *mgp) | |||
3233 | * load the optimized firmware (which assumes aligned PCIe | 3243 | * load the optimized firmware (which assumes aligned PCIe |
3234 | * completions) in order to see if it works on this host. | 3244 | * completions) in order to see if it works on this host. |
3235 | */ | 3245 | */ |
3236 | mgp->fw_name = myri10ge_fw_aligned; | 3246 | set_fw_name(mgp, myri10ge_fw_aligned, false); |
3237 | status = myri10ge_load_firmware(mgp, 1); | 3247 | status = myri10ge_load_firmware(mgp, 1); |
3238 | if (status != 0) { | 3248 | if (status != 0) { |
3239 | goto abort; | 3249 | goto abort; |
@@ -3261,7 +3271,7 @@ static void myri10ge_firmware_probe(struct myri10ge_priv *mgp) | |||
3261 | abort: | 3271 | abort: |
3262 | /* fall back to using the unaligned firmware */ | 3272 | /* fall back to using the unaligned firmware */ |
3263 | mgp->tx_boundary = 2048; | 3273 | mgp->tx_boundary = 2048; |
3264 | mgp->fw_name = myri10ge_fw_unaligned; | 3274 | set_fw_name(mgp, myri10ge_fw_unaligned, false); |
3265 | 3275 | ||
3266 | } | 3276 | } |
3267 | 3277 | ||
@@ -3284,7 +3294,7 @@ static void myri10ge_select_firmware(struct myri10ge_priv *mgp) | |||
3284 | dev_info(&mgp->pdev->dev, "PCIE x%d Link\n", | 3294 | dev_info(&mgp->pdev->dev, "PCIE x%d Link\n", |
3285 | link_width); | 3295 | link_width); |
3286 | mgp->tx_boundary = 4096; | 3296 | mgp->tx_boundary = 4096; |
3287 | mgp->fw_name = myri10ge_fw_aligned; | 3297 | set_fw_name(mgp, myri10ge_fw_aligned, false); |
3288 | } else { | 3298 | } else { |
3289 | myri10ge_firmware_probe(mgp); | 3299 | myri10ge_firmware_probe(mgp); |
3290 | } | 3300 | } |
@@ -3293,22 +3303,29 @@ static void myri10ge_select_firmware(struct myri10ge_priv *mgp) | |||
3293 | dev_info(&mgp->pdev->dev, | 3303 | dev_info(&mgp->pdev->dev, |
3294 | "Assuming aligned completions (forced)\n"); | 3304 | "Assuming aligned completions (forced)\n"); |
3295 | mgp->tx_boundary = 4096; | 3305 | mgp->tx_boundary = 4096; |
3296 | mgp->fw_name = myri10ge_fw_aligned; | 3306 | set_fw_name(mgp, myri10ge_fw_aligned, false); |
3297 | } else { | 3307 | } else { |
3298 | dev_info(&mgp->pdev->dev, | 3308 | dev_info(&mgp->pdev->dev, |
3299 | "Assuming unaligned completions (forced)\n"); | 3309 | "Assuming unaligned completions (forced)\n"); |
3300 | mgp->tx_boundary = 2048; | 3310 | mgp->tx_boundary = 2048; |
3301 | mgp->fw_name = myri10ge_fw_unaligned; | 3311 | set_fw_name(mgp, myri10ge_fw_unaligned, false); |
3302 | } | 3312 | } |
3303 | } | 3313 | } |
3314 | |||
3315 | kparam_block_sysfs_write(myri10ge_fw_name); | ||
3304 | if (myri10ge_fw_name != NULL) { | 3316 | if (myri10ge_fw_name != NULL) { |
3305 | overridden = 1; | 3317 | char *fw_name = kstrdup(myri10ge_fw_name, GFP_KERNEL); |
3306 | mgp->fw_name = myri10ge_fw_name; | 3318 | if (fw_name) { |
3319 | overridden = 1; | ||
3320 | set_fw_name(mgp, fw_name, true); | ||
3321 | } | ||
3307 | } | 3322 | } |
3323 | kparam_unblock_sysfs_write(myri10ge_fw_name); | ||
3324 | |||
3308 | if (mgp->board_number < MYRI10GE_MAX_BOARDS && | 3325 | if (mgp->board_number < MYRI10GE_MAX_BOARDS && |
3309 | myri10ge_fw_names[mgp->board_number] != NULL && | 3326 | myri10ge_fw_names[mgp->board_number] != NULL && |
3310 | strlen(myri10ge_fw_names[mgp->board_number])) { | 3327 | strlen(myri10ge_fw_names[mgp->board_number])) { |
3311 | mgp->fw_name = myri10ge_fw_names[mgp->board_number]; | 3328 | set_fw_name(mgp, myri10ge_fw_names[mgp->board_number], false); |
3312 | overridden = 1; | 3329 | overridden = 1; |
3313 | } | 3330 | } |
3314 | if (overridden) | 3331 | if (overridden) |
@@ -3660,6 +3677,7 @@ static void myri10ge_probe_slices(struct myri10ge_priv *mgp) | |||
3660 | struct myri10ge_cmd cmd; | 3677 | struct myri10ge_cmd cmd; |
3661 | struct pci_dev *pdev = mgp->pdev; | 3678 | struct pci_dev *pdev = mgp->pdev; |
3662 | char *old_fw; | 3679 | char *old_fw; |
3680 | bool old_allocated; | ||
3663 | int i, status, ncpus, msix_cap; | 3681 | int i, status, ncpus, msix_cap; |
3664 | 3682 | ||
3665 | mgp->num_slices = 1; | 3683 | mgp->num_slices = 1; |
@@ -3672,17 +3690,23 @@ static void myri10ge_probe_slices(struct myri10ge_priv *mgp) | |||
3672 | 3690 | ||
3673 | /* try to load the slice aware rss firmware */ | 3691 | /* try to load the slice aware rss firmware */ |
3674 | old_fw = mgp->fw_name; | 3692 | old_fw = mgp->fw_name; |
3693 | old_allocated = mgp->fw_name_allocated; | ||
3694 | /* don't free old_fw if we override it. */ | ||
3695 | mgp->fw_name_allocated = false; | ||
3696 | |||
3675 | if (myri10ge_fw_name != NULL) { | 3697 | if (myri10ge_fw_name != NULL) { |
3676 | dev_info(&mgp->pdev->dev, "overriding rss firmware to %s\n", | 3698 | dev_info(&mgp->pdev->dev, "overriding rss firmware to %s\n", |
3677 | myri10ge_fw_name); | 3699 | myri10ge_fw_name); |
3678 | mgp->fw_name = myri10ge_fw_name; | 3700 | set_fw_name(mgp, myri10ge_fw_name, false); |
3679 | } else if (old_fw == myri10ge_fw_aligned) | 3701 | } else if (old_fw == myri10ge_fw_aligned) |
3680 | mgp->fw_name = myri10ge_fw_rss_aligned; | 3702 | set_fw_name(mgp, myri10ge_fw_rss_aligned, false); |
3681 | else | 3703 | else |
3682 | mgp->fw_name = myri10ge_fw_rss_unaligned; | 3704 | set_fw_name(mgp, myri10ge_fw_rss_unaligned, false); |
3683 | status = myri10ge_load_firmware(mgp, 0); | 3705 | status = myri10ge_load_firmware(mgp, 0); |
3684 | if (status != 0) { | 3706 | if (status != 0) { |
3685 | dev_info(&pdev->dev, "Rss firmware not found\n"); | 3707 | dev_info(&pdev->dev, "Rss firmware not found\n"); |
3708 | if (old_allocated) | ||
3709 | kfree(old_fw); | ||
3686 | return; | 3710 | return; |
3687 | } | 3711 | } |
3688 | 3712 | ||
@@ -3747,6 +3771,8 @@ static void myri10ge_probe_slices(struct myri10ge_priv *mgp) | |||
3747 | mgp->num_slices); | 3771 | mgp->num_slices); |
3748 | if (status == 0) { | 3772 | if (status == 0) { |
3749 | pci_disable_msix(pdev); | 3773 | pci_disable_msix(pdev); |
3774 | if (old_allocated) | ||
3775 | kfree(old_fw); | ||
3750 | return; | 3776 | return; |
3751 | } | 3777 | } |
3752 | if (status > 0) | 3778 | if (status > 0) |
@@ -3763,7 +3789,7 @@ disable_msix: | |||
3763 | 3789 | ||
3764 | abort_with_fw: | 3790 | abort_with_fw: |
3765 | mgp->num_slices = 1; | 3791 | mgp->num_slices = 1; |
3766 | mgp->fw_name = old_fw; | 3792 | set_fw_name(mgp, old_fw, old_allocated); |
3767 | myri10ge_load_firmware(mgp, 0); | 3793 | myri10ge_load_firmware(mgp, 0); |
3768 | } | 3794 | } |
3769 | 3795 | ||
@@ -3993,6 +4019,7 @@ abort_with_enabled: | |||
3993 | pci_disable_device(pdev); | 4019 | pci_disable_device(pdev); |
3994 | 4020 | ||
3995 | abort_with_netdev: | 4021 | abort_with_netdev: |
4022 | set_fw_name(mgp, NULL, false); | ||
3996 | free_netdev(netdev); | 4023 | free_netdev(netdev); |
3997 | return status; | 4024 | return status; |
3998 | } | 4025 | } |
@@ -4037,6 +4064,7 @@ static void myri10ge_remove(struct pci_dev *pdev) | |||
4037 | dma_free_coherent(&pdev->dev, sizeof(*mgp->cmd), | 4064 | dma_free_coherent(&pdev->dev, sizeof(*mgp->cmd), |
4038 | mgp->cmd, mgp->cmd_bus); | 4065 | mgp->cmd, mgp->cmd_bus); |
4039 | 4066 | ||
4067 | set_fw_name(mgp, NULL, false); | ||
4040 | free_netdev(netdev); | 4068 | free_netdev(netdev); |
4041 | pci_disable_device(pdev); | 4069 | pci_disable_device(pdev); |
4042 | pci_set_drvdata(pdev, NULL); | 4070 | pci_set_drvdata(pdev, NULL); |
diff --git a/drivers/net/wireless/libertas/if_sdio.c b/drivers/net/wireless/libertas/if_sdio.c index 6e71346a7550..ba854c70ab94 100644 --- a/drivers/net/wireless/libertas/if_sdio.c +++ b/drivers/net/wireless/libertas/if_sdio.c | |||
@@ -125,6 +125,8 @@ struct if_sdio_card { | |||
125 | 125 | ||
126 | const char *helper; | 126 | const char *helper; |
127 | const char *firmware; | 127 | const char *firmware; |
128 | bool helper_allocated; | ||
129 | bool firmware_allocated; | ||
128 | 130 | ||
129 | u8 buffer[65536]; | 131 | u8 buffer[65536]; |
130 | 132 | ||
@@ -984,16 +986,34 @@ static int if_sdio_probe(struct sdio_func *func, | |||
984 | card->helper = if_sdio_models[i].helper; | 986 | card->helper = if_sdio_models[i].helper; |
985 | card->firmware = if_sdio_models[i].firmware; | 987 | card->firmware = if_sdio_models[i].firmware; |
986 | 988 | ||
989 | kparam_block_sysfs_write(helper_name); | ||
987 | if (lbs_helper_name) { | 990 | if (lbs_helper_name) { |
991 | char *helper = kstrdup(lbs_helper_name, GFP_KERNEL); | ||
992 | if (!helper) { | ||
993 | kparam_unblock_sysfs_write(helper_name); | ||
994 | ret = -ENOMEM; | ||
995 | goto free; | ||
996 | } | ||
988 | lbs_deb_sdio("overriding helper firmware: %s\n", | 997 | lbs_deb_sdio("overriding helper firmware: %s\n", |
989 | lbs_helper_name); | 998 | lbs_helper_name); |
990 | card->helper = lbs_helper_name; | 999 | card->helper = helper; |
1000 | card->helper_allocated = true; | ||
991 | } | 1001 | } |
1002 | kparam_unblock_sysfs_write(helper_name); | ||
992 | 1003 | ||
1004 | kparam_block_sysfs_write(fw_name); | ||
993 | if (lbs_fw_name) { | 1005 | if (lbs_fw_name) { |
1006 | char *fw_name = kstrdup(lbs_fw_name, GFP_KERNEL); | ||
1007 | if (!fw_name) { | ||
1008 | kparam_unblock_sysfs_write(fw_name); | ||
1009 | ret = -ENOMEM; | ||
1010 | goto free; | ||
1011 | } | ||
994 | lbs_deb_sdio("overriding firmware: %s\n", lbs_fw_name); | 1012 | lbs_deb_sdio("overriding firmware: %s\n", lbs_fw_name); |
995 | card->firmware = lbs_fw_name; | 1013 | card->firmware = fw_name; |
1014 | card->firmware_allocated = true; | ||
996 | } | 1015 | } |
1016 | kparam_unblock_sysfs_write(fw_name); | ||
997 | 1017 | ||
998 | sdio_claim_host(func); | 1018 | sdio_claim_host(func); |
999 | 1019 | ||
@@ -1127,6 +1147,10 @@ free: | |||
1127 | kfree(packet); | 1147 | kfree(packet); |
1128 | } | 1148 | } |
1129 | 1149 | ||
1150 | if (card->helper_allocated) | ||
1151 | kfree(card->helper); | ||
1152 | if (card->firmware_allocated) | ||
1153 | kfree(card->firmware); | ||
1130 | kfree(card); | 1154 | kfree(card); |
1131 | 1155 | ||
1132 | goto out; | 1156 | goto out; |
@@ -1177,6 +1201,10 @@ static void if_sdio_remove(struct sdio_func *func) | |||
1177 | kfree(packet); | 1201 | kfree(packet); |
1178 | } | 1202 | } |
1179 | 1203 | ||
1204 | if (card->helper_allocated) | ||
1205 | kfree(card->helper); | ||
1206 | if (card->firmware_allocated) | ||
1207 | kfree(card->firmware); | ||
1180 | kfree(card); | 1208 | kfree(card); |
1181 | 1209 | ||
1182 | lbs_deb_leave(LBS_DEB_SDIO); | 1210 | lbs_deb_leave(LBS_DEB_SDIO); |
diff --git a/drivers/net/wireless/libertas/if_usb.c b/drivers/net/wireless/libertas/if_usb.c index 07ece9d26c63..3ff61063671a 100644 --- a/drivers/net/wireless/libertas/if_usb.c +++ b/drivers/net/wireless/libertas/if_usb.c | |||
@@ -289,10 +289,13 @@ static int if_usb_probe(struct usb_interface *intf, | |||
289 | } | 289 | } |
290 | 290 | ||
291 | /* Upload firmware */ | 291 | /* Upload firmware */ |
292 | kparam_block_sysfs_write(fw_name); | ||
292 | if (__if_usb_prog_firmware(cardp, lbs_fw_name, BOOT_CMD_FW_BY_USB)) { | 293 | if (__if_usb_prog_firmware(cardp, lbs_fw_name, BOOT_CMD_FW_BY_USB)) { |
294 | kparam_unblock_sysfs_write(fw_name); | ||
293 | lbs_deb_usbd(&udev->dev, "FW upload failed\n"); | 295 | lbs_deb_usbd(&udev->dev, "FW upload failed\n"); |
294 | goto err_prog_firmware; | 296 | goto err_prog_firmware; |
295 | } | 297 | } |
298 | kparam_unblock_sysfs_write(fw_name); | ||
296 | 299 | ||
297 | if (!(priv = lbs_add_card(cardp, &udev->dev))) | 300 | if (!(priv = lbs_add_card(cardp, &udev->dev))) |
298 | goto err_prog_firmware; | 301 | goto err_prog_firmware; |
diff --git a/drivers/net/wireless/libertas_tf/if_usb.c b/drivers/net/wireless/libertas_tf/if_usb.c index b172f5d87a3b..41a4f214ade1 100644 --- a/drivers/net/wireless/libertas_tf/if_usb.c +++ b/drivers/net/wireless/libertas_tf/if_usb.c | |||
@@ -811,12 +811,15 @@ static int if_usb_prog_firmware(struct if_usb_card *cardp) | |||
811 | 811 | ||
812 | lbtf_deb_enter(LBTF_DEB_USB); | 812 | lbtf_deb_enter(LBTF_DEB_USB); |
813 | 813 | ||
814 | kparam_block_sysfs_write(fw_name); | ||
814 | ret = request_firmware(&cardp->fw, lbtf_fw_name, &cardp->udev->dev); | 815 | ret = request_firmware(&cardp->fw, lbtf_fw_name, &cardp->udev->dev); |
815 | if (ret < 0) { | 816 | if (ret < 0) { |
816 | pr_err("request_firmware() failed with %#x\n", ret); | 817 | pr_err("request_firmware() failed with %#x\n", ret); |
817 | pr_err("firmware %s not found\n", lbtf_fw_name); | 818 | pr_err("firmware %s not found\n", lbtf_fw_name); |
819 | kparam_unblock_sysfs_write(fw_name); | ||
818 | goto done; | 820 | goto done; |
819 | } | 821 | } |
822 | kparam_unblock_sysfs_write(fw_name); | ||
820 | 823 | ||
821 | if (check_fwfile_format(cardp->fw->data, cardp->fw->size)) | 824 | if (check_fwfile_format(cardp->fw->data, cardp->fw->size)) |
822 | goto release_fw; | 825 | goto release_fw; |
diff --git a/drivers/scsi/bfa/bfad.c b/drivers/scsi/bfa/bfad.c index 915a29d6c7ad..ca04cc9d332f 100644 --- a/drivers/scsi/bfa/bfad.c +++ b/drivers/scsi/bfa/bfad.c | |||
@@ -788,6 +788,7 @@ bfad_drv_init(struct bfad_s *bfad) | |||
788 | memset(&driver_info, 0, sizeof(driver_info)); | 788 | memset(&driver_info, 0, sizeof(driver_info)); |
789 | strncpy(driver_info.version, BFAD_DRIVER_VERSION, | 789 | strncpy(driver_info.version, BFAD_DRIVER_VERSION, |
790 | sizeof(driver_info.version) - 1); | 790 | sizeof(driver_info.version) - 1); |
791 | __kernel_param_lock(); | ||
791 | if (host_name) | 792 | if (host_name) |
792 | strncpy(driver_info.host_machine_name, host_name, | 793 | strncpy(driver_info.host_machine_name, host_name, |
793 | sizeof(driver_info.host_machine_name) - 1); | 794 | sizeof(driver_info.host_machine_name) - 1); |
@@ -797,6 +798,7 @@ bfad_drv_init(struct bfad_s *bfad) | |||
797 | if (os_patch) | 798 | if (os_patch) |
798 | strncpy(driver_info.host_os_patch, os_patch, | 799 | strncpy(driver_info.host_os_patch, os_patch, |
799 | sizeof(driver_info.host_os_patch) - 1); | 800 | sizeof(driver_info.host_os_patch) - 1); |
801 | __kernel_param_unlock(); | ||
800 | 802 | ||
801 | strncpy(driver_info.os_device_name, bfad->pci_name, | 803 | strncpy(driver_info.os_device_name, bfad->pci_name, |
802 | sizeof(driver_info.os_device_name - 1)); | 804 | sizeof(driver_info.os_device_name - 1)); |
diff --git a/drivers/staging/rtl8187se/r8180_core.c b/drivers/staging/rtl8187se/r8180_core.c index 49ab9fa9ffa7..ed7457bc24ea 100644 --- a/drivers/staging/rtl8187se/r8180_core.c +++ b/drivers/staging/rtl8187se/r8180_core.c | |||
@@ -61,7 +61,7 @@ static struct pci_device_id rtl8180_pci_id_tbl[] __devinitdata = { | |||
61 | }; | 61 | }; |
62 | 62 | ||
63 | 63 | ||
64 | static char *ifname = "wlan%d"; | 64 | static char ifname[IFNAMSIZ] = "wlan%d"; |
65 | static int hwseqnum = 0; | 65 | static int hwseqnum = 0; |
66 | static int hwwep = 0; | 66 | static int hwwep = 0; |
67 | static int channels = 0x3fff; | 67 | static int channels = 0x3fff; |
@@ -72,7 +72,7 @@ MODULE_AUTHOR("Andrea Merello <andreamrl@tiscali.it>"); | |||
72 | MODULE_DESCRIPTION("Linux driver for Realtek RTL8180 / RTL8185 WiFi cards"); | 72 | MODULE_DESCRIPTION("Linux driver for Realtek RTL8180 / RTL8185 WiFi cards"); |
73 | 73 | ||
74 | 74 | ||
75 | module_param(ifname, charp, S_IRUGO|S_IWUSR); | 75 | module_param_string(ifname, ifname, sizeof(ifname), S_IRUGO|S_IWUSR); |
76 | module_param(hwseqnum, int, S_IRUGO|S_IWUSR); | 76 | module_param(hwseqnum, int, S_IRUGO|S_IWUSR); |
77 | module_param(hwwep, int, S_IRUGO|S_IWUSR); | 77 | module_param(hwwep, int, S_IRUGO|S_IWUSR); |
78 | module_param(channels, int, S_IRUGO|S_IWUSR); | 78 | module_param(channels, int, S_IRUGO|S_IWUSR); |
@@ -3609,7 +3609,7 @@ static int __devinit rtl8180_pci_probe(struct pci_dev *pdev, | |||
3609 | 3609 | ||
3610 | if (dev_alloc_name(dev, ifname) < 0) { | 3610 | if (dev_alloc_name(dev, ifname) < 0) { |
3611 | DMESG("Oops: devname already taken! Trying wlan%%d...\n"); | 3611 | DMESG("Oops: devname already taken! Trying wlan%%d...\n"); |
3612 | ifname = "wlan%d"; | 3612 | strcpy(ifname, "wlan%d"); |
3613 | dev_alloc_name(dev, ifname); | 3613 | dev_alloc_name(dev, ifname); |
3614 | } | 3614 | } |
3615 | 3615 | ||
diff --git a/drivers/staging/rtl8192e/r8192E_core.c b/drivers/staging/rtl8192e/r8192E_core.c index 4cd071adf84b..17a806f9ee77 100644 --- a/drivers/staging/rtl8192e/r8192E_core.c +++ b/drivers/staging/rtl8192e/r8192E_core.c | |||
@@ -112,7 +112,7 @@ static const struct pci_device_id rtl8192_pci_id_tbl[] __devinitdata = { | |||
112 | {} | 112 | {} |
113 | }; | 113 | }; |
114 | 114 | ||
115 | static char* ifname = "wlan%d"; | 115 | static char ifname[IFNAMSIZ] = "wlan%d"; |
116 | static int hwwep = 1; //default use hw. set 0 to use software security | 116 | static int hwwep = 1; //default use hw. set 0 to use software security |
117 | static int channels = 0x3fff; | 117 | static int channels = 0x3fff; |
118 | 118 | ||
@@ -123,7 +123,7 @@ MODULE_DEVICE_TABLE(pci, rtl8192_pci_id_tbl); | |||
123 | MODULE_DESCRIPTION("Linux driver for Realtek RTL819x WiFi cards"); | 123 | MODULE_DESCRIPTION("Linux driver for Realtek RTL819x WiFi cards"); |
124 | 124 | ||
125 | 125 | ||
126 | module_param(ifname, charp, S_IRUGO|S_IWUSR ); | 126 | module_param_string(ifname, ifname, sizeof(ifname), S_IRUGO|S_IWUSR); |
127 | //module_param(hwseqnum,int, S_IRUGO|S_IWUSR); | 127 | //module_param(hwseqnum,int, S_IRUGO|S_IWUSR); |
128 | module_param(hwwep,int, S_IRUGO|S_IWUSR); | 128 | module_param(hwwep,int, S_IRUGO|S_IWUSR); |
129 | module_param(channels,int, S_IRUGO|S_IWUSR); | 129 | module_param(channels,int, S_IRUGO|S_IWUSR); |
@@ -6446,7 +6446,7 @@ static int __devinit rtl8192_pci_probe(struct pci_dev *pdev, | |||
6446 | 6446 | ||
6447 | if (dev_alloc_name(dev, ifname) < 0){ | 6447 | if (dev_alloc_name(dev, ifname) < 0){ |
6448 | RT_TRACE(COMP_INIT, "Oops: devname already taken! Trying wlan%%d...\n"); | 6448 | RT_TRACE(COMP_INIT, "Oops: devname already taken! Trying wlan%%d...\n"); |
6449 | ifname = "wlan%d"; | 6449 | strcpy(ifname, "wlan%d"); |
6450 | dev_alloc_name(dev, ifname); | 6450 | dev_alloc_name(dev, ifname); |
6451 | } | 6451 | } |
6452 | 6452 | ||
diff --git a/drivers/staging/rtl8192su/r8192U_core.c b/drivers/staging/rtl8192su/r8192U_core.c index 6970c97713d8..df5b52baf893 100644 --- a/drivers/staging/rtl8192su/r8192U_core.c +++ b/drivers/staging/rtl8192su/r8192U_core.c | |||
@@ -144,13 +144,13 @@ MODULE_VERSION("V 1.1"); | |||
144 | MODULE_DEVICE_TABLE(usb, rtl8192_usb_id_tbl); | 144 | MODULE_DEVICE_TABLE(usb, rtl8192_usb_id_tbl); |
145 | MODULE_DESCRIPTION("Linux driver for Realtek RTL8192 USB WiFi cards"); | 145 | MODULE_DESCRIPTION("Linux driver for Realtek RTL8192 USB WiFi cards"); |
146 | 146 | ||
147 | static char* ifname = "wlan%d"; | 147 | static char ifname[IFNAMSIZ] = "wlan%d"; |
148 | static int hwwep = 1; //default use hw. set 0 to use software security | 148 | static int hwwep = 1; //default use hw. set 0 to use software security |
149 | static int channels = 0x3fff; | 149 | static int channels = 0x3fff; |
150 | 150 | ||
151 | 151 | ||
152 | 152 | ||
153 | module_param(ifname, charp, S_IRUGO|S_IWUSR ); | 153 | module_param_string(ifname, ifname, sizeof(ifname), S_IRUGO|S_IWUSR); |
154 | //module_param(hwseqnum,int, S_IRUGO|S_IWUSR); | 154 | //module_param(hwseqnum,int, S_IRUGO|S_IWUSR); |
155 | module_param(hwwep,int, S_IRUGO|S_IWUSR); | 155 | module_param(hwwep,int, S_IRUGO|S_IWUSR); |
156 | module_param(channels,int, S_IRUGO|S_IWUSR); | 156 | module_param(channels,int, S_IRUGO|S_IWUSR); |
@@ -7406,7 +7406,7 @@ static int __devinit rtl8192_usb_probe(struct usb_interface *intf, | |||
7406 | 7406 | ||
7407 | if (dev_alloc_name(dev, ifname) < 0){ | 7407 | if (dev_alloc_name(dev, ifname) < 0){ |
7408 | RT_TRACE(COMP_INIT, "Oops: devname already taken! Trying wlan%%d...\n"); | 7408 | RT_TRACE(COMP_INIT, "Oops: devname already taken! Trying wlan%%d...\n"); |
7409 | ifname = "wlan%d"; | 7409 | strcpy(ifname, "wlan%d"); |
7410 | dev_alloc_name(dev, ifname); | 7410 | dev_alloc_name(dev, ifname); |
7411 | } | 7411 | } |
7412 | 7412 | ||
diff --git a/drivers/usb/atm/ueagle-atm.c b/drivers/usb/atm/ueagle-atm.c index 5b3f555e01c9..ea071a5b6eee 100644 --- a/drivers/usb/atm/ueagle-atm.c +++ b/drivers/usb/atm/ueagle-atm.c | |||
@@ -1577,6 +1577,7 @@ static void cmvs_file_name(struct uea_softc *sc, char *const cmv_name, int ver) | |||
1577 | char file_arr[] = "CMVxy.bin"; | 1577 | char file_arr[] = "CMVxy.bin"; |
1578 | char *file; | 1578 | char *file; |
1579 | 1579 | ||
1580 | kparam_block_sysfs_write(cmv_file); | ||
1580 | /* set proper name corresponding modem version and line type */ | 1581 | /* set proper name corresponding modem version and line type */ |
1581 | if (cmv_file[sc->modem_index] == NULL) { | 1582 | if (cmv_file[sc->modem_index] == NULL) { |
1582 | if (UEA_CHIP_VERSION(sc) == ADI930) | 1583 | if (UEA_CHIP_VERSION(sc) == ADI930) |
@@ -1595,6 +1596,7 @@ static void cmvs_file_name(struct uea_softc *sc, char *const cmv_name, int ver) | |||
1595 | strlcat(cmv_name, file, UEA_FW_NAME_MAX); | 1596 | strlcat(cmv_name, file, UEA_FW_NAME_MAX); |
1596 | if (ver == 2) | 1597 | if (ver == 2) |
1597 | strlcat(cmv_name, ".v2", UEA_FW_NAME_MAX); | 1598 | strlcat(cmv_name, ".v2", UEA_FW_NAME_MAX); |
1599 | kparam_unblock_sysfs_write(cmv_file); | ||
1598 | } | 1600 | } |
1599 | 1601 | ||
1600 | static int request_cmvs_old(struct uea_softc *sc, | 1602 | static int request_cmvs_old(struct uea_softc *sc, |
diff --git a/drivers/video/uvesafb.c b/drivers/video/uvesafb.c index 7b8839ebf3c4..52ec0959d462 100644 --- a/drivers/video/uvesafb.c +++ b/drivers/video/uvesafb.c | |||
@@ -1977,8 +1977,7 @@ static void __devexit uvesafb_exit(void) | |||
1977 | 1977 | ||
1978 | module_exit(uvesafb_exit); | 1978 | module_exit(uvesafb_exit); |
1979 | 1979 | ||
1980 | #define param_get_scroll NULL | 1980 | static int param_set_scroll(const char *val, const struct kernel_param *kp) |
1981 | static int param_set_scroll(const char *val, struct kernel_param *kp) | ||
1982 | { | 1981 | { |
1983 | ypan = 0; | 1982 | ypan = 0; |
1984 | 1983 | ||
@@ -1993,7 +1992,9 @@ static int param_set_scroll(const char *val, struct kernel_param *kp) | |||
1993 | 1992 | ||
1994 | return 0; | 1993 | return 0; |
1995 | } | 1994 | } |
1996 | 1995 | static struct kernel_param_ops param_ops_scroll = { | |
1996 | .set = param_set_scroll, | ||
1997 | }; | ||
1997 | #define param_check_scroll(name, p) __param_check(name, p, void) | 1998 | #define param_check_scroll(name, p) __param_check(name, p, void) |
1998 | 1999 | ||
1999 | module_param_named(scroll, ypan, scroll, 0); | 2000 | module_param_named(scroll, ypan, scroll, 0); |
diff --git a/drivers/video/vt8623fb.c b/drivers/video/vt8623fb.c index d31dc96f838a..85d76ec4c63e 100644 --- a/drivers/video/vt8623fb.c +++ b/drivers/video/vt8623fb.c | |||
@@ -726,7 +726,9 @@ static int __devinit vt8623_pci_probe(struct pci_dev *dev, const struct pci_devi | |||
726 | 726 | ||
727 | /* Prepare startup mode */ | 727 | /* Prepare startup mode */ |
728 | 728 | ||
729 | kparam_block_sysfs_write(mode_option); | ||
729 | rc = fb_find_mode(&(info->var), info, mode_option, NULL, 0, NULL, 8); | 730 | rc = fb_find_mode(&(info->var), info, mode_option, NULL, 0, NULL, 8); |
731 | kparam_unblock_sysfs_write(mode_option); | ||
730 | if (! ((rc == 1) || (rc == 2))) { | 732 | if (! ((rc == 1) || (rc == 2))) { |
731 | rc = -EINVAL; | 733 | rc = -EINVAL; |
732 | dev_err(info->device, "mode %s not found\n", mode_option); | 734 | dev_err(info->device, "mode %s not found\n", mode_option); |
diff --git a/fs/nfs/callback.c b/fs/nfs/callback.c index 36dfdae95123..e17b49e2eabd 100644 --- a/fs/nfs/callback.c +++ b/fs/nfs/callback.c | |||
@@ -45,7 +45,7 @@ unsigned short nfs_callback_tcpport; | |||
45 | unsigned short nfs_callback_tcpport6; | 45 | unsigned short nfs_callback_tcpport6; |
46 | #define NFS_CALLBACK_MAXPORTNR (65535U) | 46 | #define NFS_CALLBACK_MAXPORTNR (65535U) |
47 | 47 | ||
48 | static int param_set_portnr(const char *val, struct kernel_param *kp) | 48 | static int param_set_portnr(const char *val, const struct kernel_param *kp) |
49 | { | 49 | { |
50 | unsigned long num; | 50 | unsigned long num; |
51 | int ret; | 51 | int ret; |
@@ -58,11 +58,10 @@ static int param_set_portnr(const char *val, struct kernel_param *kp) | |||
58 | *((unsigned int *)kp->arg) = num; | 58 | *((unsigned int *)kp->arg) = num; |
59 | return 0; | 59 | return 0; |
60 | } | 60 | } |
61 | 61 | static struct kernel_param_ops param_ops_portnr = { | |
62 | static int param_get_portnr(char *buffer, struct kernel_param *kp) | 62 | .set = param_set_portnr, |
63 | { | 63 | .get = param_get_uint, |
64 | return param_get_uint(buffer, kp); | 64 | }; |
65 | } | ||
66 | #define param_check_portnr(name, p) __param_check(name, p, unsigned int); | 65 | #define param_check_portnr(name, p) __param_check(name, p, unsigned int); |
67 | 66 | ||
68 | module_param_named(callback_tcpport, nfs_callback_set_tcpport, portnr, 0644); | 67 | module_param_named(callback_tcpport, nfs_callback_set_tcpport, portnr, 0644); |
diff --git a/include/linux/moduleparam.h b/include/linux/moduleparam.h index 82a9124f7d75..9d2f1837b3d8 100644 --- a/include/linux/moduleparam.h +++ b/include/linux/moduleparam.h | |||
@@ -31,20 +31,23 @@ static const char __module_cat(name,__LINE__)[] \ | |||
31 | 31 | ||
32 | struct kernel_param; | 32 | struct kernel_param; |
33 | 33 | ||
34 | /* Returns 0, or -errno. arg is in kp->arg. */ | 34 | struct kernel_param_ops { |
35 | typedef int (*param_set_fn)(const char *val, struct kernel_param *kp); | 35 | /* Returns 0, or -errno. arg is in kp->arg. */ |
36 | /* Returns length written or -errno. Buffer is 4k (ie. be short!) */ | 36 | int (*set)(const char *val, const struct kernel_param *kp); |
37 | typedef int (*param_get_fn)(char *buffer, struct kernel_param *kp); | 37 | /* Returns length written or -errno. Buffer is 4k (ie. be short!) */ |
38 | int (*get)(char *buffer, const struct kernel_param *kp); | ||
39 | /* Optional function to free kp->arg when module unloaded. */ | ||
40 | void (*free)(void *arg); | ||
41 | }; | ||
38 | 42 | ||
39 | /* Flag bits for kernel_param.flags */ | 43 | /* Flag bits for kernel_param.flags */ |
40 | #define KPARAM_ISBOOL 2 | 44 | #define KPARAM_ISBOOL 2 |
41 | 45 | ||
42 | struct kernel_param { | 46 | struct kernel_param { |
43 | const char *name; | 47 | const char *name; |
48 | const struct kernel_param_ops *ops; | ||
44 | u16 perm; | 49 | u16 perm; |
45 | u16 flags; | 50 | u16 flags; |
46 | param_set_fn set; | ||
47 | param_get_fn get; | ||
48 | union { | 51 | union { |
49 | void *arg; | 52 | void *arg; |
50 | const struct kparam_string *str; | 53 | const struct kparam_string *str; |
@@ -63,12 +66,67 @@ struct kparam_array | |||
63 | { | 66 | { |
64 | unsigned int max; | 67 | unsigned int max; |
65 | unsigned int *num; | 68 | unsigned int *num; |
66 | param_set_fn set; | 69 | const struct kernel_param_ops *ops; |
67 | param_get_fn get; | ||
68 | unsigned int elemsize; | 70 | unsigned int elemsize; |
69 | void *elem; | 71 | void *elem; |
70 | }; | 72 | }; |
71 | 73 | ||
74 | /** | ||
75 | * module_param - typesafe helper for a module/cmdline parameter | ||
76 | * @value: the variable to alter, and exposed parameter name. | ||
77 | * @type: the type of the parameter | ||
78 | * @perm: visibility in sysfs. | ||
79 | * | ||
80 | * @value becomes the module parameter, or (prefixed by KBUILD_MODNAME and a | ||
81 | * ".") the kernel commandline parameter. Note that - is changed to _, so | ||
82 | * the user can use "foo-bar=1" even for variable "foo_bar". | ||
83 | * | ||
84 | * @perm is 0 if the the variable is not to appear in sysfs, or 0444 | ||
85 | * for world-readable, 0644 for root-writable, etc. Note that if it | ||
86 | * is writable, you may need to use kparam_block_sysfs_write() around | ||
87 | * accesses (esp. charp, which can be kfreed when it changes). | ||
88 | * | ||
89 | * The @type is simply pasted to refer to a param_ops_##type and a | ||
90 | * param_check_##type: for convenience many standard types are provided but | ||
91 | * you can create your own by defining those variables. | ||
92 | * | ||
93 | * Standard types are: | ||
94 | * byte, short, ushort, int, uint, long, ulong | ||
95 | * charp: a character pointer | ||
96 | * bool: a bool, values 0/1, y/n, Y/N. | ||
97 | * invbool: the above, only sense-reversed (N = true). | ||
98 | */ | ||
99 | #define module_param(name, type, perm) \ | ||
100 | module_param_named(name, name, type, perm) | ||
101 | |||
102 | /** | ||
103 | * module_param_named - typesafe helper for a renamed module/cmdline parameter | ||
104 | * @name: a valid C identifier which is the parameter name. | ||
105 | * @value: the actual lvalue to alter. | ||
106 | * @type: the type of the parameter | ||
107 | * @perm: visibility in sysfs. | ||
108 | * | ||
109 | * Usually it's a good idea to have variable names and user-exposed names the | ||
110 | * same, but that's harder if the variable must be non-static or is inside a | ||
111 | * structure. This allows exposure under a different name. | ||
112 | */ | ||
113 | #define module_param_named(name, value, type, perm) \ | ||
114 | param_check_##type(name, &(value)); \ | ||
115 | module_param_cb(name, ¶m_ops_##type, &value, perm); \ | ||
116 | __MODULE_PARM_TYPE(name, #type) | ||
117 | |||
118 | /** | ||
119 | * module_param_cb - general callback for a module/cmdline parameter | ||
120 | * @name: a valid C identifier which is the parameter name. | ||
121 | * @ops: the set & get operations for this parameter. | ||
122 | * @perm: visibility in sysfs. | ||
123 | * | ||
124 | * The ops can have NULL set or get functions. | ||
125 | */ | ||
126 | #define module_param_cb(name, ops, arg, perm) \ | ||
127 | __module_param_call(MODULE_PARAM_PREFIX, \ | ||
128 | name, ops, arg, __same_type((arg), bool *), perm) | ||
129 | |||
72 | /* On alpha, ia64 and ppc64 relocations to global data cannot go into | 130 | /* On alpha, ia64 and ppc64 relocations to global data cannot go into |
73 | read-only sections (which is part of respective UNIX ABI on these | 131 | read-only sections (which is part of respective UNIX ABI on these |
74 | platforms). So 'const' makes no sense and even causes compile failures | 132 | platforms). So 'const' makes no sense and even causes compile failures |
@@ -80,10 +138,8 @@ struct kparam_array | |||
80 | #endif | 138 | #endif |
81 | 139 | ||
82 | /* This is the fundamental function for registering boot/module | 140 | /* This is the fundamental function for registering boot/module |
83 | parameters. perm sets the visibility in sysfs: 000 means it's | 141 | parameters. */ |
84 | not there, read bits mean it's readable, write bits mean it's | 142 | #define __module_param_call(prefix, name, ops, arg, isbool, perm) \ |
85 | writable. */ | ||
86 | #define __module_param_call(prefix, name, set, get, arg, isbool, perm) \ | ||
87 | /* Default value instead of permissions? */ \ | 143 | /* Default value instead of permissions? */ \ |
88 | static int __param_perm_check_##name __attribute__((unused)) = \ | 144 | static int __param_perm_check_##name __attribute__((unused)) = \ |
89 | BUILD_BUG_ON_ZERO((perm) < 0 || (perm) > 0777 || ((perm) & 2)) \ | 145 | BUILD_BUG_ON_ZERO((perm) < 0 || (perm) > 0777 || ((perm) & 2)) \ |
@@ -92,31 +148,87 @@ struct kparam_array | |||
92 | static struct kernel_param __moduleparam_const __param_##name \ | 148 | static struct kernel_param __moduleparam_const __param_##name \ |
93 | __used \ | 149 | __used \ |
94 | __attribute__ ((unused,__section__ ("__param"),aligned(sizeof(void *)))) \ | 150 | __attribute__ ((unused,__section__ ("__param"),aligned(sizeof(void *)))) \ |
95 | = { __param_str_##name, perm, isbool ? KPARAM_ISBOOL : 0, \ | 151 | = { __param_str_##name, ops, perm, isbool ? KPARAM_ISBOOL : 0, \ |
96 | set, get, { arg } } | 152 | { arg } } |
153 | |||
154 | /* Obsolete - use module_param_cb() */ | ||
155 | #define module_param_call(name, set, get, arg, perm) \ | ||
156 | static struct kernel_param_ops __param_ops_##name = \ | ||
157 | { (void *)set, (void *)get }; \ | ||
158 | __module_param_call(MODULE_PARAM_PREFIX, \ | ||
159 | name, &__param_ops_##name, arg, \ | ||
160 | __same_type(arg, bool *), \ | ||
161 | (perm) + sizeof(__check_old_set_param(set))*0) | ||
162 | |||
163 | /* We don't get oldget: it's often a new-style param_get_uint, etc. */ | ||
164 | static inline int | ||
165 | __check_old_set_param(int (*oldset)(const char *, struct kernel_param *)) | ||
166 | { | ||
167 | return 0; | ||
168 | } | ||
97 | 169 | ||
98 | #define module_param_call(name, set, get, arg, perm) \ | 170 | /** |
99 | __module_param_call(MODULE_PARAM_PREFIX, \ | 171 | * kparam_block_sysfs_write - make sure a parameter isn't written via sysfs. |
100 | name, set, get, arg, \ | 172 | * @name: the name of the parameter |
101 | __same_type(*(arg), bool), perm) | 173 | * |
174 | * There's no point blocking write on a paramter that isn't writable via sysfs! | ||
175 | */ | ||
176 | #define kparam_block_sysfs_write(name) \ | ||
177 | do { \ | ||
178 | BUG_ON(!(__param_##name.perm & 0222)); \ | ||
179 | __kernel_param_lock(); \ | ||
180 | } while (0) | ||
102 | 181 | ||
103 | /* Helper functions: type is byte, short, ushort, int, uint, long, | 182 | /** |
104 | ulong, charp, bool or invbool, or XXX if you define param_get_XXX, | 183 | * kparam_unblock_sysfs_write - allows sysfs to write to a parameter again. |
105 | param_set_XXX and param_check_XXX. */ | 184 | * @name: the name of the parameter |
106 | #define module_param_named(name, value, type, perm) \ | 185 | */ |
107 | param_check_##type(name, &(value)); \ | 186 | #define kparam_unblock_sysfs_write(name) \ |
108 | module_param_call(name, param_set_##type, param_get_##type, &value, perm); \ | 187 | do { \ |
109 | __MODULE_PARM_TYPE(name, #type) | 188 | BUG_ON(!(__param_##name.perm & 0222)); \ |
189 | __kernel_param_unlock(); \ | ||
190 | } while (0) | ||
110 | 191 | ||
111 | #define module_param(name, type, perm) \ | 192 | /** |
112 | module_param_named(name, name, type, perm) | 193 | * kparam_block_sysfs_read - make sure a parameter isn't read via sysfs. |
194 | * @name: the name of the parameter | ||
195 | * | ||
196 | * This also blocks sysfs writes. | ||
197 | */ | ||
198 | #define kparam_block_sysfs_read(name) \ | ||
199 | do { \ | ||
200 | BUG_ON(!(__param_##name.perm & 0444)); \ | ||
201 | __kernel_param_lock(); \ | ||
202 | } while (0) | ||
203 | |||
204 | /** | ||
205 | * kparam_unblock_sysfs_read - allows sysfs to read a parameter again. | ||
206 | * @name: the name of the parameter | ||
207 | */ | ||
208 | #define kparam_unblock_sysfs_read(name) \ | ||
209 | do { \ | ||
210 | BUG_ON(!(__param_##name.perm & 0444)); \ | ||
211 | __kernel_param_unlock(); \ | ||
212 | } while (0) | ||
213 | |||
214 | #ifdef CONFIG_SYSFS | ||
215 | extern void __kernel_param_lock(void); | ||
216 | extern void __kernel_param_unlock(void); | ||
217 | #else | ||
218 | static inline void __kernel_param_lock(void) | ||
219 | { | ||
220 | } | ||
221 | static inline void __kernel_param_unlock(void) | ||
222 | { | ||
223 | } | ||
224 | #endif | ||
113 | 225 | ||
114 | #ifndef MODULE | 226 | #ifndef MODULE |
115 | /** | 227 | /** |
116 | * core_param - define a historical core kernel parameter. | 228 | * core_param - define a historical core kernel parameter. |
117 | * @name: the name of the cmdline and sysfs parameter (often the same as var) | 229 | * @name: the name of the cmdline and sysfs parameter (often the same as var) |
118 | * @var: the variable | 230 | * @var: the variable |
119 | * @type: the type (for param_set_##type and param_get_##type) | 231 | * @type: the type of the parameter |
120 | * @perm: visibility in sysfs | 232 | * @perm: visibility in sysfs |
121 | * | 233 | * |
122 | * core_param is just like module_param(), but cannot be modular and | 234 | * core_param is just like module_param(), but cannot be modular and |
@@ -126,23 +238,32 @@ struct kparam_array | |||
126 | */ | 238 | */ |
127 | #define core_param(name, var, type, perm) \ | 239 | #define core_param(name, var, type, perm) \ |
128 | param_check_##type(name, &(var)); \ | 240 | param_check_##type(name, &(var)); \ |
129 | __module_param_call("", name, param_set_##type, param_get_##type, \ | 241 | __module_param_call("", name, ¶m_ops_##type, \ |
130 | &var, __same_type(var, bool), perm) | 242 | &var, __same_type(var, bool), perm) |
131 | #endif /* !MODULE */ | 243 | #endif /* !MODULE */ |
132 | 244 | ||
133 | /* Actually copy string: maxlen param is usually sizeof(string). */ | 245 | /** |
246 | * module_param_string - a char array parameter | ||
247 | * @name: the name of the parameter | ||
248 | * @string: the string variable | ||
249 | * @len: the maximum length of the string, incl. terminator | ||
250 | * @perm: visibility in sysfs. | ||
251 | * | ||
252 | * This actually copies the string when it's set (unlike type charp). | ||
253 | * @len is usually just sizeof(string). | ||
254 | */ | ||
134 | #define module_param_string(name, string, len, perm) \ | 255 | #define module_param_string(name, string, len, perm) \ |
135 | static const struct kparam_string __param_string_##name \ | 256 | static const struct kparam_string __param_string_##name \ |
136 | = { len, string }; \ | 257 | = { len, string }; \ |
137 | __module_param_call(MODULE_PARAM_PREFIX, name, \ | 258 | __module_param_call(MODULE_PARAM_PREFIX, name, \ |
138 | param_set_copystring, param_get_string, \ | 259 | ¶m_ops_string, \ |
139 | .str = &__param_string_##name, 0, perm); \ | 260 | .str = &__param_string_##name, 0, perm); \ |
140 | __MODULE_PARM_TYPE(name, "string") | 261 | __MODULE_PARM_TYPE(name, "string") |
141 | 262 | ||
142 | /* Called on module insert or kernel boot */ | 263 | /* Called on module insert or kernel boot */ |
143 | extern int parse_args(const char *name, | 264 | extern int parse_args(const char *name, |
144 | char *args, | 265 | char *args, |
145 | struct kernel_param *params, | 266 | const struct kernel_param *params, |
146 | unsigned num, | 267 | unsigned num, |
147 | int (*unknown)(char *param, char *val)); | 268 | int (*unknown)(char *param, char *val)); |
148 | 269 | ||
@@ -162,72 +283,105 @@ static inline void destroy_params(const struct kernel_param *params, | |||
162 | #define __param_check(name, p, type) \ | 283 | #define __param_check(name, p, type) \ |
163 | static inline type *__check_##name(void) { return(p); } | 284 | static inline type *__check_##name(void) { return(p); } |
164 | 285 | ||
165 | extern int param_set_byte(const char *val, struct kernel_param *kp); | 286 | extern struct kernel_param_ops param_ops_byte; |
166 | extern int param_get_byte(char *buffer, struct kernel_param *kp); | 287 | extern int param_set_byte(const char *val, const struct kernel_param *kp); |
288 | extern int param_get_byte(char *buffer, const struct kernel_param *kp); | ||
167 | #define param_check_byte(name, p) __param_check(name, p, unsigned char) | 289 | #define param_check_byte(name, p) __param_check(name, p, unsigned char) |
168 | 290 | ||
169 | extern int param_set_short(const char *val, struct kernel_param *kp); | 291 | extern struct kernel_param_ops param_ops_short; |
170 | extern int param_get_short(char *buffer, struct kernel_param *kp); | 292 | extern int param_set_short(const char *val, const struct kernel_param *kp); |
293 | extern int param_get_short(char *buffer, const struct kernel_param *kp); | ||
171 | #define param_check_short(name, p) __param_check(name, p, short) | 294 | #define param_check_short(name, p) __param_check(name, p, short) |
172 | 295 | ||
173 | extern int param_set_ushort(const char *val, struct kernel_param *kp); | 296 | extern struct kernel_param_ops param_ops_ushort; |
174 | extern int param_get_ushort(char *buffer, struct kernel_param *kp); | 297 | extern int param_set_ushort(const char *val, const struct kernel_param *kp); |
298 | extern int param_get_ushort(char *buffer, const struct kernel_param *kp); | ||
175 | #define param_check_ushort(name, p) __param_check(name, p, unsigned short) | 299 | #define param_check_ushort(name, p) __param_check(name, p, unsigned short) |
176 | 300 | ||
177 | extern int param_set_int(const char *val, struct kernel_param *kp); | 301 | extern struct kernel_param_ops param_ops_int; |
178 | extern int param_get_int(char *buffer, struct kernel_param *kp); | 302 | extern int param_set_int(const char *val, const struct kernel_param *kp); |
303 | extern int param_get_int(char *buffer, const struct kernel_param *kp); | ||
179 | #define param_check_int(name, p) __param_check(name, p, int) | 304 | #define param_check_int(name, p) __param_check(name, p, int) |
180 | 305 | ||
181 | extern int param_set_uint(const char *val, struct kernel_param *kp); | 306 | extern struct kernel_param_ops param_ops_uint; |
182 | extern int param_get_uint(char *buffer, struct kernel_param *kp); | 307 | extern int param_set_uint(const char *val, const struct kernel_param *kp); |
308 | extern int param_get_uint(char *buffer, const struct kernel_param *kp); | ||
183 | #define param_check_uint(name, p) __param_check(name, p, unsigned int) | 309 | #define param_check_uint(name, p) __param_check(name, p, unsigned int) |
184 | 310 | ||
185 | extern int param_set_long(const char *val, struct kernel_param *kp); | 311 | extern struct kernel_param_ops param_ops_long; |
186 | extern int param_get_long(char *buffer, struct kernel_param *kp); | 312 | extern int param_set_long(const char *val, const struct kernel_param *kp); |
313 | extern int param_get_long(char *buffer, const struct kernel_param *kp); | ||
187 | #define param_check_long(name, p) __param_check(name, p, long) | 314 | #define param_check_long(name, p) __param_check(name, p, long) |
188 | 315 | ||
189 | extern int param_set_ulong(const char *val, struct kernel_param *kp); | 316 | extern struct kernel_param_ops param_ops_ulong; |
190 | extern int param_get_ulong(char *buffer, struct kernel_param *kp); | 317 | extern int param_set_ulong(const char *val, const struct kernel_param *kp); |
318 | extern int param_get_ulong(char *buffer, const struct kernel_param *kp); | ||
191 | #define param_check_ulong(name, p) __param_check(name, p, unsigned long) | 319 | #define param_check_ulong(name, p) __param_check(name, p, unsigned long) |
192 | 320 | ||
193 | extern int param_set_charp(const char *val, struct kernel_param *kp); | 321 | extern struct kernel_param_ops param_ops_charp; |
194 | extern int param_get_charp(char *buffer, struct kernel_param *kp); | 322 | extern int param_set_charp(const char *val, const struct kernel_param *kp); |
323 | extern int param_get_charp(char *buffer, const struct kernel_param *kp); | ||
195 | #define param_check_charp(name, p) __param_check(name, p, char *) | 324 | #define param_check_charp(name, p) __param_check(name, p, char *) |
196 | 325 | ||
197 | /* For historical reasons "bool" parameters can be (unsigned) "int". */ | 326 | /* For historical reasons "bool" parameters can be (unsigned) "int". */ |
198 | extern int param_set_bool(const char *val, struct kernel_param *kp); | 327 | extern struct kernel_param_ops param_ops_bool; |
199 | extern int param_get_bool(char *buffer, struct kernel_param *kp); | 328 | extern int param_set_bool(const char *val, const struct kernel_param *kp); |
329 | extern int param_get_bool(char *buffer, const struct kernel_param *kp); | ||
200 | #define param_check_bool(name, p) \ | 330 | #define param_check_bool(name, p) \ |
201 | static inline void __check_##name(void) \ | 331 | static inline void __check_##name(void) \ |
202 | { \ | 332 | { \ |
203 | BUILD_BUG_ON(!__same_type(*(p), bool) && \ | 333 | BUILD_BUG_ON(!__same_type((p), bool *) && \ |
204 | !__same_type(*(p), unsigned int) && \ | 334 | !__same_type((p), unsigned int *) && \ |
205 | !__same_type(*(p), int)); \ | 335 | !__same_type((p), int *)); \ |
206 | } | 336 | } |
207 | 337 | ||
208 | extern int param_set_invbool(const char *val, struct kernel_param *kp); | 338 | extern struct kernel_param_ops param_ops_invbool; |
209 | extern int param_get_invbool(char *buffer, struct kernel_param *kp); | 339 | extern int param_set_invbool(const char *val, const struct kernel_param *kp); |
340 | extern int param_get_invbool(char *buffer, const struct kernel_param *kp); | ||
210 | #define param_check_invbool(name, p) __param_check(name, p, bool) | 341 | #define param_check_invbool(name, p) __param_check(name, p, bool) |
211 | 342 | ||
212 | /* Comma-separated array: *nump is set to number they actually specified. */ | 343 | /** |
344 | * module_param_array - a parameter which is an array of some type | ||
345 | * @name: the name of the array variable | ||
346 | * @type: the type, as per module_param() | ||
347 | * @nump: optional pointer filled in with the number written | ||
348 | * @perm: visibility in sysfs | ||
349 | * | ||
350 | * Input and output are as comma-separated values. Commas inside values | ||
351 | * don't work properly (eg. an array of charp). | ||
352 | * | ||
353 | * ARRAY_SIZE(@name) is used to determine the number of elements in the | ||
354 | * array, so the definition must be visible. | ||
355 | */ | ||
356 | #define module_param_array(name, type, nump, perm) \ | ||
357 | module_param_array_named(name, name, type, nump, perm) | ||
358 | |||
359 | /** | ||
360 | * module_param_array_named - renamed parameter which is an array of some type | ||
361 | * @name: a valid C identifier which is the parameter name | ||
362 | * @array: the name of the array variable | ||
363 | * @type: the type, as per module_param() | ||
364 | * @nump: optional pointer filled in with the number written | ||
365 | * @perm: visibility in sysfs | ||
366 | * | ||
367 | * This exposes a different name than the actual variable name. See | ||
368 | * module_param_named() for why this might be necessary. | ||
369 | */ | ||
213 | #define module_param_array_named(name, array, type, nump, perm) \ | 370 | #define module_param_array_named(name, array, type, nump, perm) \ |
214 | static const struct kparam_array __param_arr_##name \ | 371 | static const struct kparam_array __param_arr_##name \ |
215 | = { ARRAY_SIZE(array), nump, param_set_##type, param_get_##type,\ | 372 | = { ARRAY_SIZE(array), nump, ¶m_ops_##type, \ |
216 | sizeof(array[0]), array }; \ | 373 | sizeof(array[0]), array }; \ |
217 | __module_param_call(MODULE_PARAM_PREFIX, name, \ | 374 | __module_param_call(MODULE_PARAM_PREFIX, name, \ |
218 | param_array_set, param_array_get, \ | 375 | ¶m_array_ops, \ |
219 | .arr = &__param_arr_##name, \ | 376 | .arr = &__param_arr_##name, \ |
220 | __same_type(array[0], bool), perm); \ | 377 | __same_type(array[0], bool), perm); \ |
221 | __MODULE_PARM_TYPE(name, "array of " #type) | 378 | __MODULE_PARM_TYPE(name, "array of " #type) |
222 | 379 | ||
223 | #define module_param_array(name, type, nump, perm) \ | 380 | extern struct kernel_param_ops param_array_ops; |
224 | module_param_array_named(name, name, type, nump, perm) | ||
225 | |||
226 | extern int param_array_set(const char *val, struct kernel_param *kp); | ||
227 | extern int param_array_get(char *buffer, struct kernel_param *kp); | ||
228 | 381 | ||
229 | extern int param_set_copystring(const char *val, struct kernel_param *kp); | 382 | extern struct kernel_param_ops param_ops_string; |
230 | extern int param_get_string(char *buffer, struct kernel_param *kp); | 383 | extern int param_set_copystring(const char *val, const struct kernel_param *); |
384 | extern int param_get_string(char *buffer, const struct kernel_param *kp); | ||
231 | 385 | ||
232 | /* for exporting parameters in /sys/parameters */ | 386 | /* for exporting parameters in /sys/parameters */ |
233 | 387 | ||
@@ -235,13 +389,13 @@ struct module; | |||
235 | 389 | ||
236 | #if defined(CONFIG_SYSFS) && defined(CONFIG_MODULES) | 390 | #if defined(CONFIG_SYSFS) && defined(CONFIG_MODULES) |
237 | extern int module_param_sysfs_setup(struct module *mod, | 391 | extern int module_param_sysfs_setup(struct module *mod, |
238 | struct kernel_param *kparam, | 392 | const struct kernel_param *kparam, |
239 | unsigned int num_params); | 393 | unsigned int num_params); |
240 | 394 | ||
241 | extern void module_param_sysfs_remove(struct module *mod); | 395 | extern void module_param_sysfs_remove(struct module *mod); |
242 | #else | 396 | #else |
243 | static inline int module_param_sysfs_setup(struct module *mod, | 397 | static inline int module_param_sysfs_setup(struct module *mod, |
244 | struct kernel_param *kparam, | 398 | const struct kernel_param *kparam, |
245 | unsigned int num_params) | 399 | unsigned int num_params) |
246 | { | 400 | { |
247 | return 0; | 401 | return 0; |
diff --git a/init/main.c b/init/main.c index 86cbfd085b01..22d61cb06f98 100644 --- a/init/main.c +++ b/init/main.c | |||
@@ -201,11 +201,11 @@ static char * argv_init[MAX_INIT_ARGS+2] = { "init", NULL, }; | |||
201 | char * envp_init[MAX_INIT_ENVS+2] = { "HOME=/", "TERM=linux", NULL, }; | 201 | char * envp_init[MAX_INIT_ENVS+2] = { "HOME=/", "TERM=linux", NULL, }; |
202 | static const char *panic_later, *panic_param; | 202 | static const char *panic_later, *panic_param; |
203 | 203 | ||
204 | extern struct obs_kernel_param __setup_start[], __setup_end[]; | 204 | extern const struct obs_kernel_param __setup_start[], __setup_end[]; |
205 | 205 | ||
206 | static int __init obsolete_checksetup(char *line) | 206 | static int __init obsolete_checksetup(char *line) |
207 | { | 207 | { |
208 | struct obs_kernel_param *p; | 208 | const struct obs_kernel_param *p; |
209 | int had_early_param = 0; | 209 | int had_early_param = 0; |
210 | 210 | ||
211 | p = __setup_start; | 211 | p = __setup_start; |
@@ -458,7 +458,7 @@ static noinline void __init_refok rest_init(void) | |||
458 | /* Check for early params. */ | 458 | /* Check for early params. */ |
459 | static int __init do_early_param(char *param, char *val) | 459 | static int __init do_early_param(char *param, char *val) |
460 | { | 460 | { |
461 | struct obs_kernel_param *p; | 461 | const struct obs_kernel_param *p; |
462 | 462 | ||
463 | for (p = __setup_start; p < __setup_end; p++) { | 463 | for (p = __setup_start; p < __setup_end; p++) { |
464 | if ((p->early && strcmp(param, p->str) == 0) || | 464 | if ((p->early && strcmp(param, p->str) == 0) || |
@@ -536,7 +536,7 @@ static void __init mm_init(void) | |||
536 | asmlinkage void __init start_kernel(void) | 536 | asmlinkage void __init start_kernel(void) |
537 | { | 537 | { |
538 | char * command_line; | 538 | char * command_line; |
539 | extern struct kernel_param __start___param[], __stop___param[]; | 539 | extern const struct kernel_param __start___param[], __stop___param[]; |
540 | 540 | ||
541 | smp_setup_processor_id(); | 541 | smp_setup_processor_id(); |
542 | 542 | ||
diff --git a/kernel/params.c b/kernel/params.c index 0b30ecd53a52..08107d181758 100644 --- a/kernel/params.c +++ b/kernel/params.c | |||
@@ -31,6 +31,42 @@ | |||
31 | #define DEBUGP(fmt, a...) | 31 | #define DEBUGP(fmt, a...) |
32 | #endif | 32 | #endif |
33 | 33 | ||
34 | /* Protects all parameters, and incidentally kmalloced_param list. */ | ||
35 | static DEFINE_MUTEX(param_lock); | ||
36 | |||
37 | /* This just allows us to keep track of which parameters are kmalloced. */ | ||
38 | struct kmalloced_param { | ||
39 | struct list_head list; | ||
40 | char val[]; | ||
41 | }; | ||
42 | static LIST_HEAD(kmalloced_params); | ||
43 | |||
44 | static void *kmalloc_parameter(unsigned int size) | ||
45 | { | ||
46 | struct kmalloced_param *p; | ||
47 | |||
48 | p = kmalloc(sizeof(*p) + size, GFP_KERNEL); | ||
49 | if (!p) | ||
50 | return NULL; | ||
51 | |||
52 | list_add(&p->list, &kmalloced_params); | ||
53 | return p->val; | ||
54 | } | ||
55 | |||
56 | /* Does nothing if parameter wasn't kmalloced above. */ | ||
57 | static void maybe_kfree_parameter(void *param) | ||
58 | { | ||
59 | struct kmalloced_param *p; | ||
60 | |||
61 | list_for_each_entry(p, &kmalloced_params, list) { | ||
62 | if (p->val == param) { | ||
63 | list_del(&p->list); | ||
64 | kfree(p); | ||
65 | break; | ||
66 | } | ||
67 | } | ||
68 | } | ||
69 | |||
34 | static inline char dash2underscore(char c) | 70 | static inline char dash2underscore(char c) |
35 | { | 71 | { |
36 | if (c == '-') | 72 | if (c == '-') |
@@ -49,18 +85,25 @@ static inline int parameq(const char *input, const char *paramname) | |||
49 | 85 | ||
50 | static int parse_one(char *param, | 86 | static int parse_one(char *param, |
51 | char *val, | 87 | char *val, |
52 | struct kernel_param *params, | 88 | const struct kernel_param *params, |
53 | unsigned num_params, | 89 | unsigned num_params, |
54 | int (*handle_unknown)(char *param, char *val)) | 90 | int (*handle_unknown)(char *param, char *val)) |
55 | { | 91 | { |
56 | unsigned int i; | 92 | unsigned int i; |
93 | int err; | ||
57 | 94 | ||
58 | /* Find parameter */ | 95 | /* Find parameter */ |
59 | for (i = 0; i < num_params; i++) { | 96 | for (i = 0; i < num_params; i++) { |
60 | if (parameq(param, params[i].name)) { | 97 | if (parameq(param, params[i].name)) { |
98 | /* Noone handled NULL, so do it here. */ | ||
99 | if (!val && params[i].ops->set != param_set_bool) | ||
100 | return -EINVAL; | ||
61 | DEBUGP("They are equal! Calling %p\n", | 101 | DEBUGP("They are equal! Calling %p\n", |
62 | params[i].set); | 102 | params[i].ops->set); |
63 | return params[i].set(val, ¶ms[i]); | 103 | mutex_lock(¶m_lock); |
104 | err = params[i].ops->set(val, ¶ms[i]); | ||
105 | mutex_unlock(¶m_lock); | ||
106 | return err; | ||
64 | } | 107 | } |
65 | } | 108 | } |
66 | 109 | ||
@@ -128,7 +171,7 @@ static char *next_arg(char *args, char **param, char **val) | |||
128 | /* Args looks like "foo=bar,bar2 baz=fuz wiz". */ | 171 | /* Args looks like "foo=bar,bar2 baz=fuz wiz". */ |
129 | int parse_args(const char *name, | 172 | int parse_args(const char *name, |
130 | char *args, | 173 | char *args, |
131 | struct kernel_param *params, | 174 | const struct kernel_param *params, |
132 | unsigned num, | 175 | unsigned num, |
133 | int (*unknown)(char *param, char *val)) | 176 | int (*unknown)(char *param, char *val)) |
134 | { | 177 | { |
@@ -176,22 +219,29 @@ int parse_args(const char *name, | |||
176 | 219 | ||
177 | /* Lazy bastard, eh? */ | 220 | /* Lazy bastard, eh? */ |
178 | #define STANDARD_PARAM_DEF(name, type, format, tmptype, strtolfn) \ | 221 | #define STANDARD_PARAM_DEF(name, type, format, tmptype, strtolfn) \ |
179 | int param_set_##name(const char *val, struct kernel_param *kp) \ | 222 | int param_set_##name(const char *val, const struct kernel_param *kp) \ |
180 | { \ | 223 | { \ |
181 | tmptype l; \ | 224 | tmptype l; \ |
182 | int ret; \ | 225 | int ret; \ |
183 | \ | 226 | \ |
184 | if (!val) return -EINVAL; \ | ||
185 | ret = strtolfn(val, 0, &l); \ | 227 | ret = strtolfn(val, 0, &l); \ |
186 | if (ret == -EINVAL || ((type)l != l)) \ | 228 | if (ret == -EINVAL || ((type)l != l)) \ |
187 | return -EINVAL; \ | 229 | return -EINVAL; \ |
188 | *((type *)kp->arg) = l; \ | 230 | *((type *)kp->arg) = l; \ |
189 | return 0; \ | 231 | return 0; \ |
190 | } \ | 232 | } \ |
191 | int param_get_##name(char *buffer, struct kernel_param *kp) \ | 233 | int param_get_##name(char *buffer, const struct kernel_param *kp) \ |
192 | { \ | 234 | { \ |
193 | return sprintf(buffer, format, *((type *)kp->arg)); \ | 235 | return sprintf(buffer, format, *((type *)kp->arg)); \ |
194 | } | 236 | } \ |
237 | struct kernel_param_ops param_ops_##name = { \ | ||
238 | .set = param_set_##name, \ | ||
239 | .get = param_get_##name, \ | ||
240 | }; \ | ||
241 | EXPORT_SYMBOL(param_set_##name); \ | ||
242 | EXPORT_SYMBOL(param_get_##name); \ | ||
243 | EXPORT_SYMBOL(param_ops_##name) | ||
244 | |||
195 | 245 | ||
196 | STANDARD_PARAM_DEF(byte, unsigned char, "%c", unsigned long, strict_strtoul); | 246 | STANDARD_PARAM_DEF(byte, unsigned char, "%c", unsigned long, strict_strtoul); |
197 | STANDARD_PARAM_DEF(short, short, "%hi", long, strict_strtol); | 247 | STANDARD_PARAM_DEF(short, short, "%hi", long, strict_strtol); |
@@ -201,39 +251,50 @@ STANDARD_PARAM_DEF(uint, unsigned int, "%u", unsigned long, strict_strtoul); | |||
201 | STANDARD_PARAM_DEF(long, long, "%li", long, strict_strtol); | 251 | STANDARD_PARAM_DEF(long, long, "%li", long, strict_strtol); |
202 | STANDARD_PARAM_DEF(ulong, unsigned long, "%lu", unsigned long, strict_strtoul); | 252 | STANDARD_PARAM_DEF(ulong, unsigned long, "%lu", unsigned long, strict_strtoul); |
203 | 253 | ||
204 | int param_set_charp(const char *val, struct kernel_param *kp) | 254 | int param_set_charp(const char *val, const struct kernel_param *kp) |
205 | { | 255 | { |
206 | if (!val) { | ||
207 | printk(KERN_ERR "%s: string parameter expected\n", | ||
208 | kp->name); | ||
209 | return -EINVAL; | ||
210 | } | ||
211 | |||
212 | if (strlen(val) > 1024) { | 256 | if (strlen(val) > 1024) { |
213 | printk(KERN_ERR "%s: string parameter too long\n", | 257 | printk(KERN_ERR "%s: string parameter too long\n", |
214 | kp->name); | 258 | kp->name); |
215 | return -ENOSPC; | 259 | return -ENOSPC; |
216 | } | 260 | } |
217 | 261 | ||
218 | /* This is a hack. We can't need to strdup in early boot, and we | 262 | maybe_kfree_parameter(*(char **)kp->arg); |
263 | |||
264 | /* This is a hack. We can't kmalloc in early boot, and we | ||
219 | * don't need to; this mangled commandline is preserved. */ | 265 | * don't need to; this mangled commandline is preserved. */ |
220 | if (slab_is_available()) { | 266 | if (slab_is_available()) { |
221 | *(char **)kp->arg = kstrdup(val, GFP_KERNEL); | 267 | *(char **)kp->arg = kmalloc_parameter(strlen(val)+1); |
222 | if (!*(char **)kp->arg) | 268 | if (!*(char **)kp->arg) |
223 | return -ENOMEM; | 269 | return -ENOMEM; |
270 | strcpy(*(char **)kp->arg, val); | ||
224 | } else | 271 | } else |
225 | *(const char **)kp->arg = val; | 272 | *(const char **)kp->arg = val; |
226 | 273 | ||
227 | return 0; | 274 | return 0; |
228 | } | 275 | } |
276 | EXPORT_SYMBOL(param_set_charp); | ||
229 | 277 | ||
230 | int param_get_charp(char *buffer, struct kernel_param *kp) | 278 | int param_get_charp(char *buffer, const struct kernel_param *kp) |
231 | { | 279 | { |
232 | return sprintf(buffer, "%s", *((char **)kp->arg)); | 280 | return sprintf(buffer, "%s", *((char **)kp->arg)); |
233 | } | 281 | } |
282 | EXPORT_SYMBOL(param_get_charp); | ||
283 | |||
284 | static void param_free_charp(void *arg) | ||
285 | { | ||
286 | maybe_kfree_parameter(*((char **)arg)); | ||
287 | } | ||
288 | |||
289 | struct kernel_param_ops param_ops_charp = { | ||
290 | .set = param_set_charp, | ||
291 | .get = param_get_charp, | ||
292 | .free = param_free_charp, | ||
293 | }; | ||
294 | EXPORT_SYMBOL(param_ops_charp); | ||
234 | 295 | ||
235 | /* Actually could be a bool or an int, for historical reasons. */ | 296 | /* Actually could be a bool or an int, for historical reasons. */ |
236 | int param_set_bool(const char *val, struct kernel_param *kp) | 297 | int param_set_bool(const char *val, const struct kernel_param *kp) |
237 | { | 298 | { |
238 | bool v; | 299 | bool v; |
239 | 300 | ||
@@ -258,8 +319,9 @@ int param_set_bool(const char *val, struct kernel_param *kp) | |||
258 | *(int *)kp->arg = v; | 319 | *(int *)kp->arg = v; |
259 | return 0; | 320 | return 0; |
260 | } | 321 | } |
322 | EXPORT_SYMBOL(param_set_bool); | ||
261 | 323 | ||
262 | int param_get_bool(char *buffer, struct kernel_param *kp) | 324 | int param_get_bool(char *buffer, const struct kernel_param *kp) |
263 | { | 325 | { |
264 | bool val; | 326 | bool val; |
265 | if (kp->flags & KPARAM_ISBOOL) | 327 | if (kp->flags & KPARAM_ISBOOL) |
@@ -270,9 +332,16 @@ int param_get_bool(char *buffer, struct kernel_param *kp) | |||
270 | /* Y and N chosen as being relatively non-coder friendly */ | 332 | /* Y and N chosen as being relatively non-coder friendly */ |
271 | return sprintf(buffer, "%c", val ? 'Y' : 'N'); | 333 | return sprintf(buffer, "%c", val ? 'Y' : 'N'); |
272 | } | 334 | } |
335 | EXPORT_SYMBOL(param_get_bool); | ||
336 | |||
337 | struct kernel_param_ops param_ops_bool = { | ||
338 | .set = param_set_bool, | ||
339 | .get = param_get_bool, | ||
340 | }; | ||
341 | EXPORT_SYMBOL(param_ops_bool); | ||
273 | 342 | ||
274 | /* This one must be bool. */ | 343 | /* This one must be bool. */ |
275 | int param_set_invbool(const char *val, struct kernel_param *kp) | 344 | int param_set_invbool(const char *val, const struct kernel_param *kp) |
276 | { | 345 | { |
277 | int ret; | 346 | int ret; |
278 | bool boolval; | 347 | bool boolval; |
@@ -285,18 +354,26 @@ int param_set_invbool(const char *val, struct kernel_param *kp) | |||
285 | *(bool *)kp->arg = !boolval; | 354 | *(bool *)kp->arg = !boolval; |
286 | return ret; | 355 | return ret; |
287 | } | 356 | } |
357 | EXPORT_SYMBOL(param_set_invbool); | ||
288 | 358 | ||
289 | int param_get_invbool(char *buffer, struct kernel_param *kp) | 359 | int param_get_invbool(char *buffer, const struct kernel_param *kp) |
290 | { | 360 | { |
291 | return sprintf(buffer, "%c", (*(bool *)kp->arg) ? 'N' : 'Y'); | 361 | return sprintf(buffer, "%c", (*(bool *)kp->arg) ? 'N' : 'Y'); |
292 | } | 362 | } |
363 | EXPORT_SYMBOL(param_get_invbool); | ||
364 | |||
365 | struct kernel_param_ops param_ops_invbool = { | ||
366 | .set = param_set_invbool, | ||
367 | .get = param_get_invbool, | ||
368 | }; | ||
369 | EXPORT_SYMBOL(param_ops_invbool); | ||
293 | 370 | ||
294 | /* We break the rule and mangle the string. */ | 371 | /* We break the rule and mangle the string. */ |
295 | static int param_array(const char *name, | 372 | static int param_array(const char *name, |
296 | const char *val, | 373 | const char *val, |
297 | unsigned int min, unsigned int max, | 374 | unsigned int min, unsigned int max, |
298 | void *elem, int elemsize, | 375 | void *elem, int elemsize, |
299 | int (*set)(const char *, struct kernel_param *kp), | 376 | int (*set)(const char *, const struct kernel_param *kp), |
300 | u16 flags, | 377 | u16 flags, |
301 | unsigned int *num) | 378 | unsigned int *num) |
302 | { | 379 | { |
@@ -309,12 +386,6 @@ static int param_array(const char *name, | |||
309 | kp.arg = elem; | 386 | kp.arg = elem; |
310 | kp.flags = flags; | 387 | kp.flags = flags; |
311 | 388 | ||
312 | /* No equals sign? */ | ||
313 | if (!val) { | ||
314 | printk(KERN_ERR "%s: expects arguments\n", name); | ||
315 | return -EINVAL; | ||
316 | } | ||
317 | |||
318 | *num = 0; | 389 | *num = 0; |
319 | /* We expect a comma-separated list of values. */ | 390 | /* We expect a comma-separated list of values. */ |
320 | do { | 391 | do { |
@@ -330,6 +401,7 @@ static int param_array(const char *name, | |||
330 | /* nul-terminate and parse */ | 401 | /* nul-terminate and parse */ |
331 | save = val[len]; | 402 | save = val[len]; |
332 | ((char *)val)[len] = '\0'; | 403 | ((char *)val)[len] = '\0'; |
404 | BUG_ON(!mutex_is_locked(¶m_lock)); | ||
333 | ret = set(val, &kp); | 405 | ret = set(val, &kp); |
334 | 406 | ||
335 | if (ret != 0) | 407 | if (ret != 0) |
@@ -347,17 +419,17 @@ static int param_array(const char *name, | |||
347 | return 0; | 419 | return 0; |
348 | } | 420 | } |
349 | 421 | ||
350 | int param_array_set(const char *val, struct kernel_param *kp) | 422 | static int param_array_set(const char *val, const struct kernel_param *kp) |
351 | { | 423 | { |
352 | const struct kparam_array *arr = kp->arr; | 424 | const struct kparam_array *arr = kp->arr; |
353 | unsigned int temp_num; | 425 | unsigned int temp_num; |
354 | 426 | ||
355 | return param_array(kp->name, val, 1, arr->max, arr->elem, | 427 | return param_array(kp->name, val, 1, arr->max, arr->elem, |
356 | arr->elemsize, arr->set, kp->flags, | 428 | arr->elemsize, arr->ops->set, kp->flags, |
357 | arr->num ?: &temp_num); | 429 | arr->num ?: &temp_num); |
358 | } | 430 | } |
359 | 431 | ||
360 | int param_array_get(char *buffer, struct kernel_param *kp) | 432 | static int param_array_get(char *buffer, const struct kernel_param *kp) |
361 | { | 433 | { |
362 | int i, off, ret; | 434 | int i, off, ret; |
363 | const struct kparam_array *arr = kp->arr; | 435 | const struct kparam_array *arr = kp->arr; |
@@ -368,7 +440,8 @@ int param_array_get(char *buffer, struct kernel_param *kp) | |||
368 | if (i) | 440 | if (i) |
369 | buffer[off++] = ','; | 441 | buffer[off++] = ','; |
370 | p.arg = arr->elem + arr->elemsize * i; | 442 | p.arg = arr->elem + arr->elemsize * i; |
371 | ret = arr->get(buffer + off, &p); | 443 | BUG_ON(!mutex_is_locked(¶m_lock)); |
444 | ret = arr->ops->get(buffer + off, &p); | ||
372 | if (ret < 0) | 445 | if (ret < 0) |
373 | return ret; | 446 | return ret; |
374 | off += ret; | 447 | off += ret; |
@@ -377,14 +450,27 @@ int param_array_get(char *buffer, struct kernel_param *kp) | |||
377 | return off; | 450 | return off; |
378 | } | 451 | } |
379 | 452 | ||
380 | int param_set_copystring(const char *val, struct kernel_param *kp) | 453 | static void param_array_free(void *arg) |
454 | { | ||
455 | unsigned int i; | ||
456 | const struct kparam_array *arr = arg; | ||
457 | |||
458 | if (arr->ops->free) | ||
459 | for (i = 0; i < (arr->num ? *arr->num : arr->max); i++) | ||
460 | arr->ops->free(arr->elem + arr->elemsize * i); | ||
461 | } | ||
462 | |||
463 | struct kernel_param_ops param_array_ops = { | ||
464 | .set = param_array_set, | ||
465 | .get = param_array_get, | ||
466 | .free = param_array_free, | ||
467 | }; | ||
468 | EXPORT_SYMBOL(param_array_ops); | ||
469 | |||
470 | int param_set_copystring(const char *val, const struct kernel_param *kp) | ||
381 | { | 471 | { |
382 | const struct kparam_string *kps = kp->str; | 472 | const struct kparam_string *kps = kp->str; |
383 | 473 | ||
384 | if (!val) { | ||
385 | printk(KERN_ERR "%s: missing param set value\n", kp->name); | ||
386 | return -EINVAL; | ||
387 | } | ||
388 | if (strlen(val)+1 > kps->maxlen) { | 474 | if (strlen(val)+1 > kps->maxlen) { |
389 | printk(KERN_ERR "%s: string doesn't fit in %u chars.\n", | 475 | printk(KERN_ERR "%s: string doesn't fit in %u chars.\n", |
390 | kp->name, kps->maxlen-1); | 476 | kp->name, kps->maxlen-1); |
@@ -393,12 +479,20 @@ int param_set_copystring(const char *val, struct kernel_param *kp) | |||
393 | strcpy(kps->string, val); | 479 | strcpy(kps->string, val); |
394 | return 0; | 480 | return 0; |
395 | } | 481 | } |
482 | EXPORT_SYMBOL(param_set_copystring); | ||
396 | 483 | ||
397 | int param_get_string(char *buffer, struct kernel_param *kp) | 484 | int param_get_string(char *buffer, const struct kernel_param *kp) |
398 | { | 485 | { |
399 | const struct kparam_string *kps = kp->str; | 486 | const struct kparam_string *kps = kp->str; |
400 | return strlcpy(buffer, kps->string, kps->maxlen); | 487 | return strlcpy(buffer, kps->string, kps->maxlen); |
401 | } | 488 | } |
489 | EXPORT_SYMBOL(param_get_string); | ||
490 | |||
491 | struct kernel_param_ops param_ops_string = { | ||
492 | .set = param_set_copystring, | ||
493 | .get = param_get_string, | ||
494 | }; | ||
495 | EXPORT_SYMBOL(param_ops_string); | ||
402 | 496 | ||
403 | /* sysfs output in /sys/modules/XYZ/parameters/ */ | 497 | /* sysfs output in /sys/modules/XYZ/parameters/ */ |
404 | #define to_module_attr(n) container_of(n, struct module_attribute, attr) | 498 | #define to_module_attr(n) container_of(n, struct module_attribute, attr) |
@@ -409,7 +503,7 @@ extern struct kernel_param __start___param[], __stop___param[]; | |||
409 | struct param_attribute | 503 | struct param_attribute |
410 | { | 504 | { |
411 | struct module_attribute mattr; | 505 | struct module_attribute mattr; |
412 | struct kernel_param *param; | 506 | const struct kernel_param *param; |
413 | }; | 507 | }; |
414 | 508 | ||
415 | struct module_param_attrs | 509 | struct module_param_attrs |
@@ -428,10 +522,12 @@ static ssize_t param_attr_show(struct module_attribute *mattr, | |||
428 | int count; | 522 | int count; |
429 | struct param_attribute *attribute = to_param_attr(mattr); | 523 | struct param_attribute *attribute = to_param_attr(mattr); |
430 | 524 | ||
431 | if (!attribute->param->get) | 525 | if (!attribute->param->ops->get) |
432 | return -EPERM; | 526 | return -EPERM; |
433 | 527 | ||
434 | count = attribute->param->get(buf, attribute->param); | 528 | mutex_lock(¶m_lock); |
529 | count = attribute->param->ops->get(buf, attribute->param); | ||
530 | mutex_unlock(¶m_lock); | ||
435 | if (count > 0) { | 531 | if (count > 0) { |
436 | strcat(buf, "\n"); | 532 | strcat(buf, "\n"); |
437 | ++count; | 533 | ++count; |
@@ -447,10 +543,12 @@ static ssize_t param_attr_store(struct module_attribute *mattr, | |||
447 | int err; | 543 | int err; |
448 | struct param_attribute *attribute = to_param_attr(mattr); | 544 | struct param_attribute *attribute = to_param_attr(mattr); |
449 | 545 | ||
450 | if (!attribute->param->set) | 546 | if (!attribute->param->ops->set) |
451 | return -EPERM; | 547 | return -EPERM; |
452 | 548 | ||
453 | err = attribute->param->set(buf, attribute->param); | 549 | mutex_lock(¶m_lock); |
550 | err = attribute->param->ops->set(buf, attribute->param); | ||
551 | mutex_unlock(¶m_lock); | ||
454 | if (!err) | 552 | if (!err) |
455 | return len; | 553 | return len; |
456 | return err; | 554 | return err; |
@@ -464,6 +562,18 @@ static ssize_t param_attr_store(struct module_attribute *mattr, | |||
464 | #endif | 562 | #endif |
465 | 563 | ||
466 | #ifdef CONFIG_SYSFS | 564 | #ifdef CONFIG_SYSFS |
565 | void __kernel_param_lock(void) | ||
566 | { | ||
567 | mutex_lock(¶m_lock); | ||
568 | } | ||
569 | EXPORT_SYMBOL(__kernel_param_lock); | ||
570 | |||
571 | void __kernel_param_unlock(void) | ||
572 | { | ||
573 | mutex_unlock(¶m_lock); | ||
574 | } | ||
575 | EXPORT_SYMBOL(__kernel_param_unlock); | ||
576 | |||
467 | /* | 577 | /* |
468 | * add_sysfs_param - add a parameter to sysfs | 578 | * add_sysfs_param - add a parameter to sysfs |
469 | * @mk: struct module_kobject | 579 | * @mk: struct module_kobject |
@@ -475,7 +585,7 @@ static ssize_t param_attr_store(struct module_attribute *mattr, | |||
475 | * if there's an error. | 585 | * if there's an error. |
476 | */ | 586 | */ |
477 | static __modinit int add_sysfs_param(struct module_kobject *mk, | 587 | static __modinit int add_sysfs_param(struct module_kobject *mk, |
478 | struct kernel_param *kp, | 588 | const struct kernel_param *kp, |
479 | const char *name) | 589 | const char *name) |
480 | { | 590 | { |
481 | struct module_param_attrs *new; | 591 | struct module_param_attrs *new; |
@@ -557,7 +667,7 @@ static void free_module_param_attrs(struct module_kobject *mk) | |||
557 | * /sys/module/[mod->name]/parameters/ | 667 | * /sys/module/[mod->name]/parameters/ |
558 | */ | 668 | */ |
559 | int module_param_sysfs_setup(struct module *mod, | 669 | int module_param_sysfs_setup(struct module *mod, |
560 | struct kernel_param *kparam, | 670 | const struct kernel_param *kparam, |
561 | unsigned int num_params) | 671 | unsigned int num_params) |
562 | { | 672 | { |
563 | int i, err; | 673 | int i, err; |
@@ -602,7 +712,11 @@ void module_param_sysfs_remove(struct module *mod) | |||
602 | 712 | ||
603 | void destroy_params(const struct kernel_param *params, unsigned num) | 713 | void destroy_params(const struct kernel_param *params, unsigned num) |
604 | { | 714 | { |
605 | /* FIXME: This should free kmalloced charp parameters. It doesn't. */ | 715 | unsigned int i; |
716 | |||
717 | for (i = 0; i < num; i++) | ||
718 | if (params[i].ops->free) | ||
719 | params[i].ops->free(params[i].arg); | ||
606 | } | 720 | } |
607 | 721 | ||
608 | static void __init kernel_add_sysfs_param(const char *name, | 722 | static void __init kernel_add_sysfs_param(const char *name, |
@@ -768,28 +882,3 @@ static int __init param_sysfs_init(void) | |||
768 | subsys_initcall(param_sysfs_init); | 882 | subsys_initcall(param_sysfs_init); |
769 | 883 | ||
770 | #endif /* CONFIG_SYSFS */ | 884 | #endif /* CONFIG_SYSFS */ |
771 | |||
772 | EXPORT_SYMBOL(param_set_byte); | ||
773 | EXPORT_SYMBOL(param_get_byte); | ||
774 | EXPORT_SYMBOL(param_set_short); | ||
775 | EXPORT_SYMBOL(param_get_short); | ||
776 | EXPORT_SYMBOL(param_set_ushort); | ||
777 | EXPORT_SYMBOL(param_get_ushort); | ||
778 | EXPORT_SYMBOL(param_set_int); | ||
779 | EXPORT_SYMBOL(param_get_int); | ||
780 | EXPORT_SYMBOL(param_set_uint); | ||
781 | EXPORT_SYMBOL(param_get_uint); | ||
782 | EXPORT_SYMBOL(param_set_long); | ||
783 | EXPORT_SYMBOL(param_get_long); | ||
784 | EXPORT_SYMBOL(param_set_ulong); | ||
785 | EXPORT_SYMBOL(param_get_ulong); | ||
786 | EXPORT_SYMBOL(param_set_charp); | ||
787 | EXPORT_SYMBOL(param_get_charp); | ||
788 | EXPORT_SYMBOL(param_set_bool); | ||
789 | EXPORT_SYMBOL(param_get_bool); | ||
790 | EXPORT_SYMBOL(param_set_invbool); | ||
791 | EXPORT_SYMBOL(param_get_invbool); | ||
792 | EXPORT_SYMBOL(param_array_set); | ||
793 | EXPORT_SYMBOL(param_array_get); | ||
794 | EXPORT_SYMBOL(param_set_copystring); | ||
795 | EXPORT_SYMBOL(param_get_string); | ||
diff --git a/net/mac80211/rate.c b/net/mac80211/rate.c index 6d0bd198af19..be04d46110fe 100644 --- a/net/mac80211/rate.c +++ b/net/mac80211/rate.c | |||
@@ -103,6 +103,7 @@ ieee80211_rate_control_ops_get(const char *name) | |||
103 | struct rate_control_ops *ops; | 103 | struct rate_control_ops *ops; |
104 | const char *alg_name; | 104 | const char *alg_name; |
105 | 105 | ||
106 | kparam_block_sysfs_write(ieee80211_default_rc_algo); | ||
106 | if (!name) | 107 | if (!name) |
107 | alg_name = ieee80211_default_rc_algo; | 108 | alg_name = ieee80211_default_rc_algo; |
108 | else | 109 | else |
@@ -120,6 +121,7 @@ ieee80211_rate_control_ops_get(const char *name) | |||
120 | /* try built-in one if specific alg requested but not found */ | 121 | /* try built-in one if specific alg requested but not found */ |
121 | if (!ops && strlen(CONFIG_MAC80211_RC_DEFAULT)) | 122 | if (!ops && strlen(CONFIG_MAC80211_RC_DEFAULT)) |
122 | ops = ieee80211_try_rate_control_ops_get(CONFIG_MAC80211_RC_DEFAULT); | 123 | ops = ieee80211_try_rate_control_ops_get(CONFIG_MAC80211_RC_DEFAULT); |
124 | kparam_unblock_sysfs_write(ieee80211_default_rc_algo); | ||
123 | 125 | ||
124 | return ops; | 126 | return ops; |
125 | } | 127 | } |
diff --git a/net/sunrpc/auth.c b/net/sunrpc/auth.c index 880d0de3f50f..36cb66022a27 100644 --- a/net/sunrpc/auth.c +++ b/net/sunrpc/auth.c | |||
@@ -39,7 +39,7 @@ static LIST_HEAD(cred_unused); | |||
39 | static unsigned long number_cred_unused; | 39 | static unsigned long number_cred_unused; |
40 | 40 | ||
41 | #define MAX_HASHTABLE_BITS (10) | 41 | #define MAX_HASHTABLE_BITS (10) |
42 | static int param_set_hashtbl_sz(const char *val, struct kernel_param *kp) | 42 | static int param_set_hashtbl_sz(const char *val, const struct kernel_param *kp) |
43 | { | 43 | { |
44 | unsigned long num; | 44 | unsigned long num; |
45 | unsigned int nbits; | 45 | unsigned int nbits; |
@@ -61,7 +61,7 @@ out_inval: | |||
61 | return -EINVAL; | 61 | return -EINVAL; |
62 | } | 62 | } |
63 | 63 | ||
64 | static int param_get_hashtbl_sz(char *buffer, struct kernel_param *kp) | 64 | static int param_get_hashtbl_sz(char *buffer, const struct kernel_param *kp) |
65 | { | 65 | { |
66 | unsigned int nbits; | 66 | unsigned int nbits; |
67 | 67 | ||
@@ -71,6 +71,11 @@ static int param_get_hashtbl_sz(char *buffer, struct kernel_param *kp) | |||
71 | 71 | ||
72 | #define param_check_hashtbl_sz(name, p) __param_check(name, p, unsigned int); | 72 | #define param_check_hashtbl_sz(name, p) __param_check(name, p, unsigned int); |
73 | 73 | ||
74 | static struct kernel_param_ops param_ops_hashtbl_sz = { | ||
75 | .set = param_set_hashtbl_sz, | ||
76 | .get = param_get_hashtbl_sz, | ||
77 | }; | ||
78 | |||
74 | module_param_named(auth_hashtable_size, auth_hashbits, hashtbl_sz, 0644); | 79 | module_param_named(auth_hashtable_size, auth_hashbits, hashtbl_sz, 0644); |
75 | MODULE_PARM_DESC(auth_hashtable_size, "RPC credential cache hashtable size"); | 80 | MODULE_PARM_DESC(auth_hashtable_size, "RPC credential cache hashtable size"); |
76 | 81 | ||
diff --git a/net/sunrpc/xprtsock.c b/net/sunrpc/xprtsock.c index 7ca65c7005ea..49a62f0c4b87 100644 --- a/net/sunrpc/xprtsock.c +++ b/net/sunrpc/xprtsock.c | |||
@@ -2577,7 +2577,8 @@ void cleanup_socket_xprt(void) | |||
2577 | xprt_unregister_transport(&xs_bc_tcp_transport); | 2577 | xprt_unregister_transport(&xs_bc_tcp_transport); |
2578 | } | 2578 | } |
2579 | 2579 | ||
2580 | static int param_set_uint_minmax(const char *val, struct kernel_param *kp, | 2580 | static int param_set_uint_minmax(const char *val, |
2581 | const struct kernel_param *kp, | ||
2581 | unsigned int min, unsigned int max) | 2582 | unsigned int min, unsigned int max) |
2582 | { | 2583 | { |
2583 | unsigned long num; | 2584 | unsigned long num; |
@@ -2592,34 +2593,37 @@ static int param_set_uint_minmax(const char *val, struct kernel_param *kp, | |||
2592 | return 0; | 2593 | return 0; |
2593 | } | 2594 | } |
2594 | 2595 | ||
2595 | static int param_set_portnr(const char *val, struct kernel_param *kp) | 2596 | static int param_set_portnr(const char *val, const struct kernel_param *kp) |
2596 | { | 2597 | { |
2597 | return param_set_uint_minmax(val, kp, | 2598 | return param_set_uint_minmax(val, kp, |
2598 | RPC_MIN_RESVPORT, | 2599 | RPC_MIN_RESVPORT, |
2599 | RPC_MAX_RESVPORT); | 2600 | RPC_MAX_RESVPORT); |
2600 | } | 2601 | } |
2601 | 2602 | ||
2602 | static int param_get_portnr(char *buffer, struct kernel_param *kp) | 2603 | static struct kernel_param_ops param_ops_portnr = { |
2603 | { | 2604 | .set = param_set_portnr, |
2604 | return param_get_uint(buffer, kp); | 2605 | .get = param_get_uint, |
2605 | } | 2606 | }; |
2607 | |||
2606 | #define param_check_portnr(name, p) \ | 2608 | #define param_check_portnr(name, p) \ |
2607 | __param_check(name, p, unsigned int); | 2609 | __param_check(name, p, unsigned int); |
2608 | 2610 | ||
2609 | module_param_named(min_resvport, xprt_min_resvport, portnr, 0644); | 2611 | module_param_named(min_resvport, xprt_min_resvport, portnr, 0644); |
2610 | module_param_named(max_resvport, xprt_max_resvport, portnr, 0644); | 2612 | module_param_named(max_resvport, xprt_max_resvport, portnr, 0644); |
2611 | 2613 | ||
2612 | static int param_set_slot_table_size(const char *val, struct kernel_param *kp) | 2614 | static int param_set_slot_table_size(const char *val, |
2615 | const struct kernel_param *kp) | ||
2613 | { | 2616 | { |
2614 | return param_set_uint_minmax(val, kp, | 2617 | return param_set_uint_minmax(val, kp, |
2615 | RPC_MIN_SLOT_TABLE, | 2618 | RPC_MIN_SLOT_TABLE, |
2616 | RPC_MAX_SLOT_TABLE); | 2619 | RPC_MAX_SLOT_TABLE); |
2617 | } | 2620 | } |
2618 | 2621 | ||
2619 | static int param_get_slot_table_size(char *buffer, struct kernel_param *kp) | 2622 | static struct kernel_param_ops param_ops_slot_table_size = { |
2620 | { | 2623 | .set = param_set_slot_table_size, |
2621 | return param_get_uint(buffer, kp); | 2624 | .get = param_get_uint, |
2622 | } | 2625 | }; |
2626 | |||
2623 | #define param_check_slot_table_size(name, p) \ | 2627 | #define param_check_slot_table_size(name, p) \ |
2624 | __param_check(name, p, unsigned int); | 2628 | __param_check(name, p, unsigned int); |
2625 | 2629 | ||
diff --git a/scripts/mod/modpost.c b/scripts/mod/modpost.c index 253c107b9a99..1ec7158b6c1f 100644 --- a/scripts/mod/modpost.c +++ b/scripts/mod/modpost.c | |||
@@ -1035,6 +1035,13 @@ static const struct sectioncheck *section_mismatch( | |||
1035 | * fromsec = .data* | 1035 | * fromsec = .data* |
1036 | * atsym =__param* | 1036 | * atsym =__param* |
1037 | * | 1037 | * |
1038 | * Pattern 1a: | ||
1039 | * module_param_call() ops can refer to __init set function if permissions=0 | ||
1040 | * The pattern is identified by: | ||
1041 | * tosec = .init.text | ||
1042 | * fromsec = .data* | ||
1043 | * atsym = __param_ops_* | ||
1044 | * | ||
1038 | * Pattern 2: | 1045 | * Pattern 2: |
1039 | * Many drivers utilise a *driver container with references to | 1046 | * Many drivers utilise a *driver container with references to |
1040 | * add, remove, probe functions etc. | 1047 | * add, remove, probe functions etc. |
@@ -1069,6 +1076,12 @@ static int secref_whitelist(const struct sectioncheck *mismatch, | |||
1069 | (strncmp(fromsym, "__param", strlen("__param")) == 0)) | 1076 | (strncmp(fromsym, "__param", strlen("__param")) == 0)) |
1070 | return 0; | 1077 | return 0; |
1071 | 1078 | ||
1079 | /* Check for pattern 1a */ | ||
1080 | if (strcmp(tosec, ".init.text") == 0 && | ||
1081 | match(fromsec, data_sections) && | ||
1082 | (strncmp(fromsym, "__param_ops_", strlen("__param_ops_")) == 0)) | ||
1083 | return 0; | ||
1084 | |||
1072 | /* Check for pattern 2 */ | 1085 | /* Check for pattern 2 */ |
1073 | if (match(tosec, init_exit_sections) && | 1086 | if (match(tosec, init_exit_sections) && |
1074 | match(fromsec, data_sections) && | 1087 | match(fromsec, data_sections) && |
diff --git a/security/apparmor/lsm.c b/security/apparmor/lsm.c index 8db33a8b50c4..d5666d3cc21b 100644 --- a/security/apparmor/lsm.c +++ b/security/apparmor/lsm.c | |||
@@ -667,17 +667,29 @@ static struct security_operations apparmor_ops = { | |||
667 | * AppArmor sysfs module parameters | 667 | * AppArmor sysfs module parameters |
668 | */ | 668 | */ |
669 | 669 | ||
670 | static int param_set_aabool(const char *val, struct kernel_param *kp); | 670 | static int param_set_aabool(const char *val, const struct kernel_param *kp); |
671 | static int param_get_aabool(char *buffer, struct kernel_param *kp); | 671 | static int param_get_aabool(char *buffer, const struct kernel_param *kp); |
672 | #define param_check_aabool(name, p) __param_check(name, p, int) | 672 | #define param_check_aabool(name, p) __param_check(name, p, int) |
673 | static struct kernel_param_ops param_ops_aabool = { | ||
674 | .set = param_set_aabool, | ||
675 | .get = param_get_aabool | ||
676 | }; | ||
673 | 677 | ||
674 | static int param_set_aauint(const char *val, struct kernel_param *kp); | 678 | static int param_set_aauint(const char *val, const struct kernel_param *kp); |
675 | static int param_get_aauint(char *buffer, struct kernel_param *kp); | 679 | static int param_get_aauint(char *buffer, const struct kernel_param *kp); |
676 | #define param_check_aauint(name, p) __param_check(name, p, int) | 680 | #define param_check_aauint(name, p) __param_check(name, p, int) |
681 | static struct kernel_param_ops param_ops_aauint = { | ||
682 | .set = param_set_aauint, | ||
683 | .get = param_get_aauint | ||
684 | }; | ||
677 | 685 | ||
678 | static int param_set_aalockpolicy(const char *val, struct kernel_param *kp); | 686 | static int param_set_aalockpolicy(const char *val, const struct kernel_param *kp); |
679 | static int param_get_aalockpolicy(char *buffer, struct kernel_param *kp); | 687 | static int param_get_aalockpolicy(char *buffer, const struct kernel_param *kp); |
680 | #define param_check_aalockpolicy(name, p) __param_check(name, p, int) | 688 | #define param_check_aalockpolicy(name, p) __param_check(name, p, int) |
689 | static struct kernel_param_ops param_ops_aalockpolicy = { | ||
690 | .set = param_set_aalockpolicy, | ||
691 | .get = param_get_aalockpolicy | ||
692 | }; | ||
681 | 693 | ||
682 | static int param_set_audit(const char *val, struct kernel_param *kp); | 694 | static int param_set_audit(const char *val, struct kernel_param *kp); |
683 | static int param_get_audit(char *buffer, struct kernel_param *kp); | 695 | static int param_get_audit(char *buffer, struct kernel_param *kp); |
@@ -751,7 +763,7 @@ static int __init apparmor_enabled_setup(char *str) | |||
751 | __setup("apparmor=", apparmor_enabled_setup); | 763 | __setup("apparmor=", apparmor_enabled_setup); |
752 | 764 | ||
753 | /* set global flag turning off the ability to load policy */ | 765 | /* set global flag turning off the ability to load policy */ |
754 | static int param_set_aalockpolicy(const char *val, struct kernel_param *kp) | 766 | static int param_set_aalockpolicy(const char *val, const struct kernel_param *kp) |
755 | { | 767 | { |
756 | if (!capable(CAP_MAC_ADMIN)) | 768 | if (!capable(CAP_MAC_ADMIN)) |
757 | return -EPERM; | 769 | return -EPERM; |
@@ -760,35 +772,35 @@ static int param_set_aalockpolicy(const char *val, struct kernel_param *kp) | |||
760 | return param_set_bool(val, kp); | 772 | return param_set_bool(val, kp); |
761 | } | 773 | } |
762 | 774 | ||
763 | static int param_get_aalockpolicy(char *buffer, struct kernel_param *kp) | 775 | static int param_get_aalockpolicy(char *buffer, const struct kernel_param *kp) |
764 | { | 776 | { |
765 | if (!capable(CAP_MAC_ADMIN)) | 777 | if (!capable(CAP_MAC_ADMIN)) |
766 | return -EPERM; | 778 | return -EPERM; |
767 | return param_get_bool(buffer, kp); | 779 | return param_get_bool(buffer, kp); |
768 | } | 780 | } |
769 | 781 | ||
770 | static int param_set_aabool(const char *val, struct kernel_param *kp) | 782 | static int param_set_aabool(const char *val, const struct kernel_param *kp) |
771 | { | 783 | { |
772 | if (!capable(CAP_MAC_ADMIN)) | 784 | if (!capable(CAP_MAC_ADMIN)) |
773 | return -EPERM; | 785 | return -EPERM; |
774 | return param_set_bool(val, kp); | 786 | return param_set_bool(val, kp); |
775 | } | 787 | } |
776 | 788 | ||
777 | static int param_get_aabool(char *buffer, struct kernel_param *kp) | 789 | static int param_get_aabool(char *buffer, const struct kernel_param *kp) |
778 | { | 790 | { |
779 | if (!capable(CAP_MAC_ADMIN)) | 791 | if (!capable(CAP_MAC_ADMIN)) |
780 | return -EPERM; | 792 | return -EPERM; |
781 | return param_get_bool(buffer, kp); | 793 | return param_get_bool(buffer, kp); |
782 | } | 794 | } |
783 | 795 | ||
784 | static int param_set_aauint(const char *val, struct kernel_param *kp) | 796 | static int param_set_aauint(const char *val, const struct kernel_param *kp) |
785 | { | 797 | { |
786 | if (!capable(CAP_MAC_ADMIN)) | 798 | if (!capable(CAP_MAC_ADMIN)) |
787 | return -EPERM; | 799 | return -EPERM; |
788 | return param_set_uint(val, kp); | 800 | return param_set_uint(val, kp); |
789 | } | 801 | } |
790 | 802 | ||
791 | static int param_get_aauint(char *buffer, struct kernel_param *kp) | 803 | static int param_get_aauint(char *buffer, const struct kernel_param *kp) |
792 | { | 804 | { |
793 | if (!capable(CAP_MAC_ADMIN)) | 805 | if (!capable(CAP_MAC_ADMIN)) |
794 | return -EPERM; | 806 | return -EPERM; |