Skip to content

Commit

Permalink
media: dmxdev: Fix the logic that enables DMA mmap support
Browse files Browse the repository at this point in the history
Some conditions required for DVB mmap support to work are reversed.
Also, the logic is not too clear.

So, improve the logic, making it easier to be handled.

PS.: I'm pretty sure that I fixed it while testing, but, somehow,
the change got lost.

Signed-off-by: Mauro Carvalho Chehab <[email protected]>
  • Loading branch information
mchehab committed Feb 23, 2018
1 parent a145f64 commit 0b23498
Show file tree
Hide file tree
Showing 2 changed files with 44 additions and 33 deletions.
75 changes: 42 additions & 33 deletions drivers/media/dvb-core/dmxdev.c
Original file line number Diff line number Diff line change
Expand Up @@ -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 CONFIG_DVB_MMAP
bool need_ringbuffer = false;
#else
const bool need_ringbuffer = true;
#endif

dprintk("%s\n", __func__);

Expand All @@ -144,17 +140,31 @@ static int dvb_dvr_open(struct inode *inode, struct file *file)
return -ENODEV;
}

#ifndef CONFIG_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;
Expand All @@ -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--;
}

Expand Down Expand Up @@ -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 CONFIG_DVB_MMAP
bool need_ringbuffer = false;
#else
const bool need_ringbuffer = true;
#endif

mutex_lock(&dmxdev->mutex);

Expand All @@ -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 CONFIG_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;
Expand Down Expand Up @@ -802,6 +807,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);
Expand Down Expand Up @@ -1206,6 +1217,9 @@ static int dvb_demux_mmap(struct file *file, struct vm_area_struct *vma)
struct dmxdev *dmxdev = dmxdevfilter->dev;
int ret;

if (!dmxdev->may_do_mmap)
return -EOPNOTSUPP;

if (mutex_lock_interruptible(&dmxdev->mutex))
return -ERESTARTSYS;

Expand Down Expand Up @@ -1322,11 +1336,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 CONFIG_DVB_MMAP
bool need_ringbuffer = false;
#else
const bool need_ringbuffer = true;
#endif

dprintk("%s\n", __func__);

Expand All @@ -1337,11 +1346,8 @@ static __poll_t dvb_dvr_poll(struct file *file, poll_table *wait)

poll_wait(file, &dmxdev->dvr_buffer.queue, wait);

#ifndef CONFIG_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);

Expand All @@ -1360,6 +1366,9 @@ static int dvb_dvr_mmap(struct file *file, struct vm_area_struct *vma)
struct dmxdev *dmxdev = dvbdev->priv;
int ret;

if (!dmxdev->may_do_mmap)
return -EOPNOTSUPP;

if (dmxdev->exit)
return -ENODEV;

Expand Down
2 changes: 2 additions & 0 deletions include/media/dmxdev.h
Original file line number Diff line number Diff line change
Expand Up @@ -163,6 +163,7 @@ struct dmxdev_filter {
* @demux: pointer to &struct dmx_demux.
* @filternum: number of filters.
* @capabilities: demux capabilities as defined by &enum dmx_demux_caps.
* @may_do_mmap: flag used to indicate if the device may do mmap.
* @exit: flag to indicate that the demux is being released.
* @dvr_orig_fe: pointer to &struct dmx_frontend.
* @dvr_buffer: embedded &struct dvb_ringbuffer for DVB output.
Expand All @@ -180,6 +181,7 @@ struct dmxdev {
int filternum;
int capabilities;

unsigned int may_do_mmap:1;
unsigned int exit:1;
#define DMXDEV_CAP_DUPLEX 1
struct dmx_frontend *dvr_orig_fe;
Expand Down

0 comments on commit 0b23498

Please sign in to comment.