diff options
author | Jan Kara <jack@suse.cz> | 2011-04-28 18:24:29 -0400 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@suse.de> | 2011-05-06 20:52:31 -0400 |
commit | 0078bff5283d1fd6417b840eda6dab912b7a5560 (patch) | |
tree | 96e3c823a7ce0be46297f52b59b6d15973a9a61b /drivers/char/raw.c | |
parent | a1d9a09ae8003380a7f2297ee4367947cbdf874f (diff) |
Allow setting of number of raw devices as a module parameter
Allow setting of maximal number of raw devices as a module parameter. This
requires changing of static array into a vmalloced one (the array is going to
be too large for kmalloc).
Signed-off-by: Jan Kara <jack@suse.cz>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers/char/raw.c')
-rw-r--r-- | drivers/char/raw.c | 33 |
1 files changed, 27 insertions, 6 deletions
diff --git a/drivers/char/raw.c b/drivers/char/raw.c index b4b9d5a47885..6f9db621155a 100644 --- a/drivers/char/raw.c +++ b/drivers/char/raw.c | |||
@@ -21,6 +21,7 @@ | |||
21 | #include <linux/mutex.h> | 21 | #include <linux/mutex.h> |
22 | #include <linux/gfp.h> | 22 | #include <linux/gfp.h> |
23 | #include <linux/compat.h> | 23 | #include <linux/compat.h> |
24 | #include <linux/vmalloc.h> | ||
24 | 25 | ||
25 | #include <asm/uaccess.h> | 26 | #include <asm/uaccess.h> |
26 | 27 | ||
@@ -30,10 +31,15 @@ struct raw_device_data { | |||
30 | }; | 31 | }; |
31 | 32 | ||
32 | static struct class *raw_class; | 33 | static struct class *raw_class; |
33 | static struct raw_device_data raw_devices[MAX_RAW_MINORS]; | 34 | static struct raw_device_data *raw_devices; |
34 | static DEFINE_MUTEX(raw_mutex); | 35 | static DEFINE_MUTEX(raw_mutex); |
35 | static const struct file_operations raw_ctl_fops; /* forward declaration */ | 36 | static const struct file_operations raw_ctl_fops; /* forward declaration */ |
36 | 37 | ||
38 | static int max_raw_minors = MAX_RAW_MINORS; | ||
39 | |||
40 | module_param(max_raw_minors, int, 0); | ||
41 | MODULE_PARM_DESC(max_raw_minors, "Maximum number of raw devices (1-65536)"); | ||
42 | |||
37 | /* | 43 | /* |
38 | * Open/close code for raw IO. | 44 | * Open/close code for raw IO. |
39 | * | 45 | * |
@@ -125,7 +131,7 @@ static int bind_set(int number, u64 major, u64 minor) | |||
125 | struct raw_device_data *rawdev; | 131 | struct raw_device_data *rawdev; |
126 | int err = 0; | 132 | int err = 0; |
127 | 133 | ||
128 | if (number <= 0 || number >= MAX_RAW_MINORS) | 134 | if (number <= 0 || number >= max_raw_minors) |
129 | return -EINVAL; | 135 | return -EINVAL; |
130 | 136 | ||
131 | if (MAJOR(dev) != major || MINOR(dev) != minor) | 137 | if (MAJOR(dev) != major || MINOR(dev) != minor) |
@@ -312,12 +318,26 @@ static int __init raw_init(void) | |||
312 | dev_t dev = MKDEV(RAW_MAJOR, 0); | 318 | dev_t dev = MKDEV(RAW_MAJOR, 0); |
313 | int ret; | 319 | int ret; |
314 | 320 | ||
315 | ret = register_chrdev_region(dev, MAX_RAW_MINORS, "raw"); | 321 | if (max_raw_minors < 1 || max_raw_minors > 65536) { |
322 | printk(KERN_WARNING "raw: invalid max_raw_minors (must be" | ||
323 | " between 1 and 65536), using %d\n", MAX_RAW_MINORS); | ||
324 | max_raw_minors = MAX_RAW_MINORS; | ||
325 | } | ||
326 | |||
327 | raw_devices = vmalloc(sizeof(struct raw_device_data) * max_raw_minors); | ||
328 | if (!raw_devices) { | ||
329 | printk(KERN_ERR "Not enough memory for raw device structures\n"); | ||
330 | ret = -ENOMEM; | ||
331 | goto error; | ||
332 | } | ||
333 | memset(raw_devices, 0, sizeof(struct raw_device_data) * max_raw_minors); | ||
334 | |||
335 | ret = register_chrdev_region(dev, max_raw_minors, "raw"); | ||
316 | if (ret) | 336 | if (ret) |
317 | goto error; | 337 | goto error; |
318 | 338 | ||
319 | cdev_init(&raw_cdev, &raw_fops); | 339 | cdev_init(&raw_cdev, &raw_fops); |
320 | ret = cdev_add(&raw_cdev, dev, MAX_RAW_MINORS); | 340 | ret = cdev_add(&raw_cdev, dev, max_raw_minors); |
321 | if (ret) { | 341 | if (ret) { |
322 | kobject_put(&raw_cdev.kobj); | 342 | kobject_put(&raw_cdev.kobj); |
323 | goto error_region; | 343 | goto error_region; |
@@ -336,8 +356,9 @@ static int __init raw_init(void) | |||
336 | return 0; | 356 | return 0; |
337 | 357 | ||
338 | error_region: | 358 | error_region: |
339 | unregister_chrdev_region(dev, MAX_RAW_MINORS); | 359 | unregister_chrdev_region(dev, max_raw_minors); |
340 | error: | 360 | error: |
361 | vfree(raw_devices); | ||
341 | return ret; | 362 | return ret; |
342 | } | 363 | } |
343 | 364 | ||
@@ -346,7 +367,7 @@ static void __exit raw_exit(void) | |||
346 | device_destroy(raw_class, MKDEV(RAW_MAJOR, 0)); | 367 | device_destroy(raw_class, MKDEV(RAW_MAJOR, 0)); |
347 | class_destroy(raw_class); | 368 | class_destroy(raw_class); |
348 | cdev_del(&raw_cdev); | 369 | cdev_del(&raw_cdev); |
349 | unregister_chrdev_region(MKDEV(RAW_MAJOR, 0), MAX_RAW_MINORS); | 370 | unregister_chrdev_region(MKDEV(RAW_MAJOR, 0), max_raw_minors); |
350 | } | 371 | } |
351 | 372 | ||
352 | module_init(raw_init); | 373 | module_init(raw_init); |