summaryrefslogtreecommitdiff
path: root/drivers/media/dvb-core/dmxdev.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/media/dvb-core/dmxdev.c')
-rw-r--r--drivers/media/dvb-core/dmxdev.c115
1 files changed, 65 insertions, 50 deletions
diff --git a/drivers/media/dvb-core/dmxdev.c b/drivers/media/dvb-core/dmxdev.c
index 6d53af00190e..61a750fae465 100644
--- a/drivers/media/dvb-core/dmxdev.c
+++ b/drivers/media/dvb-core/dmxdev.c
@@ -128,11 +128,7 @@ 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__);
@@ -144,17 +140,31 @@ static int dvb_dvr_open(struct inode *inode, struct file *file)
return -ENODEV;
}
-#ifndef DVB_MMAP
+ dmxdev->may_do_mmap = 0;
+
+ /*
+ * The logic here is a little tricky due to the ifdef.
+ *
+ * The ringbuffer is used for both read and mmap.
+ *
+ * It is not needed, however, on two situations:
+ * - Write devices (access with O_WRONLY);
+ * - For duplex device nodes, opened with O_RDWR.
+ */
+
if ((file->f_flags & O_ACCMODE) == O_RDONLY)
need_ringbuffer = true;
-#else
- if ((file->f_flags & O_ACCMODE) == O_RDWR) {
+ else if ((file->f_flags & O_ACCMODE) == O_RDWR) {
if (!(dmxdev->capabilities & DMXDEV_CAP_DUPLEX)) {
+#ifdef CONFIG_DVB_MMAP
+ dmxdev->may_do_mmap = 1;
+ need_ringbuffer = true;
+#else
mutex_unlock(&dmxdev->mutex);
return -EOPNOTSUPP;
+#endif
}
}
-#endif
if (need_ringbuffer) {
void *mem;
@@ -169,8 +179,9 @@ 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);
+ if (dmxdev->may_do_mmap)
+ dvb_vb2_init(&dmxdev->dvr_vb2_ctx, "dvr",
+ file->f_flags & O_NONBLOCK);
dvbdev->readers--;
}
@@ -200,11 +211,6 @@ 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);
@@ -213,15 +219,14 @@ static int dvb_dvr_release(struct inode *inode, struct file *file)
dmxdev->demux->connect_frontend(dmxdev->demux,
dmxdev->dvr_orig_fe);
}
-#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);
+ if (((file->f_flags & O_ACCMODE) == O_RDONLY) ||
+ dmxdev->may_do_mmap) {
+ if (dmxdev->may_do_mmap) {
+ 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;
@@ -380,7 +385,8 @@ static void dvb_dmxdev_filter_timer(struct dmxdev_filter *dmxdevfilter)
static int dvb_dmxdev_section_callback(const u8 *buffer1, size_t buffer1_len,
const u8 *buffer2, size_t buffer2_len,
- struct dmx_section_filter *filter)
+ struct dmx_section_filter *filter,
+ u32 *buffer_flags)
{
struct dmxdev_filter *dmxdevfilter = filter->priv;
int ret;
@@ -399,10 +405,12 @@ static int dvb_dmxdev_section_callback(const u8 *buffer1, size_t buffer1_len,
dprintk("section callback %*ph\n", 6, buffer1);
if (dvb_vb2_is_streaming(&dmxdevfilter->vb2_ctx)) {
ret = dvb_vb2_fill_buffer(&dmxdevfilter->vb2_ctx,
- buffer1, buffer1_len);
+ buffer1, buffer1_len,
+ buffer_flags);
if (ret == buffer1_len)
ret = dvb_vb2_fill_buffer(&dmxdevfilter->vb2_ctx,
- buffer2, buffer2_len);
+ buffer2, buffer2_len,
+ buffer_flags);
} else {
ret = dvb_dmxdev_buffer_write(&dmxdevfilter->buffer,
buffer1, buffer1_len);
@@ -422,11 +430,12 @@ static int dvb_dmxdev_section_callback(const u8 *buffer1, size_t buffer1_len,
static int dvb_dmxdev_ts_callback(const u8 *buffer1, size_t buffer1_len,
const u8 *buffer2, size_t buffer2_len,
- struct dmx_ts_feed *feed)
+ struct dmx_ts_feed *feed,
+ u32 *buffer_flags)
{
struct dmxdev_filter *dmxdevfilter = feed->priv;
struct dvb_ringbuffer *buffer;
-#ifdef DVB_MMAP
+#ifdef CONFIG_DVB_MMAP
struct dvb_vb2_ctx *ctx;
#endif
int ret;
@@ -440,20 +449,22 @@ static int dvb_dmxdev_ts_callback(const u8 *buffer1, size_t buffer1_len,
if (dmxdevfilter->params.pes.output == DMX_OUT_TAP ||
dmxdevfilter->params.pes.output == DMX_OUT_TSDEMUX_TAP) {
buffer = &dmxdevfilter->buffer;
-#ifdef DVB_MMAP
+#ifdef CONFIG_DVB_MMAP
ctx = &dmxdevfilter->vb2_ctx;
#endif
} else {
buffer = &dmxdevfilter->dev->dvr_buffer;
-#ifdef DVB_MMAP
+#ifdef CONFIG_DVB_MMAP
ctx = &dmxdevfilter->dev->dvr_vb2_ctx;
#endif
}
if (dvb_vb2_is_streaming(ctx)) {
- ret = dvb_vb2_fill_buffer(ctx, buffer1, buffer1_len);
+ ret = dvb_vb2_fill_buffer(ctx, buffer1, buffer1_len,
+ buffer_flags);
if (ret == buffer1_len)
- ret = dvb_vb2_fill_buffer(ctx, buffer2, buffer2_len);
+ ret = dvb_vb2_fill_buffer(ctx, buffer2, buffer2_len,
+ buffer_flags);
} else {
if (buffer->error) {
spin_unlock(&dmxdevfilter->dev->lock);
@@ -802,6 +813,12 @@ static int dvb_demux_open(struct inode *inode, struct file *file)
mutex_init(&dmxdevfilter->mutex);
file->private_data = dmxdevfilter;
+#ifdef CONFIG_DVB_MMAP
+ dmxdev->may_do_mmap = 1;
+#else
+ dmxdev->may_do_mmap = 0;
+#endif
+
dvb_ringbuffer_init(&dmxdevfilter->buffer, NULL, 8192);
dvb_vb2_init(&dmxdevfilter->vb2_ctx, "demux_filter",
file->f_flags & O_NONBLOCK);
@@ -1111,7 +1128,7 @@ static int dvb_demux_do_ioctl(struct file *file,
mutex_unlock(&dmxdevfilter->mutex);
break;
-#ifdef DVB_MMAP
+#ifdef CONFIG_DVB_MMAP
case DMX_REQBUFS:
if (mutex_lock_interruptible(&dmxdevfilter->mutex)) {
mutex_unlock(&dmxdev->mutex);
@@ -1160,7 +1177,7 @@ static int dvb_demux_do_ioctl(struct file *file,
break;
#endif
default:
- ret = -EINVAL;
+ ret = -ENOTTY;
break;
}
mutex_unlock(&dmxdev->mutex);
@@ -1199,13 +1216,16 @@ static __poll_t dvb_demux_poll(struct file *file, poll_table *wait)
return mask;
}
-#ifdef DVB_MMAP
+#ifdef CONFIG_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 (!dmxdev->may_do_mmap)
+ return -ENOTTY;
+
if (mutex_lock_interruptible(&dmxdev->mutex))
return -ERESTARTSYS;
@@ -1249,7 +1269,7 @@ static const struct file_operations dvb_demux_fops = {
.release = dvb_demux_release,
.poll = dvb_demux_poll,
.llseek = default_llseek,
-#ifdef DVB_MMAP
+#ifdef CONFIG_DVB_MMAP
.mmap = dvb_demux_mmap,
#endif
};
@@ -1280,7 +1300,7 @@ static int dvb_dvr_do_ioctl(struct file *file,
ret = dvb_dvr_set_buffer_size(dmxdev, arg);
break;
-#ifdef DVB_MMAP
+#ifdef CONFIG_DVB_MMAP
case DMX_REQBUFS:
ret = dvb_vb2_reqbufs(&dmxdev->dvr_vb2_ctx, parg);
break;
@@ -1304,7 +1324,7 @@ static int dvb_dvr_do_ioctl(struct file *file,
break;
#endif
default:
- ret = -EINVAL;
+ ret = -ENOTTY;
break;
}
mutex_unlock(&dmxdev->mutex);
@@ -1322,11 +1342,6 @@ 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__);
@@ -1337,11 +1352,8 @@ static __poll_t dvb_dvr_poll(struct file *file, poll_table *wait)
poll_wait(file, &dmxdev->dvr_buffer.queue, wait);
-#ifndef DVB_MMAP
- if ((file->f_flags & O_ACCMODE) == O_RDONLY)
- need_ringbuffer = true;
-#endif
- if (need_ringbuffer) {
+ if (((file->f_flags & O_ACCMODE) == O_RDONLY) ||
+ dmxdev->may_do_mmap) {
if (dmxdev->dvr_buffer.error)
mask |= (EPOLLIN | EPOLLRDNORM | EPOLLPRI | EPOLLERR);
@@ -1353,13 +1365,16 @@ static __poll_t dvb_dvr_poll(struct file *file, poll_table *wait)
return mask;
}
-#ifdef DVB_MMAP
+#ifdef CONFIG_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->may_do_mmap)
+ return -ENOTTY;
+
if (dmxdev->exit)
return -ENODEV;
@@ -1381,7 +1396,7 @@ static const struct file_operations dvb_dvr_fops = {
.release = dvb_dvr_release,
.poll = dvb_dvr_poll,
.llseek = default_llseek,
-#ifdef DVB_MMAP
+#ifdef CONFIG_DVB_MMAP
.mmap = dvb_dvr_mmap,
#endif
};