diff --git a/drivers/media/dvb/dvb-core/dmxdev.c b/drivers/media/dvb/dvb-core/dmxdev.c
index a5c0e1a3e6d14f1cd41f55247af56409f2b9bb46..275df65fde992680b82631f7ee1ca98750a6d256 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)
 	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);
 		}
 	}
-	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;
 }
 
@@ -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);
 
diff --git a/drivers/media/dvb/dvb-core/dmxdev.h b/drivers/media/dvb/dvb-core/dmxdev.h
index d2bee9ffe43cff81421bba33846c42cae9234f92..29746e70d3252dedaa2a40856b91472e55934603 100644
--- a/drivers/media/dvb/dvb-core/dmxdev.h
+++ b/drivers/media/dvb/dvb-core/dmxdev.h
@@ -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;
 
diff --git a/drivers/media/dvb/dvb-core/dvb_demux.c b/drivers/media/dvb/dvb-core/dvb_demux.c
index 6d8d1c3df8631a4832b34954e44e5633cd3a34c6..f558ac9c09547bd27b2cd8c75ded25a6566314b1 100644
--- a/drivers/media/dvb/dvb-core/dvb_demux.c
+++ b/drivers/media/dvb/dvb-core/dvb_demux.c
@@ -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);
 
diff --git a/drivers/media/dvb/dvb-core/dvb_demux.h b/drivers/media/dvb/dvb-core/dvb_demux.h
index 2c5f915329ca9c5658e68628208f57c58c856364..e1e91399afd91fc43c0444e8a89687e4ae4a916c 100644
--- a/drivers/media/dvb/dvb-core/dvb_demux.h
+++ b/drivers/media/dvb/dvb-core/dvb_demux.h
@@ -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;
diff --git a/drivers/media/dvb/dvb-core/dvb_frontend.c b/drivers/media/dvb/dvb-core/dvb_frontend.c
index 9783d392b7d3babddc9f7965a5f7130ed9b9a21f..f4e4ca2dcaded8083ac6927ba4630636be374de5 100644
--- a/drivers/media/dvb/dvb-core/dvb_frontend.c
+++ b/drivers/media/dvb/dvb-core/dvb_frontend.c
@@ -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);