aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/char/raw.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/char/raw.c')
-rw-r--r--drivers/char/raw.c34
1 files changed, 27 insertions, 7 deletions
diff --git a/drivers/char/raw.c b/drivers/char/raw.c
index b4b9d5a47885..b33e8ea314ed 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
32static struct class *raw_class; 33static struct class *raw_class;
33static struct raw_device_data raw_devices[MAX_RAW_MINORS]; 34static struct raw_device_data *raw_devices;
34static DEFINE_MUTEX(raw_mutex); 35static DEFINE_MUTEX(raw_mutex);
35static const struct file_operations raw_ctl_fops; /* forward declaration */ 36static const struct file_operations raw_ctl_fops; /* forward declaration */
36 37
38static int max_raw_minors = MAX_RAW_MINORS;
39
40module_param(max_raw_minors, int, 0);
41MODULE_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,14 +318,27 @@ 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);
323 goto error_region; 342 goto error_region;
324 } 343 }
325 344
@@ -336,8 +355,9 @@ static int __init raw_init(void)
336 return 0; 355 return 0;
337 356
338error_region: 357error_region:
339 unregister_chrdev_region(dev, MAX_RAW_MINORS); 358 unregister_chrdev_region(dev, max_raw_minors);
340error: 359error:
360 vfree(raw_devices);
341 return ret; 361 return ret;
342} 362}
343 363
@@ -346,7 +366,7 @@ static void __exit raw_exit(void)
346 device_destroy(raw_class, MKDEV(RAW_MAJOR, 0)); 366 device_destroy(raw_class, MKDEV(RAW_MAJOR, 0));
347 class_destroy(raw_class); 367 class_destroy(raw_class);
348 cdev_del(&raw_cdev); 368 cdev_del(&raw_cdev);
349 unregister_chrdev_region(MKDEV(RAW_MAJOR, 0), MAX_RAW_MINORS); 369 unregister_chrdev_region(MKDEV(RAW_MAJOR, 0), max_raw_minors);
350} 370}
351 371
352module_init(raw_init); 372module_init(raw_init);