diff options
-rw-r--r-- | drivers/media/Kconfig | 12 | ||||
-rw-r--r-- | drivers/media/dvb-core/Makefile | 3 | ||||
-rw-r--r-- | drivers/media/dvb-core/dmxdev.c | 66 | ||||
-rw-r--r-- | drivers/media/dvb-core/dvb_vb2.h | 30 |
4 files changed, 98 insertions, 13 deletions
diff --git a/drivers/media/Kconfig b/drivers/media/Kconfig index edfe99b22d56..3f69b948d102 100644 --- a/drivers/media/Kconfig +++ b/drivers/media/Kconfig @@ -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) diff --git a/drivers/media/dvb-core/Makefile b/drivers/media/dvb-core/Makefile index bbc65dfa0a8e..3756ccf83384 100644 --- a/drivers/media/dvb-core/Makefile +++ b/drivers/media/dvb-core/Makefile @@ -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 diff --git a/drivers/media/dvb-core/dmxdev.c b/drivers/media/dvb-core/dmxdev.c index 0ddf58adb172..1308c11f0e5b 100644 --- a/drivers/media/dvb-core/dmxdev.c +++ b/drivers/media/dvb-core/dmxdev.c @@ -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 = { diff --git a/drivers/media/dvb-core/dvb_vb2.h b/drivers/media/dvb-core/dvb_vb2.h index aa67f8081127..7a529844c5e1 100644 --- a/drivers/media/dvb-core/dvb_vb2.h +++ b/drivers/media/dvb-core/dvb_vb2.h @@ -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 */ |