Commit 4021053e authored by Mauro Carvalho Chehab's avatar Mauro Carvalho Chehab

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: default avatarMauro Carvalho Chehab <mchehab@s-opensource.com>
parent 651d6666
...@@ -144,6 +144,18 @@ config DVB_CORE ...@@ -144,6 +144,18 @@ config DVB_CORE
default y default y
select CRC32 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 config DVB_NET
bool "DVB Network Support" bool "DVB Network Support"
default (NET && INET) default (NET && INET)
......
...@@ -4,9 +4,10 @@ ...@@ -4,9 +4,10 @@
# #
dvb-net-$(CONFIG_DVB_NET) := dvb_net.o 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-core-objs := dvbdev.o dmxdev.o dvb_demux.o \
dvb_ca_en50221.o dvb_frontend.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 obj-$(CONFIG_DVB_CORE) += dvb-core.o
...@@ -128,6 +128,11 @@ static int dvb_dvr_open(struct inode *inode, struct file *file) ...@@ -128,6 +128,11 @@ static int dvb_dvr_open(struct inode *inode, struct file *file)
struct dvb_device *dvbdev = file->private_data; struct dvb_device *dvbdev = file->private_data;
struct dmxdev *dmxdev = dvbdev->priv; struct dmxdev *dmxdev = dvbdev->priv;
struct dmx_frontend *front; struct dmx_frontend *front;
#ifndef DVB_MMAP
bool need_ringbuffer = false;
#else
const bool need_ringbuffer = true;
#endif
dprintk("%s\n", __func__); dprintk("%s\n", __func__);
...@@ -139,8 +144,19 @@ static int dvb_dvr_open(struct inode *inode, struct file *file) ...@@ -139,8 +144,19 @@ static int dvb_dvr_open(struct inode *inode, struct file *file)
return -ENODEV; return -ENODEV;
} }
if (((file->f_flags & O_ACCMODE) == O_RDONLY) || #ifndef DVB_MMAP
((file->f_flags & O_ACCMODE) == O_RDWR)) { 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; void *mem;
if (!dvbdev->readers) { if (!dvbdev->readers) {
...@@ -184,6 +200,11 @@ static int dvb_dvr_release(struct inode *inode, struct file *file) ...@@ -184,6 +200,11 @@ static int dvb_dvr_release(struct inode *inode, struct file *file)
{ {
struct dvb_device *dvbdev = file->private_data; struct dvb_device *dvbdev = file->private_data;
struct dmxdev *dmxdev = dvbdev->priv; struct dmxdev *dmxdev = dvbdev->priv;
#ifndef DVB_MMAP
bool need_ringbuffer = false;
#else
const bool need_ringbuffer = true;
#endif
mutex_lock(&dmxdev->mutex); mutex_lock(&dmxdev->mutex);
...@@ -192,8 +213,12 @@ static int dvb_dvr_release(struct inode *inode, struct file *file) ...@@ -192,8 +213,12 @@ static int dvb_dvr_release(struct inode *inode, struct file *file)
dmxdev->demux->connect_frontend(dmxdev->demux, dmxdev->demux->connect_frontend(dmxdev->demux,
dmxdev->dvr_orig_fe); dmxdev->dvr_orig_fe);
} }
if (((file->f_flags & O_ACCMODE) == O_RDONLY) || #ifndef DVB_MMAP
((file->f_flags & O_ACCMODE) == O_RDWR)) { if ((file->f_flags & O_ACCMODE) == O_RDONLY)
need_ringbuffer = true;
#endif
if (need_ringbuffer) {
if (dvb_vb2_is_streaming(&dmxdev->dvr_vb2_ctx)) if (dvb_vb2_is_streaming(&dmxdev->dvr_vb2_ctx))
dvb_vb2_stream_off(&dmxdev->dvr_vb2_ctx); dvb_vb2_stream_off(&dmxdev->dvr_vb2_ctx);
dvb_vb2_release(&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, ...@@ -359,6 +384,7 @@ static int dvb_dmxdev_section_callback(const u8 *buffer1, size_t buffer1_len,
{ {
struct dmxdev_filter *dmxdevfilter = filter->priv; struct dmxdev_filter *dmxdevfilter = filter->priv;
int ret; int ret;
if (!dvb_vb2_is_streaming(&dmxdevfilter->vb2_ctx) && if (!dvb_vb2_is_streaming(&dmxdevfilter->vb2_ctx) &&
dmxdevfilter->buffer.error) { dmxdevfilter->buffer.error) {
wake_up(&dmxdevfilter->buffer.queue); wake_up(&dmxdevfilter->buffer.queue);
...@@ -400,7 +426,9 @@ static int dvb_dmxdev_ts_callback(const u8 *buffer1, size_t buffer1_len, ...@@ -400,7 +426,9 @@ static int dvb_dmxdev_ts_callback(const u8 *buffer1, size_t buffer1_len,
{ {
struct dmxdev_filter *dmxdevfilter = feed->priv; struct dmxdev_filter *dmxdevfilter = feed->priv;
struct dvb_ringbuffer *buffer; struct dvb_ringbuffer *buffer;
#ifdef DVB_MMAP
struct dvb_vb2_ctx *ctx; struct dvb_vb2_ctx *ctx;
#endif
int ret; int ret;
spin_lock(&dmxdevfilter->dev->lock); spin_lock(&dmxdevfilter->dev->lock);
...@@ -412,10 +440,14 @@ static int dvb_dmxdev_ts_callback(const u8 *buffer1, size_t buffer1_len, ...@@ -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 || if (dmxdevfilter->params.pes.output == DMX_OUT_TAP ||
dmxdevfilter->params.pes.output == DMX_OUT_TSDEMUX_TAP) { dmxdevfilter->params.pes.output == DMX_OUT_TSDEMUX_TAP) {
buffer = &dmxdevfilter->buffer; buffer = &dmxdevfilter->buffer;
#ifdef DVB_MMAP
ctx = &dmxdevfilter->vb2_ctx; ctx = &dmxdevfilter->vb2_ctx;
#endif
} else { } else {
buffer = &dmxdevfilter->dev->dvr_buffer; buffer = &dmxdevfilter->dev->dvr_buffer;
#ifdef DVB_MMAP
ctx = &dmxdevfilter->dev->dvr_vb2_ctx; ctx = &dmxdevfilter->dev->dvr_vb2_ctx;
#endif
} }
if (dvb_vb2_is_streaming(ctx)) { if (dvb_vb2_is_streaming(ctx)) {
...@@ -1079,6 +1111,7 @@ static int dvb_demux_do_ioctl(struct file *file, ...@@ -1079,6 +1111,7 @@ static int dvb_demux_do_ioctl(struct file *file,
mutex_unlock(&dmxdevfilter->mutex); mutex_unlock(&dmxdevfilter->mutex);
break; break;
#ifdef DVB_MMAP
case DMX_REQBUFS: case DMX_REQBUFS:
if (mutex_lock_interruptible(&dmxdevfilter->mutex)) { if (mutex_lock_interruptible(&dmxdevfilter->mutex)) {
mutex_unlock(&dmxdev->mutex); mutex_unlock(&dmxdev->mutex);
...@@ -1125,7 +1158,7 @@ static int dvb_demux_do_ioctl(struct file *file, ...@@ -1125,7 +1158,7 @@ static int dvb_demux_do_ioctl(struct file *file,
ret = dvb_vb2_dqbuf(&dmxdevfilter->vb2_ctx, parg); ret = dvb_vb2_dqbuf(&dmxdevfilter->vb2_ctx, parg);
mutex_unlock(&dmxdevfilter->mutex); mutex_unlock(&dmxdevfilter->mutex);
break; break;
#endif
default: default:
ret = -EINVAL; ret = -EINVAL;
break; break;
...@@ -1166,6 +1199,7 @@ static unsigned int dvb_demux_poll(struct file *file, poll_table *wait) ...@@ -1166,6 +1199,7 @@ static unsigned int dvb_demux_poll(struct file *file, poll_table *wait)
return mask; return mask;
} }
#ifdef DVB_MMAP
static int dvb_demux_mmap(struct file *file, struct vm_area_struct *vma) static int dvb_demux_mmap(struct file *file, struct vm_area_struct *vma)
{ {
struct dmxdev_filter *dmxdevfilter = file->private_data; struct dmxdev_filter *dmxdevfilter = file->private_data;
...@@ -1186,6 +1220,7 @@ static int dvb_demux_mmap(struct file *file, struct vm_area_struct *vma) ...@@ -1186,6 +1220,7 @@ static int dvb_demux_mmap(struct file *file, struct vm_area_struct *vma)
return ret; return ret;
} }
#endif
static int dvb_demux_release(struct inode *inode, struct file *file) static int dvb_demux_release(struct inode *inode, struct file *file)
{ {
...@@ -1214,7 +1249,9 @@ static const struct file_operations dvb_demux_fops = { ...@@ -1214,7 +1249,9 @@ static const struct file_operations dvb_demux_fops = {
.release = dvb_demux_release, .release = dvb_demux_release,
.poll = dvb_demux_poll, .poll = dvb_demux_poll,
.llseek = default_llseek, .llseek = default_llseek,
#ifdef DVB_MMAP
.mmap = dvb_demux_mmap, .mmap = dvb_demux_mmap,
#endif
}; };
static const struct dvb_device dvbdev_demux = { static const struct dvb_device dvbdev_demux = {
...@@ -1243,6 +1280,7 @@ static int dvb_dvr_do_ioctl(struct file *file, ...@@ -1243,6 +1280,7 @@ static int dvb_dvr_do_ioctl(struct file *file,
ret = dvb_dvr_set_buffer_size(dmxdev, arg); ret = dvb_dvr_set_buffer_size(dmxdev, arg);
break; break;
#ifdef DVB_MMAP
case DMX_REQBUFS: case DMX_REQBUFS:
ret = dvb_vb2_reqbufs(&dmxdev->dvr_vb2_ctx, parg); ret = dvb_vb2_reqbufs(&dmxdev->dvr_vb2_ctx, parg);
break; break;
...@@ -1264,7 +1302,7 @@ static int dvb_dvr_do_ioctl(struct file *file, ...@@ -1264,7 +1302,7 @@ static int dvb_dvr_do_ioctl(struct file *file,
case DMX_DQBUF: case DMX_DQBUF:
ret = dvb_vb2_dqbuf(&dmxdev->dvr_vb2_ctx, parg); ret = dvb_vb2_dqbuf(&dmxdev->dvr_vb2_ctx, parg);
break; break;
#endif
default: default:
ret = -EINVAL; ret = -EINVAL;
break; break;
...@@ -1284,6 +1322,11 @@ static unsigned int dvb_dvr_poll(struct file *file, poll_table *wait) ...@@ -1284,6 +1322,11 @@ static unsigned int dvb_dvr_poll(struct file *file, poll_table *wait)
struct dvb_device *dvbdev = file->private_data; struct dvb_device *dvbdev = file->private_data;
struct dmxdev *dmxdev = dvbdev->priv; struct dmxdev *dmxdev = dvbdev->priv;
unsigned int mask = 0; unsigned int mask = 0;
#ifndef DVB_MMAP
bool need_ringbuffer = false;
#else
const bool need_ringbuffer = true;
#endif
dprintk("%s\n", __func__); dprintk("%s\n", __func__);
...@@ -1294,8 +1337,11 @@ static unsigned int dvb_dvr_poll(struct file *file, poll_table *wait) ...@@ -1294,8 +1337,11 @@ static unsigned int dvb_dvr_poll(struct file *file, poll_table *wait)
poll_wait(file, &dmxdev->dvr_buffer.queue, wait); poll_wait(file, &dmxdev->dvr_buffer.queue, wait);
if (((file->f_flags & O_ACCMODE) == O_RDONLY) || #ifndef DVB_MMAP
((file->f_flags & O_ACCMODE) == O_RDWR)) { if ((file->f_flags & O_ACCMODE) == O_RDONLY)
need_ringbuffer = true;
#endif
if (need_ringbuffer) {
if (dmxdev->dvr_buffer.error) if (dmxdev->dvr_buffer.error)
mask |= (POLLIN | POLLRDNORM | POLLPRI | POLLERR); mask |= (POLLIN | POLLRDNORM | POLLPRI | POLLERR);
...@@ -1307,6 +1353,7 @@ static unsigned int dvb_dvr_poll(struct file *file, poll_table *wait) ...@@ -1307,6 +1353,7 @@ static unsigned int dvb_dvr_poll(struct file *file, poll_table *wait)
return mask; return mask;
} }
#ifdef DVB_MMAP
static int dvb_dvr_mmap(struct file *file, struct vm_area_struct *vma) static int dvb_dvr_mmap(struct file *file, struct vm_area_struct *vma)
{ {
struct dvb_device *dvbdev = file->private_data; struct dvb_device *dvbdev = file->private_data;
...@@ -1323,6 +1370,7 @@ static int dvb_dvr_mmap(struct file *file, struct vm_area_struct *vma) ...@@ -1323,6 +1370,7 @@ static int dvb_dvr_mmap(struct file *file, struct vm_area_struct *vma)
mutex_unlock(&dmxdev->mutex); mutex_unlock(&dmxdev->mutex);
return ret; return ret;
} }
#endif
static const struct file_operations dvb_dvr_fops = { static const struct file_operations dvb_dvr_fops = {
.owner = THIS_MODULE, .owner = THIS_MODULE,
...@@ -1333,7 +1381,9 @@ static const struct file_operations dvb_dvr_fops = { ...@@ -1333,7 +1381,9 @@ static const struct file_operations dvb_dvr_fops = {
.release = dvb_dvr_release, .release = dvb_dvr_release,
.poll = dvb_dvr_poll, .poll = dvb_dvr_poll,
.llseek = default_llseek, .llseek = default_llseek,
#ifdef DVB_MMAP
.mmap = dvb_dvr_mmap, .mmap = dvb_dvr_mmap,
#endif
}; };
static const struct dvb_device dvbdev_dvr = { static const struct dvb_device dvbdev_dvr = {
......
...@@ -54,13 +54,37 @@ struct dvb_vb2_ctx { ...@@ -54,13 +54,37 @@ struct dvb_vb2_ctx {
char name[DVB_VB2_NAME_MAX + 1]; 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_on(struct dvb_vb2_ctx *ctx);
int dvb_vb2_stream_off(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_is_streaming(struct dvb_vb2_ctx *ctx);
int dvb_vb2_fill_buffer(struct dvb_vb2_ctx *ctx, int dvb_vb2_fill_buffer(struct dvb_vb2_ctx *ctx,
const unsigned char *src, int len); 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_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_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); ...@@ -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_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_dqbuf(struct dvb_vb2_ctx *ctx, struct dmx_buffer *b);
int dvb_vb2_mmap(struct dvb_vb2_ctx *ctx, struct vm_area_struct *vma); 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 */ #endif /* _DVB_VB2_H */
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment