media: dvb-core: make DVB mmap API optional

This API is still experimental. Make it optional, allowing to
compile the code without it.

Signed-off-by: Mauro Carvalho Chehab <mchehab@s-opensource.com>
This commit is contained in:
Mauro Carvalho Chehab 2017-12-28 09:24:20 -05:00
Родитель 651d666605
Коммит 4021053ed5
4 изменённых файлов: 98 добавлений и 13 удалений

Просмотреть файл

@ -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)

Просмотреть файл

@ -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

Просмотреть файл

@ -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__);
@ -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) {
@ -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);
@ -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);
@ -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);
@ -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);
@ -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)) {
@ -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);
@ -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;
@ -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;
@ -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)
{
@ -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 = {
@ -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;
@ -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;
@ -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__);
@ -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);
@ -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;
@ -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,
@ -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 = {

Просмотреть файл

@ -54,13 +54,37 @@ 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);
@ -68,7 +92,5 @@ 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 */