vfs: do bulk POLL* -> EPOLL* replacement
[linux-2.6-block.git] / drivers / media / dvb-core / dmxdev.c
index 3fe0eb740a6dce297b129799a55e0289d553ee9d..6d53af00190e396fda03bab661b56d4e4a1fc4a2 100644 (file)
@@ -27,7 +27,8 @@
 #include <linux/ioctl.h>
 #include <linux/wait.h>
 #include <linux/uaccess.h>
-#include "dmxdev.h"
+#include <media/dmxdev.h>
+#include <media/dvb_vb2.h>
 
 static int debug;
 
@@ -127,6 +128,11 @@ static int dvb_dvr_open(struct inode *inode, struct file *file)
        struct dvb_device *dvbdev = file->private_data;
        struct dmxdev *dmxdev = dvbdev->priv;
        struct dmx_frontend *front;
+#ifndef DVB_MMAP
+       bool need_ringbuffer = false;
+#else
+       const bool need_ringbuffer = true;
+#endif
 
        dprintk("%s\n", __func__);
 
@@ -138,14 +144,19 @@ static int dvb_dvr_open(struct inode *inode, struct file *file)
                return -ENODEV;
        }
 
+#ifndef DVB_MMAP
+       if ((file->f_flags & O_ACCMODE) == O_RDONLY)
+               need_ringbuffer = true;
+#else
        if ((file->f_flags & O_ACCMODE) == O_RDWR) {
                if (!(dmxdev->capabilities & DMXDEV_CAP_DUPLEX)) {
                        mutex_unlock(&dmxdev->mutex);
                        return -EOPNOTSUPP;
                }
        }
+#endif
 
-       if ((file->f_flags & O_ACCMODE) == O_RDONLY) {
+       if (need_ringbuffer) {
                void *mem;
 
                if (!dvbdev->readers) {
@@ -158,6 +169,8 @@ static int dvb_dvr_open(struct inode *inode, struct file *file)
                        return -ENOMEM;
                }
                dvb_ringbuffer_init(&dmxdev->dvr_buffer, mem, DVR_BUFFER_SIZE);
+               dvb_vb2_init(&dmxdev->dvr_vb2_ctx, "dvr",
+                            file->f_flags & O_NONBLOCK);
                dvbdev->readers--;
        }
 
@@ -187,6 +200,11 @@ static int dvb_dvr_release(struct inode *inode, struct file *file)
 {
        struct dvb_device *dvbdev = file->private_data;
        struct dmxdev *dmxdev = dvbdev->priv;
+#ifndef DVB_MMAP
+       bool need_ringbuffer = false;
+#else
+       const bool need_ringbuffer = true;
+#endif
 
        mutex_lock(&dmxdev->mutex);
 
@@ -195,7 +213,15 @@ static int dvb_dvr_release(struct inode *inode, struct file *file)
                dmxdev->demux->connect_frontend(dmxdev->demux,
                                                dmxdev->dvr_orig_fe);
        }
-       if ((file->f_flags & O_ACCMODE) == O_RDONLY) {
+#ifndef DVB_MMAP
+       if ((file->f_flags & O_ACCMODE) == O_RDONLY)
+               need_ringbuffer = true;
+#endif
+
+       if (need_ringbuffer) {
+               if (dvb_vb2_is_streaming(&dmxdev->dvr_vb2_ctx))
+                       dvb_vb2_stream_off(&dmxdev->dvr_vb2_ctx);
+               dvb_vb2_release(&dmxdev->dvr_vb2_ctx);
                dvbdev->readers++;
                if (dmxdev->dvr_buffer.data) {
                        void *mem = dmxdev->dvr_buffer.data;
@@ -359,7 +385,8 @@ static int dvb_dmxdev_section_callback(const u8 *buffer1, size_t buffer1_len,
        struct dmxdev_filter *dmxdevfilter = filter->priv;
        int ret;
 
-       if (dmxdevfilter->buffer.error) {
+       if (!dvb_vb2_is_streaming(&dmxdevfilter->vb2_ctx) &&
+           dmxdevfilter->buffer.error) {
                wake_up(&dmxdevfilter->buffer.queue);
                return 0;
        }
@@ -370,11 +397,19 @@ static int dvb_dmxdev_section_callback(const u8 *buffer1, size_t buffer1_len,
        }
        del_timer(&dmxdevfilter->timer);
        dprintk("section callback %*ph\n", 6, buffer1);
-       ret = dvb_dmxdev_buffer_write(&dmxdevfilter->buffer, buffer1,
-                                     buffer1_len);
-       if (ret == buffer1_len) {
-               ret = dvb_dmxdev_buffer_write(&dmxdevfilter->buffer, buffer2,
-                                             buffer2_len);
+       if (dvb_vb2_is_streaming(&dmxdevfilter->vb2_ctx)) {
+               ret = dvb_vb2_fill_buffer(&dmxdevfilter->vb2_ctx,
+                                         buffer1, buffer1_len);
+               if (ret == buffer1_len)
+                       ret = dvb_vb2_fill_buffer(&dmxdevfilter->vb2_ctx,
+                                                 buffer2, buffer2_len);
+       } else {
+               ret = dvb_dmxdev_buffer_write(&dmxdevfilter->buffer,
+                                             buffer1, buffer1_len);
+               if (ret == buffer1_len) {
+                       ret = dvb_dmxdev_buffer_write(&dmxdevfilter->buffer,
+                                                     buffer2, buffer2_len);
+               }
        }
        if (ret < 0)
                dmxdevfilter->buffer.error = ret;
@@ -391,6 +426,9 @@ static int dvb_dmxdev_ts_callback(const u8 *buffer1, size_t buffer1_len,
 {
        struct dmxdev_filter *dmxdevfilter = feed->priv;
        struct dvb_ringbuffer *buffer;
+#ifdef DVB_MMAP
+       struct dvb_vb2_ctx *ctx;
+#endif
        int ret;
 
        spin_lock(&dmxdevfilter->dev->lock);
@@ -399,19 +437,34 @@ static int dvb_dmxdev_ts_callback(const u8 *buffer1, size_t buffer1_len,
                return 0;
        }
 
-       if (dmxdevfilter->params.pes.output == DMX_OUT_TAP
-           || dmxdevfilter->params.pes.output == DMX_OUT_TSDEMUX_TAP)
+       if (dmxdevfilter->params.pes.output == DMX_OUT_TAP ||
+           dmxdevfilter->params.pes.output == DMX_OUT_TSDEMUX_TAP) {
                buffer = &dmxdevfilter->buffer;
-       else
+#ifdef DVB_MMAP
+               ctx = &dmxdevfilter->vb2_ctx;
+#endif
+       } else {
                buffer = &dmxdevfilter->dev->dvr_buffer;
-       if (buffer->error) {
-               spin_unlock(&dmxdevfilter->dev->lock);
-               wake_up(&buffer->queue);
-               return 0;
+#ifdef DVB_MMAP
+               ctx = &dmxdevfilter->dev->dvr_vb2_ctx;
+#endif
+       }
+
+       if (dvb_vb2_is_streaming(ctx)) {
+               ret = dvb_vb2_fill_buffer(ctx, buffer1, buffer1_len);
+               if (ret == buffer1_len)
+                       ret = dvb_vb2_fill_buffer(ctx, buffer2, buffer2_len);
+       } else {
+               if (buffer->error) {
+                       spin_unlock(&dmxdevfilter->dev->lock);
+                       wake_up(&buffer->queue);
+                       return 0;
+               }
+               ret = dvb_dmxdev_buffer_write(buffer, buffer1, buffer1_len);
+               if (ret == buffer1_len)
+                       ret = dvb_dmxdev_buffer_write(buffer,
+                                                     buffer2, buffer2_len);
        }
-       ret = dvb_dmxdev_buffer_write(buffer, buffer1, buffer1_len);
-       if (ret == buffer1_len)
-               ret = dvb_dmxdev_buffer_write(buffer, buffer2, buffer2_len);
        if (ret < 0)
                buffer->error = ret;
        spin_unlock(&dmxdevfilter->dev->lock);
@@ -750,6 +803,8 @@ static int dvb_demux_open(struct inode *inode, struct file *file)
        file->private_data = dmxdevfilter;
 
        dvb_ringbuffer_init(&dmxdevfilter->buffer, NULL, 8192);
+       dvb_vb2_init(&dmxdevfilter->vb2_ctx, "demux_filter",
+                    file->f_flags & O_NONBLOCK);
        dmxdevfilter->type = DMXDEV_TYPE_NONE;
        dvb_dmxdev_filter_state_set(dmxdevfilter, DMXDEV_STATE_ALLOCATED);
        timer_setup(&dmxdevfilter->timer, dvb_dmxdev_filter_timeout, 0);
@@ -765,6 +820,10 @@ static int dvb_dmxdev_filter_free(struct dmxdev *dmxdev,
 {
        mutex_lock(&dmxdev->mutex);
        mutex_lock(&dmxdevfilter->mutex);
+       if (dvb_vb2_is_streaming(&dmxdevfilter->vb2_ctx))
+               dvb_vb2_stream_off(&dmxdevfilter->vb2_ctx);
+       dvb_vb2_release(&dmxdevfilter->vb2_ctx);
+
 
        dvb_dmxdev_filter_stop(dmxdevfilter);
        dvb_dmxdev_filter_reset(dmxdevfilter);
@@ -1052,6 +1111,54 @@ static int dvb_demux_do_ioctl(struct file *file,
                mutex_unlock(&dmxdevfilter->mutex);
                break;
 
+#ifdef DVB_MMAP
+       case DMX_REQBUFS:
+               if (mutex_lock_interruptible(&dmxdevfilter->mutex)) {
+                       mutex_unlock(&dmxdev->mutex);
+                       return -ERESTARTSYS;
+               }
+               ret = dvb_vb2_reqbufs(&dmxdevfilter->vb2_ctx, parg);
+               mutex_unlock(&dmxdevfilter->mutex);
+               break;
+
+       case DMX_QUERYBUF:
+               if (mutex_lock_interruptible(&dmxdevfilter->mutex)) {
+                       mutex_unlock(&dmxdev->mutex);
+                       return -ERESTARTSYS;
+               }
+               ret = dvb_vb2_querybuf(&dmxdevfilter->vb2_ctx, parg);
+               mutex_unlock(&dmxdevfilter->mutex);
+               break;
+
+       case DMX_EXPBUF:
+               if (mutex_lock_interruptible(&dmxdevfilter->mutex)) {
+                       mutex_unlock(&dmxdev->mutex);
+                       return -ERESTARTSYS;
+               }
+               ret = dvb_vb2_expbuf(&dmxdevfilter->vb2_ctx, parg);
+               mutex_unlock(&dmxdevfilter->mutex);
+               break;
+
+       case DMX_QBUF:
+               if (mutex_lock_interruptible(&dmxdevfilter->mutex)) {
+                       mutex_unlock(&dmxdev->mutex);
+                       return -ERESTARTSYS;
+               }
+               ret = dvb_vb2_qbuf(&dmxdevfilter->vb2_ctx, parg);
+               if (ret == 0 && !dvb_vb2_is_streaming(&dmxdevfilter->vb2_ctx))
+                       ret = dvb_vb2_stream_on(&dmxdevfilter->vb2_ctx);
+               mutex_unlock(&dmxdevfilter->mutex);
+               break;
+
+       case DMX_DQBUF:
+               if (mutex_lock_interruptible(&dmxdevfilter->mutex)) {
+                       mutex_unlock(&dmxdev->mutex);
+                       return -ERESTARTSYS;
+               }
+               ret = dvb_vb2_dqbuf(&dmxdevfilter->vb2_ctx, parg);
+               mutex_unlock(&dmxdevfilter->mutex);
+               break;
+#endif
        default:
                ret = -EINVAL;
                break;
@@ -1072,7 +1179,9 @@ static __poll_t dvb_demux_poll(struct file *file, poll_table *wait)
        __poll_t mask = 0;
 
        if ((!dmxdevfilter) || dmxdevfilter->dev->exit)
-               return POLLERR;
+               return EPOLLERR;
+       if (dvb_vb2_is_streaming(&dmxdevfilter->vb2_ctx))
+               return dvb_vb2_poll(&dmxdevfilter->vb2_ctx, file, wait);
 
        poll_wait(file, &dmxdevfilter->buffer.queue, wait);
 
@@ -1082,19 +1191,41 @@ static __poll_t dvb_demux_poll(struct file *file, poll_table *wait)
                return 0;
 
        if (dmxdevfilter->buffer.error)
-               mask |= (POLLIN | POLLRDNORM | POLLPRI | POLLERR);
+               mask |= (EPOLLIN | EPOLLRDNORM | EPOLLPRI | EPOLLERR);
 
        if (!dvb_ringbuffer_empty(&dmxdevfilter->buffer))
-               mask |= (POLLIN | POLLRDNORM | POLLPRI);
+               mask |= (EPOLLIN | EPOLLRDNORM | EPOLLPRI);
 
        return mask;
 }
 
-static int dvb_demux_release(struct inode *inode, struct file *file)
+#ifdef DVB_MMAP
+static int dvb_demux_mmap(struct file *file, struct vm_area_struct *vma)
 {
        struct dmxdev_filter *dmxdevfilter = file->private_data;
        struct dmxdev *dmxdev = dmxdevfilter->dev;
+       int ret;
+
+       if (mutex_lock_interruptible(&dmxdev->mutex))
+               return -ERESTARTSYS;
+
+       if (mutex_lock_interruptible(&dmxdevfilter->mutex)) {
+               mutex_unlock(&dmxdev->mutex);
+               return -ERESTARTSYS;
+       }
+       ret = dvb_vb2_mmap(&dmxdevfilter->vb2_ctx, vma);
+
+       mutex_unlock(&dmxdevfilter->mutex);
+       mutex_unlock(&dmxdev->mutex);
 
+       return ret;
+}
+#endif
+
+static int dvb_demux_release(struct inode *inode, struct file *file)
+{
+       struct dmxdev_filter *dmxdevfilter = file->private_data;
+       struct dmxdev *dmxdev = dmxdevfilter->dev;
        int ret;
 
        ret = dvb_dmxdev_filter_free(dmxdev, dmxdevfilter);
@@ -1118,6 +1249,9 @@ static const struct file_operations dvb_demux_fops = {
        .release = dvb_demux_release,
        .poll = dvb_demux_poll,
        .llseek = default_llseek,
+#ifdef DVB_MMAP
+       .mmap = dvb_demux_mmap,
+#endif
 };
 
 static const struct dvb_device dvbdev_demux = {
@@ -1146,6 +1280,29 @@ static int dvb_dvr_do_ioctl(struct file *file,
                ret = dvb_dvr_set_buffer_size(dmxdev, arg);
                break;
 
+#ifdef DVB_MMAP
+       case DMX_REQBUFS:
+               ret = dvb_vb2_reqbufs(&dmxdev->dvr_vb2_ctx, parg);
+               break;
+
+       case DMX_QUERYBUF:
+               ret = dvb_vb2_querybuf(&dmxdev->dvr_vb2_ctx, parg);
+               break;
+
+       case DMX_EXPBUF:
+               ret = dvb_vb2_expbuf(&dmxdev->dvr_vb2_ctx, parg);
+               break;
+
+       case DMX_QBUF:
+               ret = dvb_vb2_qbuf(&dmxdev->dvr_vb2_ctx, parg);
+               if (ret == 0 && !dvb_vb2_is_streaming(&dmxdev->dvr_vb2_ctx))
+                       ret = dvb_vb2_stream_on(&dmxdev->dvr_vb2_ctx);
+               break;
+
+       case DMX_DQBUF:
+               ret = dvb_vb2_dqbuf(&dmxdev->dvr_vb2_ctx, parg);
+               break;
+#endif
        default:
                ret = -EINVAL;
                break;
@@ -1165,26 +1322,56 @@ static __poll_t dvb_dvr_poll(struct file *file, poll_table *wait)
        struct dvb_device *dvbdev = file->private_data;
        struct dmxdev *dmxdev = dvbdev->priv;
        __poll_t mask = 0;
+#ifndef DVB_MMAP
+       bool need_ringbuffer = false;
+#else
+       const bool need_ringbuffer = true;
+#endif
 
        dprintk("%s\n", __func__);
 
        if (dmxdev->exit)
-               return POLLERR;
+               return EPOLLERR;
+       if (dvb_vb2_is_streaming(&dmxdev->dvr_vb2_ctx))
+               return dvb_vb2_poll(&dmxdev->dvr_vb2_ctx, file, wait);
 
        poll_wait(file, &dmxdev->dvr_buffer.queue, wait);
 
-       if ((file->f_flags & O_ACCMODE) == O_RDONLY) {
+#ifndef DVB_MMAP
+       if ((file->f_flags & O_ACCMODE) == O_RDONLY)
+               need_ringbuffer = true;
+#endif
+       if (need_ringbuffer) {
                if (dmxdev->dvr_buffer.error)
-                       mask |= (POLLIN | POLLRDNORM | POLLPRI | POLLERR);
+                       mask |= (EPOLLIN | EPOLLRDNORM | EPOLLPRI | EPOLLERR);
 
                if (!dvb_ringbuffer_empty(&dmxdev->dvr_buffer))
-                       mask |= (POLLIN | POLLRDNORM | POLLPRI);
+                       mask |= (EPOLLIN | EPOLLRDNORM | EPOLLPRI);
        } else
-               mask |= (POLLOUT | POLLWRNORM | POLLPRI);
+               mask |= (EPOLLOUT | EPOLLWRNORM | EPOLLPRI);
 
        return mask;
 }
 
+#ifdef DVB_MMAP
+static int dvb_dvr_mmap(struct file *file, struct vm_area_struct *vma)
+{
+       struct dvb_device *dvbdev = file->private_data;
+       struct dmxdev *dmxdev = dvbdev->priv;
+       int ret;
+
+       if (dmxdev->exit)
+               return -ENODEV;
+
+       if (mutex_lock_interruptible(&dmxdev->mutex))
+               return -ERESTARTSYS;
+
+       ret = dvb_vb2_mmap(&dmxdev->dvr_vb2_ctx, vma);
+       mutex_unlock(&dmxdev->mutex);
+       return ret;
+}
+#endif
+
 static const struct file_operations dvb_dvr_fops = {
        .owner = THIS_MODULE,
        .read = dvb_dvr_read,
@@ -1194,6 +1381,9 @@ static const struct file_operations dvb_dvr_fops = {
        .release = dvb_dvr_release,
        .poll = dvb_dvr_poll,
        .llseek = default_llseek,
+#ifdef DVB_MMAP
+       .mmap = dvb_dvr_mmap,
+#endif
 };
 
 static const struct dvb_device dvbdev_dvr = {