Skip to content

Commit

Permalink
media: dvb-core: make DVB mmap API optional
Browse files Browse the repository at this point in the history
This API is still experimental. Make it optional, allowing to
compile the code without it.

Signed-off-by: Mauro Carvalho Chehab <[email protected]>
  • Loading branch information
mchehab committed Dec 28, 2017
1 parent 651d666 commit 4021053
Show file tree
Hide file tree
Showing 4 changed files with 98 additions and 13 deletions.
12 changes: 12 additions & 0 deletions drivers/media/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,18 @@ config DVB_CORE
default y
select CRC32

config DVB_MMAP
bool "Enable DVB memory-mapped API (EXPERIMENTAL)"
depends on DVB_CORE
default n
help
This option enables DVB experimental memory-mapped API, with
reduces the number of context switches to read DVB buffers, as
the buffers can use mmap() syscalls.

Support for it is experimental. Use with care. If unsure,
say N.

config DVB_NET
bool "DVB Network Support"
default (NET && INET)
Expand Down
3 changes: 2 additions & 1 deletion drivers/media/dvb-core/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,10 @@
#

dvb-net-$(CONFIG_DVB_NET) := dvb_net.o
dvb-vb2-$(CONFIG_DVB_MMSP) := dvb_vb2.o

dvb-core-objs := dvbdev.o dmxdev.o dvb_demux.o \
dvb_ca_en50221.o dvb_frontend.o \
$(dvb-net-y) dvb_ringbuffer.o dvb_vb2.o dvb_math.o
$(dvb-net-y) dvb_ringbuffer.o $(dvb-vb2-y) dvb_math.o

obj-$(CONFIG_DVB_CORE) += dvb-core.o
66 changes: 58 additions & 8 deletions drivers/media/dvb-core/dmxdev.c
Original file line number Diff line number Diff line change
Expand Up @@ -128,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__);

Expand All @@ -139,8 +144,19 @@ static int dvb_dvr_open(struct inode *inode, struct file *file)
return -ENODEV;
}

if (((file->f_flags & O_ACCMODE) == O_RDONLY) ||
((file->f_flags & O_ACCMODE) == O_RDWR)) {
#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 (need_ringbuffer) {
void *mem;

if (!dvbdev->readers) {
Expand Down Expand Up @@ -184,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);

Expand All @@ -192,8 +213,12 @@ 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) ||
((file->f_flags & O_ACCMODE) == O_RDWR)) {
#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);
Expand Down Expand Up @@ -359,6 +384,7 @@ static int dvb_dmxdev_section_callback(const u8 *buffer1, size_t buffer1_len,
{
struct dmxdev_filter *dmxdevfilter = filter->priv;
int ret;

if (!dvb_vb2_is_streaming(&dmxdevfilter->vb2_ctx) &&
dmxdevfilter->buffer.error) {
wake_up(&dmxdevfilter->buffer.queue);
Expand Down Expand Up @@ -400,7 +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);
Expand All @@ -412,10 +440,14 @@ 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
ctx = &dmxdevfilter->vb2_ctx;
#endif
} else {
buffer = &dmxdevfilter->dev->dvr_buffer;
#ifdef DVB_MMAP
ctx = &dmxdevfilter->dev->dvr_vb2_ctx;
#endif
}

if (dvb_vb2_is_streaming(ctx)) {
Expand Down Expand Up @@ -1079,6 +1111,7 @@ 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);
Expand Down Expand Up @@ -1125,7 +1158,7 @@ static int dvb_demux_do_ioctl(struct file *file,
ret = dvb_vb2_dqbuf(&dmxdevfilter->vb2_ctx, parg);
mutex_unlock(&dmxdevfilter->mutex);
break;

#endif
default:
ret = -EINVAL;
break;
Expand Down Expand Up @@ -1166,6 +1199,7 @@ static unsigned int dvb_demux_poll(struct file *file, poll_table *wait)
return mask;
}

#ifdef DVB_MMAP
static int dvb_demux_mmap(struct file *file, struct vm_area_struct *vma)
{
struct dmxdev_filter *dmxdevfilter = file->private_data;
Expand All @@ -1186,6 +1220,7 @@ static int dvb_demux_mmap(struct file *file, struct vm_area_struct *vma)

return ret;
}
#endif

static int dvb_demux_release(struct inode *inode, struct file *file)
{
Expand Down Expand Up @@ -1214,7 +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 = {
Expand Down Expand Up @@ -1243,6 +1280,7 @@ 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;
Expand All @@ -1264,7 +1302,7 @@ static int dvb_dvr_do_ioctl(struct file *file,
case DMX_DQBUF:
ret = dvb_vb2_dqbuf(&dmxdev->dvr_vb2_ctx, parg);
break;

#endif
default:
ret = -EINVAL;
break;
Expand All @@ -1284,6 +1322,11 @@ static unsigned int dvb_dvr_poll(struct file *file, poll_table *wait)
struct dvb_device *dvbdev = file->private_data;
struct dmxdev *dmxdev = dvbdev->priv;
unsigned int mask = 0;
#ifndef DVB_MMAP
bool need_ringbuffer = false;
#else
const bool need_ringbuffer = true;
#endif

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

Expand All @@ -1294,8 +1337,11 @@ static unsigned int dvb_dvr_poll(struct file *file, poll_table *wait)

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

if (((file->f_flags & O_ACCMODE) == O_RDONLY) ||
((file->f_flags & O_ACCMODE) == O_RDWR)) {
#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);

Expand All @@ -1307,6 +1353,7 @@ static unsigned int dvb_dvr_poll(struct file *file, poll_table *wait)
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;
Expand All @@ -1323,6 +1370,7 @@ static int dvb_dvr_mmap(struct file *file, struct vm_area_struct *vma)
mutex_unlock(&dmxdev->mutex);
return ret;
}
#endif

static const struct file_operations dvb_dvr_fops = {
.owner = THIS_MODULE,
Expand All @@ -1333,7 +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 = {
Expand Down
30 changes: 26 additions & 4 deletions drivers/media/dvb-core/dvb_vb2.h
Original file line number Diff line number Diff line change
Expand Up @@ -54,21 +54,43 @@ struct dvb_vb2_ctx {
char name[DVB_VB2_NAME_MAX + 1];
};

int dvb_vb2_init(struct dvb_vb2_ctx *ctx, const char *name, int non_blocking);
int dvb_vb2_release(struct dvb_vb2_ctx *ctx);
int dvb_vb2_stream_on(struct dvb_vb2_ctx *ctx);
int dvb_vb2_stream_off(struct dvb_vb2_ctx *ctx);
#ifndef DVB_MMAP
static inline int dvb_vb2_init(struct dvb_vb2_ctx *ctx,
const char *name, int non_blocking)
{
return 0;
};
static inline int dvb_vb2_release(struct dvb_vb2_ctx *ctx)
{
return 0;
};
#define dvb_vb2_is_streaming(ctx) (0)
#define dvb_vb2_fill_buffer(ctx, file, wait) (0)

static inline unsigned int dvb_vb2_poll(struct dvb_vb2_ctx *ctx,
struct file *file,
poll_table *wait)
{
return 0;
}
#else
int dvb_vb2_init(struct dvb_vb2_ctx *ctx, const char *name, int non_blocking);
int dvb_vb2_release(struct dvb_vb2_ctx *ctx);
int dvb_vb2_is_streaming(struct dvb_vb2_ctx *ctx);
int dvb_vb2_fill_buffer(struct dvb_vb2_ctx *ctx,
const unsigned char *src, int len);
unsigned int dvb_vb2_poll(struct dvb_vb2_ctx *ctx, struct file *file,
poll_table *wait);
#endif


int dvb_vb2_reqbufs(struct dvb_vb2_ctx *ctx, struct dmx_requestbuffers *req);
int dvb_vb2_querybuf(struct dvb_vb2_ctx *ctx, struct dmx_buffer *b);
int dvb_vb2_expbuf(struct dvb_vb2_ctx *ctx, struct dmx_exportbuffer *exp);
int dvb_vb2_qbuf(struct dvb_vb2_ctx *ctx, struct dmx_buffer *b);
int dvb_vb2_dqbuf(struct dvb_vb2_ctx *ctx, struct dmx_buffer *b);
int dvb_vb2_mmap(struct dvb_vb2_ctx *ctx, struct vm_area_struct *vma);
unsigned int dvb_vb2_poll(struct dvb_vb2_ctx *ctx, struct file *file,
poll_table *wait);

#endif /* _DVB_VB2_H */

0 comments on commit 4021053

Please sign in to comment.