aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/uio/uio.c
diff options
context:
space:
mode:
authorEric W. Biederman <ebiederm@aristanetworks.com>2010-09-14 14:38:06 -0400
committerGreg Kroah-Hartman <gregkh@suse.de>2010-10-22 13:16:43 -0400
commit91960a46c658b719c03fba80f1c60a96393bbcfd (patch)
treeffa50ea8eeddd9105dff834877ed594cf71ce697 /drivers/uio/uio.c
parent6427a7655afd7f07dfa83736defd1d94656c83e5 (diff)
uio: Support 2^MINOR_BITS minors
register_chrdev limits uio devices to 256 minor numbers which causes problems on one system I have with 384+ uio devices. So instead set UIO_MAX_DEVICES to the maximum number of minors and use alloc_chrdev_region to reserve the uio minors. The final result is that the code works the same but the uio driver now supports any minor the idr allocator comes up with. Signed-off-by: Eric W. Biederman <ebiederm@aristanetworks.com> Reviewed-by: Thomas Gleixner <tglx@linutronix.de> Signed-off-by: Hans J. Koch <hjk@linutronix.de> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers/uio/uio.c')
-rw-r--r--drivers/uio/uio.c43
1 files changed, 37 insertions, 6 deletions
diff --git a/drivers/uio/uio.c b/drivers/uio/uio.c
index 0fd2cda74244..3d4d65b0626f 100644
--- a/drivers/uio/uio.c
+++ b/drivers/uio/uio.c
@@ -23,9 +23,10 @@
23#include <linux/sched.h> 23#include <linux/sched.h>
24#include <linux/string.h> 24#include <linux/string.h>
25#include <linux/kobject.h> 25#include <linux/kobject.h>
26#include <linux/cdev.h>
26#include <linux/uio_driver.h> 27#include <linux/uio_driver.h>
27 28
28#define UIO_MAX_DEVICES 255 29#define UIO_MAX_DEVICES (1U << MINORBITS)
29 30
30struct uio_device { 31struct uio_device {
31 struct module *owner; 32 struct module *owner;
@@ -41,6 +42,7 @@ struct uio_device {
41}; 42};
42 43
43static int uio_major; 44static int uio_major;
45static struct cdev *uio_cdev;
44static DEFINE_IDR(uio_idr); 46static DEFINE_IDR(uio_idr);
45static const struct file_operations uio_fops; 47static const struct file_operations uio_fops;
46 48
@@ -731,15 +733,44 @@ static const struct file_operations uio_fops = {
731 733
732static int uio_major_init(void) 734static int uio_major_init(void)
733{ 735{
734 uio_major = register_chrdev(0, "uio", &uio_fops); 736 static const char name[] = "uio";
735 if (uio_major < 0) 737 struct cdev *cdev = NULL;
736 return uio_major; 738 dev_t uio_dev = 0;
737 return 0; 739 int result;
740
741 result = alloc_chrdev_region(&uio_dev, 0, UIO_MAX_DEVICES, name);
742 if (result)
743 goto out;
744
745 result = -ENOMEM;
746 cdev = cdev_alloc();
747 if (!cdev)
748 goto out_unregister;
749
750 cdev->owner = THIS_MODULE;
751 cdev->ops = &uio_fops;
752 kobject_set_name(&cdev->kobj, "%s", name);
753
754 result = cdev_add(cdev, uio_dev, UIO_MAX_DEVICES);
755 if (result)
756 goto out_put;
757
758 uio_major = MAJOR(uio_dev);
759 uio_cdev = cdev;
760 result = 0;
761out:
762 return result;
763out_put:
764 kobject_put(&cdev->kobj);
765out_unregister:
766 unregister_chrdev_region(uio_dev, UIO_MAX_DEVICES);
767 goto out;
738} 768}
739 769
740static void uio_major_cleanup(void) 770static void uio_major_cleanup(void)
741{ 771{
742 unregister_chrdev(uio_major, "uio"); 772 unregister_chrdev_region(MKDEV(uio_major, 0), UIO_MAX_DEVICES);
773 cdev_del(uio_cdev);
743} 774}
744 775
745static int init_uio_class(void) 776static int init_uio_class(void)