diff options
author | Mauro Carvalho Chehab <mchehab@redhat.com> | 2008-10-23 17:11:19 +0200 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@redhat.com> | 2008-10-23 17:11:19 +0200 |
commit | 6b5f5ff6db5bdccf525c24c356d71bedfba91417 (patch) | |
tree | 6934f7ace5e65deeb962d4a6ac8e678c68eee623 /linux/drivers/media/dvb/dvb-core | |
parent | 4085bc31e472f8d6cabf91d541501f4577ca4e3b (diff) | |
download | mediapointer-dvb-s2-6b5f5ff6db5bdccf525c24c356d71bedfba91417.tar.gz mediapointer-dvb-s2-6b5f5ff6db5bdccf525c24c356d71bedfba91417.tar.bz2 |
Dynamic DVB minor allocation
From: Andreas Oberritter <obi@linuxtv.org>
This is a multi-part message in MIME format.
Implement dynamic minor allocation for DVB, to allow more than four
devices of the same type per adapter, based on drivers/usb/core/file.c.
Add a new config option, DVB_DYNAMIC_MINORS, to make use of this
feature, which defaults to no for backwards compatibility.
Signed-off-by: Andreas Oberritter <obi@linuxtv.org>
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
Diffstat (limited to 'linux/drivers/media/dvb/dvb-core')
-rw-r--r-- | linux/drivers/media/dvb/dvb-core/dvbdev.c | 61 | ||||
-rw-r--r-- | linux/drivers/media/dvb/dvb-core/dvbdev.h | 1 |
2 files changed, 41 insertions, 21 deletions
diff --git a/linux/drivers/media/dvb/dvb-core/dvbdev.c b/linux/drivers/media/dvb/dvb-core/dvbdev.c index c2e824710..a35286f1a 100644 --- a/linux/drivers/media/dvb/dvb-core/dvbdev.c +++ b/linux/drivers/media/dvb/dvb-core/dvbdev.c @@ -51,33 +51,27 @@ static const char * const dnames[] = { "net", "osd" }; +#ifdef CONFIG_DVB_DYNAMIC_MINORS +#define MAX_DVB_MINORS 256 +#define DVB_MAX_IDS MAX_DVB_MINORS +#else #define DVB_MAX_IDS 4 #define nums2minor(num,type,id) ((num << 6) | (id << 4) | type) #define MAX_DVB_MINORS (DVB_MAX_ADAPTERS*64) +#endif static struct class *dvb_class; -static struct dvb_device* dvbdev_find_device (int minor) -{ - struct dvb_adapter *adap; - - list_for_each_entry(adap, &dvb_adapter_list, list_head) { - struct dvb_device *dev; - list_for_each_entry(dev, &adap->device_list, list_head) - if (nums2minor(adap->num, dev->type, dev->id) == minor) - return dev; - } - - return NULL; -} - +static struct dvb_device *dvb_minors[MAX_DVB_MINORS]; +static DECLARE_RWSEM(minor_rwsem); static int dvb_device_open(struct inode *inode, struct file *file) { struct dvb_device *dvbdev; lock_kernel(); - dvbdev = dvbdev_find_device (iminor(inode)); + down_read(&minor_rwsem); + dvbdev = dvb_minors[iminor(inode)]; if (dvbdev && dvbdev->fops) { int err = 0; @@ -97,9 +91,11 @@ static int dvb_device_open(struct inode *inode, struct file *file) file->f_op = fops_get(old_fops); } fops_put(old_fops); + up_read(&minor_rwsem); unlock_kernel(); return err; } + up_read(&minor_rwsem); unlock_kernel(); return -ENODEV; } @@ -201,6 +197,7 @@ int dvb_register_device(struct dvb_adapter *adap, struct dvb_device **pdvbdev, #else struct class_device *clsdev; #endif + int minor; int id; mutex_lock(&dvbdev_register_lock); @@ -240,6 +237,26 @@ int dvb_register_device(struct dvb_adapter *adap, struct dvb_device **pdvbdev, list_add_tail (&dvbdev->list_head, &adap->device_list); + down_write(&minor_rwsem); +#ifdef CONFIG_DVB_DYNAMIC_MINORS + for (minor = 0; minor < MAX_DVB_MINORS; minor++) + if (dvb_minors[minor] == NULL) + break; + + if (minor == MAX_DVB_MINORS) { + kfree(dvbdevfops); + kfree(dvbdev); + mutex_unlock(&dvbdev_register_lock); + return -EINVAL; + } +#else + minor = nums2minor(adap->num, type, id); +#endif + + dvbdev->minor = minor; + dvb_minors[minor] = dvbdev; + up_write(&minor_rwsem); + mutex_unlock(&dvbdev_register_lock); #if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 27) @@ -248,11 +265,11 @@ int dvb_register_device(struct dvb_adapter *adap, struct dvb_device **pdvbdev, NULL, "dvb%d.%s%d", adap->num, dnames[type], id); #elif LINUX_VERSION_CODE == KERNEL_VERSION(2, 6, 27) clsdev = device_create_drvdata(dvb_class, adap->device, - MKDEV(DVB_MAJOR, nums2minor(adap->num, type, id)), + MKDEV(DVB_MAJOR, minor), NULL, "dvb%d.%s%d", adap->num, dnames[type], id); #else clsdev = device_create(dvb_class, adap->device, - MKDEV(DVB_MAJOR, nums2minor(adap->num, type, id)), + MKDEV(DVB_MAJOR, minor), "dvb%d.%s%d", adap->num, dnames[type], id); #endif if (IS_ERR(clsdev)) { @@ -262,8 +279,7 @@ int dvb_register_device(struct dvb_adapter *adap, struct dvb_device **pdvbdev, } dprintk(KERN_DEBUG "DVB: register adapter%d/%s%d @ minor: %i (0x%02x)\n", - adap->num, dnames[type], id, nums2minor(adap->num, type, id), - nums2minor(adap->num, type, id)); + adap->num, dnames[type], id, minor, minor); return 0; } @@ -275,8 +291,11 @@ void dvb_unregister_device(struct dvb_device *dvbdev) if (!dvbdev) return; - device_destroy(dvb_class, MKDEV(DVB_MAJOR, nums2minor(dvbdev->adapter->num, - dvbdev->type, dvbdev->id))); + down_write(&minor_rwsem); + dvb_minors[dvbdev->minor] = NULL; + up_write(&minor_rwsem); + + device_destroy(dvb_class, MKDEV(DVB_MAJOR, dvbdev->minor)); list_del (&dvbdev->list_head); kfree (dvbdev->fops); diff --git a/linux/drivers/media/dvb/dvb-core/dvbdev.h b/linux/drivers/media/dvb/dvb-core/dvbdev.h index 574e336ba..dca49cf96 100644 --- a/linux/drivers/media/dvb/dvb-core/dvbdev.h +++ b/linux/drivers/media/dvb/dvb-core/dvbdev.h @@ -74,6 +74,7 @@ struct dvb_device { struct file_operations *fops; struct dvb_adapter *adapter; int type; + int minor; u32 id; /* in theory, 'users' can vanish now, |