* [linux-dvb] [PATCH/RFC] Dynamic DVB minor allocation
@ 2008-10-20 13:52 Andreas Oberritter
0 siblings, 0 replies; only message in thread
From: Andreas Oberritter @ 2008-10-20 13:52 UTC (permalink / raw)
To: linux-dvb@linuxtv.org, v4l-dvb maintainer list
[-- Attachment #1: Type: text/plain, Size: 491 bytes --]
Hello,
recently we've exceeded the limit of minor devices, when we tried to
register five demux devices on an adapter instance. We circumvented
this limit by changing the macro nums2minor, which is not acceptable if
you want to stay backwards compatible.
So I went for a cleaner solution and added a new configuration option,
which allows dynamic minor allocation for DVB devices.
I haven't tested it yet. It is loosely based on drivers/usb/core/file.c.
Any comments?
Regards,
Andreas
[-- Attachment #2: dvbdev.diff --]
[-- Type: text/x-patch, Size: 4465 bytes --]
diff -r 9273407ca6e1 linux/drivers/media/dvb/Kconfig
--- a/linux/drivers/media/dvb/Kconfig Wed Oct 15 02:50:03 2008 +0400
+++ b/linux/drivers/media/dvb/Kconfig Mon Oct 20 15:30:50 2008 +0200
@@ -8,6 +8,18 @@
default y
---help---
Say Y to select Digital TV adapters
+
+config DVB_DYNAMIC_MINORS
+ bool "Dynamic DVB minor allocation"
+ depends on DVB_CORE
+ help
+ If you say Y here, the DVB subsystem will use dynamic minor
+ allocation for any device that uses the DVB major number.
+ This means that you can have more than 4 of a single type
+ of device (like demuxes and frontends) per adapter, but udev
+ will be required to manage the device nodes.
+
+ If you are unsure about this, say N here.
if DVB_CAPTURE_DRIVERS && DVB_CORE
diff -r 9273407ca6e1 linux/drivers/media/dvb/dvb-core/dvbdev.c
--- a/linux/drivers/media/dvb/dvb-core/dvbdev.c Wed Oct 15 02:50:03 2008 +0400
+++ b/linux/drivers/media/dvb/dvb-core/dvbdev.c Mon Oct 20 15:30:50 2008 +0200
@@ -51,33 +51,27 @@
"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 @@
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 @@
#else
struct class_device *clsdev;
#endif
+ int minor;
int id;
mutex_lock(&dvbdev_register_lock);
@@ -240,15 +237,35 @@
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, 26)
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)) {
@@ -258,8 +275,7 @@
}
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;
}
@@ -271,8 +287,11 @@
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 -r 9273407ca6e1 linux/drivers/media/dvb/dvb-core/dvbdev.h
--- a/linux/drivers/media/dvb/dvb-core/dvbdev.h Wed Oct 15 02:50:03 2008 +0400
+++ b/linux/drivers/media/dvb/dvb-core/dvbdev.h Mon Oct 20 15:30:50 2008 +0200
@@ -70,6 +70,7 @@
struct file_operations *fops;
struct dvb_adapter *adapter;
int type;
+ int minor;
u32 id;
/* in theory, 'users' can vanish now,
[-- Attachment #3: Type: text/plain, Size: 150 bytes --]
_______________________________________________
linux-dvb mailing list
linux-dvb@linuxtv.org
http://www.linuxtv.org/cgi-bin/mailman/listinfo/linux-dvb
^ permalink raw reply [flat|nested] only message in thread
only message in thread, other threads:[~2008-10-20 13:52 UTC | newest]
Thread overview: (only message) (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2008-10-20 13:52 [linux-dvb] [PATCH/RFC] Dynamic DVB minor allocation Andreas Oberritter
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox