mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-08-23 09:19:51 +00:00
V4L/DVB (5511): Fix 2/3 for bug 7819: demux and dvr
fixing hotplug issue for demux[n] and dvr[n] Signed-off-by: Michal CIJOML Semler <cijoml@volny.cz> Signed-off-by: Markus Rechberger <markus.rechberger@amd.com> Signed-off-by: Mauro Carvalho Chehab <mchehab@infradead.org>
This commit is contained in:
parent
ca5be9cd05
commit
57861b432b
5 changed files with 67 additions and 7 deletions
|
@ -132,6 +132,11 @@ static int dvb_dvr_open(struct inode *inode, struct file *file)
|
|||
if (mutex_lock_interruptible(&dmxdev->mutex))
|
||||
return -ERESTARTSYS;
|
||||
|
||||
if (dmxdev->exit) {
|
||||
mutex_unlock(&dmxdev->mutex);
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
if ((file->f_flags & O_ACCMODE) == O_RDWR) {
|
||||
if (!(dmxdev->capabilities & DMXDEV_CAP_DUPLEX)) {
|
||||
mutex_unlock(&dmxdev->mutex);
|
||||
|
@ -171,6 +176,7 @@ static int dvb_dvr_open(struct inode *inode, struct file *file)
|
|||
dmxdev->demux->disconnect_frontend(dmxdev->demux);
|
||||
dmxdev->demux->connect_frontend(dmxdev->demux, front);
|
||||
}
|
||||
dvbdev->users++;
|
||||
mutex_unlock(&dmxdev->mutex);
|
||||
return 0;
|
||||
}
|
||||
|
@ -198,7 +204,16 @@ static int dvb_dvr_release(struct inode *inode, struct file *file)
|
|||
vfree(mem);
|
||||
}
|
||||
}
|
||||
/* TODO */
|
||||
dvbdev->users--;
|
||||
if(dvbdev->users==-1 && dmxdev->exit==1) {
|
||||
fops_put(file->f_op);
|
||||
file->f_op = NULL;
|
||||
mutex_unlock(&dmxdev->mutex);
|
||||
wake_up(&dvbdev->wait_queue);
|
||||
} else
|
||||
mutex_unlock(&dmxdev->mutex);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -215,6 +230,11 @@ static ssize_t dvb_dvr_write(struct file *file, const char __user *buf,
|
|||
return -EINVAL;
|
||||
if (mutex_lock_interruptible(&dmxdev->mutex))
|
||||
return -ERESTARTSYS;
|
||||
|
||||
if (dmxdev->exit) {
|
||||
mutex_unlock(&dmxdev->mutex);
|
||||
return -ENODEV;
|
||||
}
|
||||
ret = dmxdev->demux->write(dmxdev->demux, buf, count);
|
||||
mutex_unlock(&dmxdev->mutex);
|
||||
return ret;
|
||||
|
@ -227,6 +247,11 @@ static ssize_t dvb_dvr_read(struct file *file, char __user *buf, size_t count,
|
|||
struct dmxdev *dmxdev = dvbdev->priv;
|
||||
int ret;
|
||||
|
||||
if (dmxdev->exit) {
|
||||
mutex_unlock(&dmxdev->mutex);
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
//mutex_lock(&dmxdev->mutex);
|
||||
ret = dvb_dmxdev_buffer_read(&dmxdev->dvr_buffer,
|
||||
file->f_flags & O_NONBLOCK,
|
||||
|
@ -665,6 +690,8 @@ static int dvb_demux_open(struct inode *inode, struct file *file)
|
|||
dmxdevfilter->feed.ts = NULL;
|
||||
init_timer(&dmxdevfilter->timer);
|
||||
|
||||
dvbdev->users++;
|
||||
|
||||
mutex_unlock(&dmxdev->mutex);
|
||||
return 0;
|
||||
}
|
||||
|
@ -943,7 +970,21 @@ static int dvb_demux_release(struct inode *inode, struct file *file)
|
|||
struct dmxdev_filter *dmxdevfilter = file->private_data;
|
||||
struct dmxdev *dmxdev = dmxdevfilter->dev;
|
||||
|
||||
return dvb_dmxdev_filter_free(dmxdev, dmxdevfilter);
|
||||
int ret;
|
||||
|
||||
ret = dvb_dmxdev_filter_free(dmxdev, dmxdevfilter);
|
||||
|
||||
mutex_lock(&dmxdev->mutex);
|
||||
dmxdev->dvbdev->users--;
|
||||
if(dmxdev->dvbdev->users==1 && dmxdev->exit==1) {
|
||||
fops_put(file->f_op);
|
||||
file->f_op = NULL;
|
||||
mutex_unlock(&dmxdev->mutex);
|
||||
wake_up(&dmxdev->dvbdev->wait_queue);
|
||||
} else
|
||||
mutex_unlock(&dmxdev->mutex);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static struct file_operations dvb_demux_fops = {
|
||||
|
@ -1027,6 +1068,7 @@ static struct file_operations dvb_dvr_fops = {
|
|||
static struct dvb_device dvbdev_dvr = {
|
||||
.priv = NULL,
|
||||
.readers = 1,
|
||||
.users = 1,
|
||||
.fops = &dvb_dvr_fops
|
||||
};
|
||||
|
||||
|
@ -1064,6 +1106,16 @@ EXPORT_SYMBOL(dvb_dmxdev_init);
|
|||
|
||||
void dvb_dmxdev_release(struct dmxdev *dmxdev)
|
||||
{
|
||||
dmxdev->exit=1;
|
||||
if (dmxdev->dvbdev->users > 1) {
|
||||
wait_event(dmxdev->dvbdev->wait_queue,
|
||||
dmxdev->dvbdev->users==1);
|
||||
}
|
||||
if (dmxdev->dvr_dvbdev->users > 1) {
|
||||
wait_event(dmxdev->dvr_dvbdev->wait_queue,
|
||||
dmxdev->dvr_dvbdev->users==1);
|
||||
}
|
||||
|
||||
dvb_unregister_device(dmxdev->dvbdev);
|
||||
dvb_unregister_device(dmxdev->dvr_dvbdev);
|
||||
|
||||
|
|
|
@ -91,6 +91,8 @@ struct dmxdev {
|
|||
|
||||
int filternum;
|
||||
int capabilities;
|
||||
|
||||
unsigned int exit:1;
|
||||
#define DMXDEV_CAP_DUPLEX 1
|
||||
struct dmx_frontend *dvr_orig_fe;
|
||||
|
||||
|
|
|
@ -1208,6 +1208,8 @@ int dvb_dmx_init(struct dvb_demux *dvbdemux)
|
|||
dmx->disconnect_frontend = dvbdmx_disconnect_frontend;
|
||||
dmx->get_pes_pids = dvbdmx_get_pes_pids;
|
||||
|
||||
init_waitqueue_head (&dvbdemux->wait_queue);
|
||||
|
||||
mutex_init(&dvbdemux->mutex);
|
||||
spin_lock_init(&dvbdemux->lock);
|
||||
|
||||
|
|
|
@ -119,6 +119,7 @@ struct dvb_demux {
|
|||
u16 pids[DMX_TS_PES_OTHER];
|
||||
int playing;
|
||||
int recording;
|
||||
wait_queue_head_t wait_queue;
|
||||
|
||||
#define DMX_MAX_PID 0x2000
|
||||
struct list_head feed_list;
|
||||
|
|
|
@ -607,10 +607,6 @@ static void dvb_frontend_stop(struct dvb_frontend *fe)
|
|||
|
||||
kthread_stop(fepriv->thread);
|
||||
|
||||
if (fepriv->dvbdev->users < -1)
|
||||
wait_event_interruptible(fepriv->dvbdev->wait_queue,
|
||||
fepriv->dvbdev->users==-1);
|
||||
|
||||
init_MUTEX (&fepriv->sem);
|
||||
fepriv->state = FESTATE_IDLE;
|
||||
|
||||
|
@ -1043,7 +1039,7 @@ static int dvb_frontend_release(struct inode *inode, struct file *file)
|
|||
if (dvbdev->users==-1 && fepriv->exit==1) {
|
||||
fops_put(file->f_op);
|
||||
file->f_op = NULL;
|
||||
wake_up_interruptible (&dvbdev->wait_queue);
|
||||
wake_up(&dvbdev->wait_queue);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
@ -1104,7 +1100,14 @@ int dvb_unregister_frontend(struct dvb_frontend* fe)
|
|||
struct dvb_frontend_private *fepriv = fe->frontend_priv;
|
||||
dprintk ("%s\n", __FUNCTION__);
|
||||
|
||||
mutex_lock(&frontend_mutex);
|
||||
dvb_frontend_stop (fe);
|
||||
mutex_unlock(&frontend_mutex);
|
||||
|
||||
if (fepriv->dvbdev->users < -1)
|
||||
wait_event(fepriv->dvbdev->wait_queue,
|
||||
fepriv->dvbdev->users==-1);
|
||||
|
||||
mutex_lock(&frontend_mutex);
|
||||
dvb_unregister_device (fepriv->dvbdev);
|
||||
|
||||
|
|
Loading…
Reference in a new issue