Commit 57861b43 authored by Markus Rechberger's avatar Markus Rechberger Committed by Mauro Carvalho Chehab

V4L/DVB (5511): Fix 2/3 for bug 7819: demux and dvr

fixing hotplug issue for demux[n] and dvr[n]
Signed-off-by: default avatarMichal CIJOML Semler <cijoml@volny.cz>
Signed-off-by: default avatarMarkus Rechberger <markus.rechberger@amd.com>
Signed-off-by: default avatarMauro Carvalho Chehab <mchehab@infradead.org>
parent ca5be9cd
...@@ -132,6 +132,11 @@ static int dvb_dvr_open(struct inode *inode, struct file *file) ...@@ -132,6 +132,11 @@ static int dvb_dvr_open(struct inode *inode, struct file *file)
if (mutex_lock_interruptible(&dmxdev->mutex)) if (mutex_lock_interruptible(&dmxdev->mutex))
return -ERESTARTSYS; return -ERESTARTSYS;
if (dmxdev->exit) {
mutex_unlock(&dmxdev->mutex);
return -ENODEV;
}
if ((file->f_flags & O_ACCMODE) == O_RDWR) { if ((file->f_flags & O_ACCMODE) == O_RDWR) {
if (!(dmxdev->capabilities & DMXDEV_CAP_DUPLEX)) { if (!(dmxdev->capabilities & DMXDEV_CAP_DUPLEX)) {
mutex_unlock(&dmxdev->mutex); mutex_unlock(&dmxdev->mutex);
...@@ -171,6 +176,7 @@ static int dvb_dvr_open(struct inode *inode, struct file *file) ...@@ -171,6 +176,7 @@ static int dvb_dvr_open(struct inode *inode, struct file *file)
dmxdev->demux->disconnect_frontend(dmxdev->demux); dmxdev->demux->disconnect_frontend(dmxdev->demux);
dmxdev->demux->connect_frontend(dmxdev->demux, front); dmxdev->demux->connect_frontend(dmxdev->demux, front);
} }
dvbdev->users++;
mutex_unlock(&dmxdev->mutex); mutex_unlock(&dmxdev->mutex);
return 0; return 0;
} }
...@@ -198,7 +204,16 @@ static int dvb_dvr_release(struct inode *inode, struct file *file) ...@@ -198,7 +204,16 @@ static int dvb_dvr_release(struct inode *inode, struct file *file)
vfree(mem); vfree(mem);
} }
} }
mutex_unlock(&dmxdev->mutex); /* 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; return 0;
} }
...@@ -215,6 +230,11 @@ static ssize_t dvb_dvr_write(struct file *file, const char __user *buf, ...@@ -215,6 +230,11 @@ static ssize_t dvb_dvr_write(struct file *file, const char __user *buf,
return -EINVAL; return -EINVAL;
if (mutex_lock_interruptible(&dmxdev->mutex)) if (mutex_lock_interruptible(&dmxdev->mutex))
return -ERESTARTSYS; return -ERESTARTSYS;
if (dmxdev->exit) {
mutex_unlock(&dmxdev->mutex);
return -ENODEV;
}
ret = dmxdev->demux->write(dmxdev->demux, buf, count); ret = dmxdev->demux->write(dmxdev->demux, buf, count);
mutex_unlock(&dmxdev->mutex); mutex_unlock(&dmxdev->mutex);
return ret; return ret;
...@@ -227,6 +247,11 @@ static ssize_t dvb_dvr_read(struct file *file, char __user *buf, size_t count, ...@@ -227,6 +247,11 @@ static ssize_t dvb_dvr_read(struct file *file, char __user *buf, size_t count,
struct dmxdev *dmxdev = dvbdev->priv; struct dmxdev *dmxdev = dvbdev->priv;
int ret; int ret;
if (dmxdev->exit) {
mutex_unlock(&dmxdev->mutex);
return -ENODEV;
}
//mutex_lock(&dmxdev->mutex); //mutex_lock(&dmxdev->mutex);
ret = dvb_dmxdev_buffer_read(&dmxdev->dvr_buffer, ret = dvb_dmxdev_buffer_read(&dmxdev->dvr_buffer,
file->f_flags & O_NONBLOCK, file->f_flags & O_NONBLOCK,
...@@ -665,6 +690,8 @@ static int dvb_demux_open(struct inode *inode, struct file *file) ...@@ -665,6 +690,8 @@ static int dvb_demux_open(struct inode *inode, struct file *file)
dmxdevfilter->feed.ts = NULL; dmxdevfilter->feed.ts = NULL;
init_timer(&dmxdevfilter->timer); init_timer(&dmxdevfilter->timer);
dvbdev->users++;
mutex_unlock(&dmxdev->mutex); mutex_unlock(&dmxdev->mutex);
return 0; return 0;
} }
...@@ -943,7 +970,21 @@ static int dvb_demux_release(struct inode *inode, struct file *file) ...@@ -943,7 +970,21 @@ static int dvb_demux_release(struct inode *inode, struct file *file)
struct dmxdev_filter *dmxdevfilter = file->private_data; struct dmxdev_filter *dmxdevfilter = file->private_data;
struct dmxdev *dmxdev = dmxdevfilter->dev; 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 = { static struct file_operations dvb_demux_fops = {
...@@ -1027,6 +1068,7 @@ static struct file_operations dvb_dvr_fops = { ...@@ -1027,6 +1068,7 @@ static struct file_operations dvb_dvr_fops = {
static struct dvb_device dvbdev_dvr = { static struct dvb_device dvbdev_dvr = {
.priv = NULL, .priv = NULL,
.readers = 1, .readers = 1,
.users = 1,
.fops = &dvb_dvr_fops .fops = &dvb_dvr_fops
}; };
...@@ -1064,6 +1106,16 @@ EXPORT_SYMBOL(dvb_dmxdev_init); ...@@ -1064,6 +1106,16 @@ EXPORT_SYMBOL(dvb_dmxdev_init);
void dvb_dmxdev_release(struct dmxdev *dmxdev) 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->dvbdev);
dvb_unregister_device(dmxdev->dvr_dvbdev); dvb_unregister_device(dmxdev->dvr_dvbdev);
......
...@@ -91,6 +91,8 @@ struct dmxdev { ...@@ -91,6 +91,8 @@ struct dmxdev {
int filternum; int filternum;
int capabilities; int capabilities;
unsigned int exit:1;
#define DMXDEV_CAP_DUPLEX 1 #define DMXDEV_CAP_DUPLEX 1
struct dmx_frontend *dvr_orig_fe; struct dmx_frontend *dvr_orig_fe;
......
...@@ -1208,6 +1208,8 @@ int dvb_dmx_init(struct dvb_demux *dvbdemux) ...@@ -1208,6 +1208,8 @@ int dvb_dmx_init(struct dvb_demux *dvbdemux)
dmx->disconnect_frontend = dvbdmx_disconnect_frontend; dmx->disconnect_frontend = dvbdmx_disconnect_frontend;
dmx->get_pes_pids = dvbdmx_get_pes_pids; dmx->get_pes_pids = dvbdmx_get_pes_pids;
init_waitqueue_head (&dvbdemux->wait_queue);
mutex_init(&dvbdemux->mutex); mutex_init(&dvbdemux->mutex);
spin_lock_init(&dvbdemux->lock); spin_lock_init(&dvbdemux->lock);
......
...@@ -119,6 +119,7 @@ struct dvb_demux { ...@@ -119,6 +119,7 @@ struct dvb_demux {
u16 pids[DMX_TS_PES_OTHER]; u16 pids[DMX_TS_PES_OTHER];
int playing; int playing;
int recording; int recording;
wait_queue_head_t wait_queue;
#define DMX_MAX_PID 0x2000 #define DMX_MAX_PID 0x2000
struct list_head feed_list; struct list_head feed_list;
......
...@@ -607,10 +607,6 @@ static void dvb_frontend_stop(struct dvb_frontend *fe) ...@@ -607,10 +607,6 @@ static void dvb_frontend_stop(struct dvb_frontend *fe)
kthread_stop(fepriv->thread); kthread_stop(fepriv->thread);
if (fepriv->dvbdev->users < -1)
wait_event_interruptible(fepriv->dvbdev->wait_queue,
fepriv->dvbdev->users==-1);
init_MUTEX (&fepriv->sem); init_MUTEX (&fepriv->sem);
fepriv->state = FESTATE_IDLE; fepriv->state = FESTATE_IDLE;
...@@ -1043,7 +1039,7 @@ static int dvb_frontend_release(struct inode *inode, struct file *file) ...@@ -1043,7 +1039,7 @@ static int dvb_frontend_release(struct inode *inode, struct file *file)
if (dvbdev->users==-1 && fepriv->exit==1) { if (dvbdev->users==-1 && fepriv->exit==1) {
fops_put(file->f_op); fops_put(file->f_op);
file->f_op = NULL; file->f_op = NULL;
wake_up_interruptible (&dvbdev->wait_queue); wake_up(&dvbdev->wait_queue);
} }
return ret; return ret;
} }
...@@ -1104,7 +1100,14 @@ int dvb_unregister_frontend(struct dvb_frontend* fe) ...@@ -1104,7 +1100,14 @@ int dvb_unregister_frontend(struct dvb_frontend* fe)
struct dvb_frontend_private *fepriv = fe->frontend_priv; struct dvb_frontend_private *fepriv = fe->frontend_priv;
dprintk ("%s\n", __FUNCTION__); dprintk ("%s\n", __FUNCTION__);
mutex_lock(&frontend_mutex);
dvb_frontend_stop (fe); 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); mutex_lock(&frontend_mutex);
dvb_unregister_device (fepriv->dvbdev); dvb_unregister_device (fepriv->dvbdev);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment