aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/dvb/dvb-core/dmxdev.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/media/dvb/dvb-core/dmxdev.c')
-rw-r--r--drivers/media/dvb/dvb-core/dmxdev.c56
1 files changed, 54 insertions, 2 deletions
diff --git a/drivers/media/dvb/dvb-core/dmxdev.c b/drivers/media/dvb/dvb-core/dmxdev.c
index a5c0e1a3e6d1..275df65fde99 100644
--- a/drivers/media/dvb/dvb-core/dmxdev.c
+++ b/drivers/media/dvb/dvb-core/dmxdev.c
@@ -132,6 +132,11 @@ static int dvb_dvr_open(struct inode *inode, struct file *file)
132 if (mutex_lock_interruptible(&dmxdev->mutex)) 132 if (mutex_lock_interruptible(&dmxdev->mutex))
133 return -ERESTARTSYS; 133 return -ERESTARTSYS;
134 134
135 if (dmxdev->exit) {
136 mutex_unlock(&dmxdev->mutex);
137 return -ENODEV;
138 }
139
135 if ((file->f_flags & O_ACCMODE) == O_RDWR) { 140 if ((file->f_flags & O_ACCMODE) == O_RDWR) {
136 if (!(dmxdev->capabilities & DMXDEV_CAP_DUPLEX)) { 141 if (!(dmxdev->capabilities & DMXDEV_CAP_DUPLEX)) {
137 mutex_unlock(&dmxdev->mutex); 142 mutex_unlock(&dmxdev->mutex);
@@ -171,6 +176,7 @@ static int dvb_dvr_open(struct inode *inode, struct file *file)
171 dmxdev->demux->disconnect_frontend(dmxdev->demux); 176 dmxdev->demux->disconnect_frontend(dmxdev->demux);
172 dmxdev->demux->connect_frontend(dmxdev->demux, front); 177 dmxdev->demux->connect_frontend(dmxdev->demux, front);
173 } 178 }
179 dvbdev->users++;
174 mutex_unlock(&dmxdev->mutex); 180 mutex_unlock(&dmxdev->mutex);
175 return 0; 181 return 0;
176} 182}
@@ -198,7 +204,16 @@ static int dvb_dvr_release(struct inode *inode, struct file *file)
198 vfree(mem); 204 vfree(mem);
199 } 205 }
200 } 206 }
201 mutex_unlock(&dmxdev->mutex); 207 /* TODO */
208 dvbdev->users--;
209 if(dvbdev->users==-1 && dmxdev->exit==1) {
210 fops_put(file->f_op);
211 file->f_op = NULL;
212 mutex_unlock(&dmxdev->mutex);
213 wake_up(&dvbdev->wait_queue);
214 } else
215 mutex_unlock(&dmxdev->mutex);
216
202 return 0; 217 return 0;
203} 218}
204 219
@@ -215,6 +230,11 @@ static ssize_t dvb_dvr_write(struct file *file, const char __user *buf,
215 return -EINVAL; 230 return -EINVAL;
216 if (mutex_lock_interruptible(&dmxdev->mutex)) 231 if (mutex_lock_interruptible(&dmxdev->mutex))
217 return -ERESTARTSYS; 232 return -ERESTARTSYS;
233
234 if (dmxdev->exit) {
235 mutex_unlock(&dmxdev->mutex);
236 return -ENODEV;
237 }
218 ret = dmxdev->demux->write(dmxdev->demux, buf, count); 238 ret = dmxdev->demux->write(dmxdev->demux, buf, count);
219 mutex_unlock(&dmxdev->mutex); 239 mutex_unlock(&dmxdev->mutex);
220 return ret; 240 return ret;
@@ -227,6 +247,11 @@ static ssize_t dvb_dvr_read(struct file *file, char __user *buf, size_t count,
227 struct dmxdev *dmxdev = dvbdev->priv; 247 struct dmxdev *dmxdev = dvbdev->priv;
228 int ret; 248 int ret;
229 249
250 if (dmxdev->exit) {
251 mutex_unlock(&dmxdev->mutex);
252 return -ENODEV;
253 }
254
230 //mutex_lock(&dmxdev->mutex); 255 //mutex_lock(&dmxdev->mutex);
231 ret = dvb_dmxdev_buffer_read(&dmxdev->dvr_buffer, 256 ret = dvb_dmxdev_buffer_read(&dmxdev->dvr_buffer,
232 file->f_flags & O_NONBLOCK, 257 file->f_flags & O_NONBLOCK,
@@ -665,6 +690,8 @@ static int dvb_demux_open(struct inode *inode, struct file *file)
665 dmxdevfilter->feed.ts = NULL; 690 dmxdevfilter->feed.ts = NULL;
666 init_timer(&dmxdevfilter->timer); 691 init_timer(&dmxdevfilter->timer);
667 692
693 dvbdev->users++;
694
668 mutex_unlock(&dmxdev->mutex); 695 mutex_unlock(&dmxdev->mutex);
669 return 0; 696 return 0;
670} 697}
@@ -943,7 +970,21 @@ static int dvb_demux_release(struct inode *inode, struct file *file)
943 struct dmxdev_filter *dmxdevfilter = file->private_data; 970 struct dmxdev_filter *dmxdevfilter = file->private_data;
944 struct dmxdev *dmxdev = dmxdevfilter->dev; 971 struct dmxdev *dmxdev = dmxdevfilter->dev;
945 972
946 return dvb_dmxdev_filter_free(dmxdev, dmxdevfilter); 973 int ret;
974
975 ret = dvb_dmxdev_filter_free(dmxdev, dmxdevfilter);
976
977 mutex_lock(&dmxdev->mutex);
978 dmxdev->dvbdev->users--;
979 if(dmxdev->dvbdev->users==1 && dmxdev->exit==1) {
980 fops_put(file->f_op);
981 file->f_op = NULL;
982 mutex_unlock(&dmxdev->mutex);
983 wake_up(&dmxdev->dvbdev->wait_queue);
984 } else
985 mutex_unlock(&dmxdev->mutex);
986
987 return ret;
947} 988}
948 989
949static struct file_operations dvb_demux_fops = { 990static struct file_operations dvb_demux_fops = {
@@ -1027,6 +1068,7 @@ static struct file_operations dvb_dvr_fops = {
1027static struct dvb_device dvbdev_dvr = { 1068static struct dvb_device dvbdev_dvr = {
1028 .priv = NULL, 1069 .priv = NULL,
1029 .readers = 1, 1070 .readers = 1,
1071 .users = 1,
1030 .fops = &dvb_dvr_fops 1072 .fops = &dvb_dvr_fops
1031}; 1073};
1032 1074
@@ -1064,6 +1106,16 @@ EXPORT_SYMBOL(dvb_dmxdev_init);
1064 1106
1065void dvb_dmxdev_release(struct dmxdev *dmxdev) 1107void dvb_dmxdev_release(struct dmxdev *dmxdev)
1066{ 1108{
1109 dmxdev->exit=1;
1110 if (dmxdev->dvbdev->users > 1) {
1111 wait_event(dmxdev->dvbdev->wait_queue,
1112 dmxdev->dvbdev->users==1);
1113 }
1114 if (dmxdev->dvr_dvbdev->users > 1) {
1115 wait_event(dmxdev->dvr_dvbdev->wait_queue,
1116 dmxdev->dvr_dvbdev->users==1);
1117 }
1118
1067 dvb_unregister_device(dmxdev->dvbdev); 1119 dvb_unregister_device(dmxdev->dvbdev);
1068 dvb_unregister_device(dmxdev->dvr_dvbdev); 1120 dvb_unregister_device(dmxdev->dvr_dvbdev);
1069 1121