diff options
Diffstat (limited to 'drivers/media/dvb')
-rw-r--r-- | drivers/media/dvb/Kconfig | 13 | ||||
-rw-r--r-- | drivers/media/dvb/dvb-core/dvbdev.c | 57 | ||||
-rw-r--r-- | drivers/media/dvb/dvb-core/dvbdev.h | 1 |
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 | ||
5 | config 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 | |||
5 | menuconfig DVB_CAPTURE_DRIVERS | 18 | menuconfig 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 | ||
57 | static struct class *dvb_class; | 62 | static struct class *dvb_class; |
58 | 63 | ||
59 | static struct dvb_device* dvbdev_find_device (int minor) | 64 | static struct dvb_device *dvb_minors[MAX_DVB_MINORS]; |
60 | { | 65 | static 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 | ||
74 | static int dvb_device_open(struct inode *inode, struct file *file) | 67 | static 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, |