aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorAndreas Oberritter <obi@linuxtv.org>2008-10-23 11:11:19 -0400
committerMauro Carvalho Chehab <mchehab@redhat.com>2008-12-29 14:53:12 -0500
commit5dd3f3071070f5a306bdf8d474c80062f5691cba (patch)
treefc576a715c397ac5c5459006ea34a9ffac3d430b /drivers
parent568e9bb8d764300e1de81d49ae698cc970a511d8 (diff)
V4L/DVB (9361): Dynamic DVB minor allocation
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 'drivers')
-rw-r--r--drivers/media/dvb/Kconfig13
-rw-r--r--drivers/media/dvb/dvb-core/dvbdev.c57
-rw-r--r--drivers/media/dvb/dvb-core/dvbdev.h1
3 files changed, 52 insertions, 19 deletions
diff --git a/drivers/media/dvb/Kconfig b/drivers/media/dvb/Kconfig
index 0bcd852576d6..40ebde53b3ce 100644
--- a/drivers/media/dvb/Kconfig
+++ b/drivers/media/dvb/Kconfig
@@ -2,6 +2,19 @@
2# DVB device configuration 2# DVB device configuration
3# 3#
4 4
5config DVB_DYNAMIC_MINORS
6 bool "Dynamic DVB minor allocation"
7 depends on DVB_CORE
8 default n
9 help
10 If you say Y here, the DVB subsystem will use dynamic minor
11 allocation for any device that uses the DVB major number.
12 This means that you can have more than 4 of a single type
13 of device (like demuxes and frontends) per adapter, but udev
14 will be required to manage the device nodes.
15
16 If you are unsure about this, say N here.
17
5menuconfig DVB_CAPTURE_DRIVERS 18menuconfig DVB_CAPTURE_DRIVERS
6 bool "DVB/ATSC adapters" 19 bool "DVB/ATSC adapters"
7 depends on DVB_CORE 20 depends on DVB_CORE
diff --git a/drivers/media/dvb/dvb-core/dvbdev.c b/drivers/media/dvb/dvb-core/dvbdev.c
index a113744a56cc..e363a3b5054c 100644
--- a/drivers/media/dvb/dvb-core/dvbdev.c
+++ b/drivers/media/dvb/dvb-core/dvbdev.c
@@ -50,33 +50,27 @@ static const char * const dnames[] = {
50 "net", "osd" 50 "net", "osd"
51}; 51};
52 52
53#ifdef CONFIG_DVB_DYNAMIC_MINORS
54#define MAX_DVB_MINORS 256
55#define DVB_MAX_IDS MAX_DVB_MINORS
56#else
53#define DVB_MAX_IDS 4 57#define DVB_MAX_IDS 4
54#define nums2minor(num,type,id) ((num << 6) | (id << 4) | type) 58#define nums2minor(num,type,id) ((num << 6) | (id << 4) | type)
55#define MAX_DVB_MINORS (DVB_MAX_ADAPTERS*64) 59#define MAX_DVB_MINORS (DVB_MAX_ADAPTERS*64)
60#endif
56 61
57static struct class *dvb_class; 62static struct class *dvb_class;
58 63
59static struct dvb_device* dvbdev_find_device (int minor) 64static struct dvb_device *dvb_minors[MAX_DVB_MINORS];
60{ 65static DECLARE_RWSEM(minor_rwsem);
61 struct dvb_adapter *adap;
62
63 list_for_each_entry(adap, &dvb_adapter_list, list_head) {
64 struct dvb_device *dev;
65 list_for_each_entry(dev, &adap->device_list, list_head)
66 if (nums2minor(adap->num, dev->type, dev->id) == minor)
67 return dev;
68 }
69
70 return NULL;
71}
72
73 66
74static int dvb_device_open(struct inode *inode, struct file *file) 67static int dvb_device_open(struct inode *inode, struct file *file)
75{ 68{
76 struct dvb_device *dvbdev; 69 struct dvb_device *dvbdev;
77 70
78 lock_kernel(); 71 lock_kernel();
79 dvbdev = dvbdev_find_device (iminor(inode)); 72 down_read(&minor_rwsem);
73 dvbdev = dvb_minors[iminor(inode)];
80 74
81 if (dvbdev && dvbdev->fops) { 75 if (dvbdev && dvbdev->fops) {
82 int err = 0; 76 int err = 0;
@@ -92,9 +86,11 @@ static int dvb_device_open(struct inode *inode, struct file *file)
92 file->f_op = fops_get(old_fops); 86 file->f_op = fops_get(old_fops);
93 } 87 }
94 fops_put(old_fops); 88 fops_put(old_fops);
89 up_read(&minor_rwsem);
95 unlock_kernel(); 90 unlock_kernel();
96 return err; 91 return err;
97 } 92 }
93 up_read(&minor_rwsem);
98 unlock_kernel(); 94 unlock_kernel();
99 return -ENODEV; 95 return -ENODEV;
100} 96}
@@ -192,6 +188,7 @@ int dvb_register_device(struct dvb_adapter *adap, struct dvb_device **pdvbdev,
192 struct dvb_device *dvbdev; 188 struct dvb_device *dvbdev;
193 struct file_operations *dvbdevfops; 189 struct file_operations *dvbdevfops;
194 struct device *clsdev; 190 struct device *clsdev;
191 int minor;
195 int id; 192 int id;
196 193
197 mutex_lock(&dvbdev_register_lock); 194 mutex_lock(&dvbdev_register_lock);
@@ -231,6 +228,26 @@ int dvb_register_device(struct dvb_adapter *adap, struct dvb_device **pdvbdev,
231 228
232 list_add_tail (&dvbdev->list_head, &adap->device_list); 229 list_add_tail (&dvbdev->list_head, &adap->device_list);
233 230
231 down_write(&minor_rwsem);
232#ifdef CONFIG_DVB_DYNAMIC_MINORS
233 for (minor = 0; minor < MAX_DVB_MINORS; minor++)
234 if (dvb_minors[minor] == NULL)
235 break;
236
237 if (minor == MAX_DVB_MINORS) {
238 kfree(dvbdevfops);
239 kfree(dvbdev);
240 mutex_unlock(&dvbdev_register_lock);
241 return -EINVAL;
242 }
243#else
244 minor = nums2minor(adap->num, type, id);
245#endif
246
247 dvbdev->minor = minor;
248 dvb_minors[minor] = dvbdev;
249 up_write(&minor_rwsem);
250
234 mutex_unlock(&dvbdev_register_lock); 251 mutex_unlock(&dvbdev_register_lock);
235 252
236 clsdev = device_create(dvb_class, adap->device, 253 clsdev = device_create(dvb_class, adap->device,
@@ -243,8 +260,7 @@ int dvb_register_device(struct dvb_adapter *adap, struct dvb_device **pdvbdev,
243 } 260 }
244 261
245 dprintk(KERN_DEBUG "DVB: register adapter%d/%s%d @ minor: %i (0x%02x)\n", 262 dprintk(KERN_DEBUG "DVB: register adapter%d/%s%d @ minor: %i (0x%02x)\n",
246 adap->num, dnames[type], id, nums2minor(adap->num, type, id), 263 adap->num, dnames[type], id, minor, minor);
247 nums2minor(adap->num, type, id));
248 264
249 return 0; 265 return 0;
250} 266}
@@ -256,8 +272,11 @@ void dvb_unregister_device(struct dvb_device *dvbdev)
256 if (!dvbdev) 272 if (!dvbdev)
257 return; 273 return;
258 274
259 device_destroy(dvb_class, MKDEV(DVB_MAJOR, nums2minor(dvbdev->adapter->num, 275 down_write(&minor_rwsem);
260 dvbdev->type, dvbdev->id))); 276 dvb_minors[dvbdev->minor] = NULL;
277 up_write(&minor_rwsem);
278
279 device_destroy(dvb_class, MKDEV(DVB_MAJOR, dvbdev->minor));
261 280
262 list_del (&dvbdev->list_head); 281 list_del (&dvbdev->list_head);
263 kfree (dvbdev->fops); 282 kfree (dvbdev->fops);
diff --git a/drivers/media/dvb/dvb-core/dvbdev.h b/drivers/media/dvb/dvb-core/dvbdev.h
index 574e336bac35..dca49cf962e8 100644
--- a/drivers/media/dvb/dvb-core/dvbdev.h
+++ b/drivers/media/dvb/dvb-core/dvbdev.h
@@ -74,6 +74,7 @@ struct dvb_device {
74 struct file_operations *fops; 74 struct file_operations *fops;
75 struct dvb_adapter *adapter; 75 struct dvb_adapter *adapter;
76 int type; 76 int type;
77 int minor;
77 u32 id; 78 u32 id;
78 79
79 /* in theory, 'users' can vanish now, 80 /* in theory, 'users' can vanish now,