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

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
Loading
Loading
Loading
Loading
+54 −2
Original line number Diff line number Diff line
@@ -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);

+2 −0
Original line number Diff line number Diff line
@@ -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;

+2 −0
Original line number Diff line number Diff line
@@ -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);

+1 −0
Original line number Diff line number Diff line
@@ -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;
+8 −5
Original line number Diff line number Diff line
@@ -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);