diff options
Diffstat (limited to 'drivers/media/dvb/dvb-core/dmxdev.c')
-rw-r--r-- | drivers/media/dvb/dvb-core/dmxdev.c | 56 |
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 | ||
949 | static struct file_operations dvb_demux_fops = { | 990 | static struct file_operations dvb_demux_fops = { |
@@ -1027,6 +1068,7 @@ static struct file_operations dvb_dvr_fops = { | |||
1027 | static struct dvb_device dvbdev_dvr = { | 1068 | static 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 | ||
1065 | void dvb_dmxdev_release(struct dmxdev *dmxdev) | 1107 | void 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 | ||