]> err.no Git - linux-2.6/blobdiff - drivers/media/dvb/dvb-core/dmxdev.c
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/cooloney...
[linux-2.6] / drivers / media / dvb / dvb-core / dmxdev.c
index fc77de45ca4dc415fdaa77634eda086a2e78945e..f94bc31e3b3334d020b7e5dc95759f25a3e70ca8 100644 (file)
@@ -24,7 +24,6 @@
 #include <linux/slab.h>
 #include <linux/vmalloc.h>
 #include <linux/module.h>
-#include <linux/moduleparam.h>
 #include <linux/poll.h>
 #include <linux/ioctl.h>
 #include <linux/wait.h>
@@ -97,7 +96,7 @@ static ssize_t dvb_dmxdev_buffer_read(struct dvb_ringbuffer *src,
                if (avail > todo)
                        avail = todo;
 
-               ret = dvb_ringbuffer_read(src, buf, avail, 1);
+               ret = dvb_ringbuffer_read(src, (u8 *)buf, avail, 1);
                if (ret < 0)
                        break;
 
@@ -132,6 +131,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 +175,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;
 }
@@ -180,8 +185,7 @@ static int dvb_dvr_release(struct inode *inode, struct file *file)
        struct dvb_device *dvbdev = file->private_data;
        struct dmxdev *dmxdev = dvbdev->priv;
 
-       if (mutex_lock_interruptible(&dmxdev->mutex))
-               return -ERESTARTSYS;
+       mutex_lock(&dmxdev->mutex);
 
        if ((file->f_flags & O_ACCMODE) == O_WRONLY) {
                dmxdev->demux->disconnect_frontend(dmxdev->demux);
@@ -199,7 +203,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;
 }
 
@@ -216,6 +229,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;
@@ -228,6 +246,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,
@@ -666,6 +689,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;
 }
@@ -673,13 +698,8 @@ static int dvb_demux_open(struct inode *inode, struct file *file)
 static int dvb_dmxdev_filter_free(struct dmxdev *dmxdev,
                                  struct dmxdev_filter *dmxdevfilter)
 {
-       if (mutex_lock_interruptible(&dmxdev->mutex))
-               return -ERESTARTSYS;
-
-       if (mutex_lock_interruptible(&dmxdevfilter->mutex)) {
-               mutex_unlock(&dmxdev->mutex);
-               return -ERESTARTSYS;
-       }
+       mutex_lock(&dmxdev->mutex);
+       mutex_lock(&dmxdevfilter->mutex);
 
        dvb_dmxdev_filter_stop(dmxdevfilter);
        dvb_dmxdev_filter_reset(dmxdevfilter);
@@ -949,7 +969,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 = {
@@ -1033,6 +1067,7 @@ static struct file_operations dvb_dvr_fops = {
 static struct dvb_device dvbdev_dvr = {
        .priv = NULL,
        .readers = 1,
+       .users = 1,
        .fops = &dvb_dvr_fops
 };
 
@@ -1070,6 +1105,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);