Commit 34731df2 authored by Andreas Oberritter's avatar Andreas Oberritter Committed by Linus Torvalds

V4L/DVB (3501): Dmxdev: use dvb_ringbuffer

Use dvb_ringbuffer instead of an own buffer implementation in
dmxdev.[ch].
Signed-off-by: default avatarAndreas Oberritter <obi@linuxtv.org>
Signed-off-by: default avatarMauro Carvalho Chehab <mchehab@infradead.org>
parent 4304954e
...@@ -40,110 +40,72 @@ MODULE_PARM_DESC(debug, "Turn on/off debugging (default:off)."); ...@@ -40,110 +40,72 @@ MODULE_PARM_DESC(debug, "Turn on/off debugging (default:off).");
#define dprintk if (debug) printk #define dprintk if (debug) printk
static inline void dvb_dmxdev_buffer_init(struct dmxdev_buffer *buffer) static int dvb_dmxdev_buffer_write(struct dvb_ringbuffer *buf,
const u8 *src, size_t len)
{ {
buffer->data = NULL; ssize_t free;
buffer->size = 8192;
buffer->pread = 0;
buffer->pwrite = 0;
buffer->error = 0;
init_waitqueue_head(&buffer->queue);
}
static inline int dvb_dmxdev_buffer_write(struct dmxdev_buffer *buf,
const u8 *src, int len)
{
int split;
int free;
int todo;
if (!len) if (!len)
return 0; return 0;
if (!buf->data) if (!buf->data)
return 0; return 0;
free = buf->pread - buf->pwrite; free = dvb_ringbuffer_free(buf);
split = 0; if (len > free) {
if (free <= 0) {
free += buf->size;
split = buf->size - buf->pwrite;
}
if (len >= free) {
dprintk("dmxdev: buffer overflow\n"); dprintk("dmxdev: buffer overflow\n");
return -1; return -EOVERFLOW;
}
if (split >= len)
split = 0;
todo = len;
if (split) {
memcpy(buf->data + buf->pwrite, src, split);
todo -= split;
buf->pwrite = 0;
} }
memcpy(buf->data + buf->pwrite, src + split, todo);
buf->pwrite = (buf->pwrite + todo) % buf->size; return dvb_ringbuffer_write(buf, src, len);
return len;
} }
static ssize_t dvb_dmxdev_buffer_read(struct dmxdev_buffer *src, static ssize_t dvb_dmxdev_buffer_read(struct dvb_ringbuffer *src,
int non_blocking, char __user *buf, int non_blocking, char __user *buf,
size_t count, loff_t *ppos) size_t count, loff_t *ppos)
{ {
unsigned long todo = count; size_t todo;
int split, avail, error; ssize_t avail;
ssize_t ret = 0;
if (!src->data) if (!src->data)
return 0; return 0;
if ((error = src->error)) { if (src->error) {
src->pwrite = src->pread; ret = src->error;
src->error = 0; dvb_ringbuffer_flush(src);
return error; return ret;
} }
if (non_blocking && (src->pwrite == src->pread)) for (todo = count; todo > 0; todo -= ret) {
return -EWOULDBLOCK; if (non_blocking && dvb_ringbuffer_empty(src)) {
ret = -EWOULDBLOCK;
while (todo > 0) { break;
if (non_blocking && (src->pwrite == src->pread)) }
return (count - todo) ? (count - todo) : -EWOULDBLOCK;
if (wait_event_interruptible(src->queue, ret = wait_event_interruptible(src->queue,
(src->pread != src->pwrite) || !dvb_ringbuffer_empty(src) ||
(src->error)) < 0) (src->error != 0));
return count - todo; if (ret < 0)
break;
if ((error = src->error)) { if (src->error) {
src->pwrite = src->pread; ret = src->error;
src->error = 0; dvb_ringbuffer_flush(src);
return error; break;
} }
split = src->size; avail = dvb_ringbuffer_avail(src);
avail = src->pwrite - src->pread;
if (avail < 0) {
avail += src->size;
split = src->size - src->pread;
}
if (avail > todo) if (avail > todo)
avail = todo; avail = todo;
if (split < avail) {
if (copy_to_user(buf, src->data + src->pread, split)) ret = dvb_ringbuffer_read(src, buf, avail, 1);
return -EFAULT; if (ret < 0)
buf += split; break;
src->pread = 0;
todo -= split; buf += ret;
avail -= split;
}
if (avail) {
if (copy_to_user(buf, src->data + src->pread, avail))
return -EFAULT;
src->pread = (src->pread + avail) % src->size;
todo -= avail;
buf += avail;
}
} }
return count;
return (count - todo) ? (count - todo) : ret;
} }
static struct dmx_frontend *get_fe(struct dmx_demux *demux, int type) static struct dmx_frontend *get_fe(struct dmx_demux *demux, int type)
...@@ -179,13 +141,12 @@ static int dvb_dvr_open(struct inode *inode, struct file *file) ...@@ -179,13 +141,12 @@ static int dvb_dvr_open(struct inode *inode, struct file *file)
} }
if ((file->f_flags & O_ACCMODE) == O_RDONLY) { if ((file->f_flags & O_ACCMODE) == O_RDONLY) {
dvb_dmxdev_buffer_init(&dmxdev->dvr_buffer); void *mem = vmalloc(DVR_BUFFER_SIZE);
dmxdev->dvr_buffer.size = DVR_BUFFER_SIZE; if (!mem) {
dmxdev->dvr_buffer.data = vmalloc(DVR_BUFFER_SIZE);
if (!dmxdev->dvr_buffer.data) {
mutex_unlock(&dmxdev->mutex); mutex_unlock(&dmxdev->mutex);
return -ENOMEM; return -ENOMEM;
} }
dvb_ringbuffer_init(&dmxdev->dvr_buffer, mem, DVR_BUFFER_SIZE);
} }
if ((file->f_flags & O_ACCMODE) == O_WRONLY) { if ((file->f_flags & O_ACCMODE) == O_WRONLY) {
...@@ -280,7 +241,7 @@ static inline void dvb_dmxdev_filter_state_set(struct dmxdev_filter ...@@ -280,7 +241,7 @@ static inline void dvb_dmxdev_filter_state_set(struct dmxdev_filter
static int dvb_dmxdev_set_buffer_size(struct dmxdev_filter *dmxdevfilter, static int dvb_dmxdev_set_buffer_size(struct dmxdev_filter *dmxdevfilter,
unsigned long size) unsigned long size)
{ {
struct dmxdev_buffer *buf = &dmxdevfilter->buffer; struct dvb_ringbuffer *buf = &dmxdevfilter->buffer;
void *mem; void *mem;
if (buf->size == size) if (buf->size == size)
...@@ -291,7 +252,7 @@ static int dvb_dmxdev_set_buffer_size(struct dmxdev_filter *dmxdevfilter, ...@@ -291,7 +252,7 @@ static int dvb_dmxdev_set_buffer_size(struct dmxdev_filter *dmxdevfilter,
mem = buf->data; mem = buf->data;
buf->data = NULL; buf->data = NULL;
buf->size = size; buf->size = size;
buf->pwrite = buf->pread = 0; dvb_ringbuffer_flush(buf);
spin_unlock_irq(&dmxdevfilter->dev->lock); spin_unlock_irq(&dmxdevfilter->dev->lock);
vfree(mem); vfree(mem);
...@@ -359,8 +320,8 @@ static int dvb_dmxdev_section_callback(const u8 *buffer1, size_t buffer1_len, ...@@ -359,8 +320,8 @@ static int dvb_dmxdev_section_callback(const u8 *buffer1, size_t buffer1_len,
buffer2_len); buffer2_len);
} }
if (ret < 0) { if (ret < 0) {
dmxdevfilter->buffer.pwrite = dmxdevfilter->buffer.pread; dvb_ringbuffer_flush(&dmxdevfilter->buffer);
dmxdevfilter->buffer.error = -EOVERFLOW; dmxdevfilter->buffer.error = ret;
} }
if (dmxdevfilter->params.sec.flags & DMX_ONESHOT) if (dmxdevfilter->params.sec.flags & DMX_ONESHOT)
dmxdevfilter->state = DMXDEV_STATE_DONE; dmxdevfilter->state = DMXDEV_STATE_DONE;
...@@ -375,7 +336,7 @@ static int dvb_dmxdev_ts_callback(const u8 *buffer1, size_t buffer1_len, ...@@ -375,7 +336,7 @@ static int dvb_dmxdev_ts_callback(const u8 *buffer1, size_t buffer1_len,
enum dmx_success success) enum dmx_success success)
{ {
struct dmxdev_filter *dmxdevfilter = feed->priv; struct dmxdev_filter *dmxdevfilter = feed->priv;
struct dmxdev_buffer *buffer; struct dvb_ringbuffer *buffer;
int ret; int ret;
spin_lock(&dmxdevfilter->dev->lock); spin_lock(&dmxdevfilter->dev->lock);
...@@ -397,8 +358,8 @@ static int dvb_dmxdev_ts_callback(const u8 *buffer1, size_t buffer1_len, ...@@ -397,8 +358,8 @@ static int dvb_dmxdev_ts_callback(const u8 *buffer1, size_t buffer1_len,
if (ret == buffer1_len) if (ret == buffer1_len)
ret = dvb_dmxdev_buffer_write(buffer, buffer2, buffer2_len); ret = dvb_dmxdev_buffer_write(buffer, buffer2, buffer2_len);
if (ret < 0) { if (ret < 0) {
buffer->pwrite = buffer->pread; dvb_ringbuffer_flush(buffer);
buffer->error = -EOVERFLOW; buffer->error = ret;
} }
spin_unlock(&dmxdevfilter->dev->lock); spin_unlock(&dmxdevfilter->dev->lock);
wake_up(&buffer->queue); wake_up(&buffer->queue);
...@@ -494,7 +455,8 @@ static int dvb_dmxdev_filter_stop(struct dmxdev_filter *dmxdevfilter) ...@@ -494,7 +455,8 @@ static int dvb_dmxdev_filter_stop(struct dmxdev_filter *dmxdevfilter)
return 0; return 0;
return -EINVAL; return -EINVAL;
} }
dmxdevfilter->buffer.pwrite = dmxdevfilter->buffer.pread = 0;
dvb_ringbuffer_flush(&dmxdevfilter->buffer);
return 0; return 0;
} }
...@@ -520,16 +482,16 @@ static int dvb_dmxdev_filter_start(struct dmxdev_filter *filter) ...@@ -520,16 +482,16 @@ static int dvb_dmxdev_filter_start(struct dmxdev_filter *filter)
if (filter->state >= DMXDEV_STATE_GO) if (filter->state >= DMXDEV_STATE_GO)
dvb_dmxdev_filter_stop(filter); dvb_dmxdev_filter_stop(filter);
if (!(mem = filter->buffer.data)) { if (!filter->buffer.data) {
mem = vmalloc(filter->buffer.size); mem = vmalloc(filter->buffer.size);
if (!mem)
return -ENOMEM;
spin_lock_irq(&filter->dev->lock); spin_lock_irq(&filter->dev->lock);
filter->buffer.data = mem; filter->buffer.data = mem;
spin_unlock_irq(&filter->dev->lock); spin_unlock_irq(&filter->dev->lock);
if (!filter->buffer.data)
return -ENOMEM;
} }
filter->buffer.pwrite = filter->buffer.pread = 0; dvb_ringbuffer_flush(&filter->buffer);
switch (filter->type) { switch (filter->type) {
case DMXDEV_TYPE_SEC: case DMXDEV_TYPE_SEC:
...@@ -692,7 +654,7 @@ static int dvb_demux_open(struct inode *inode, struct file *file) ...@@ -692,7 +654,7 @@ static int dvb_demux_open(struct inode *inode, struct file *file)
mutex_init(&dmxdevfilter->mutex); mutex_init(&dmxdevfilter->mutex);
file->private_data = dmxdevfilter; file->private_data = dmxdevfilter;
dvb_dmxdev_buffer_init(&dmxdevfilter->buffer); dvb_ringbuffer_init(&dmxdevfilter->buffer, NULL, 8192);
dmxdevfilter->type = DMXDEV_TYPE_NONE; dmxdevfilter->type = DMXDEV_TYPE_NONE;
dvb_dmxdev_filter_state_set(dmxdevfilter, DMXDEV_STATE_ALLOCATED); dvb_dmxdev_filter_state_set(dmxdevfilter, DMXDEV_STATE_ALLOCATED);
dmxdevfilter->feed.ts = NULL; dmxdevfilter->feed.ts = NULL;
...@@ -973,7 +935,7 @@ static unsigned int dvb_demux_poll(struct file *file, poll_table *wait) ...@@ -973,7 +935,7 @@ static unsigned int dvb_demux_poll(struct file *file, poll_table *wait)
if (dmxdevfilter->buffer.error) if (dmxdevfilter->buffer.error)
mask |= (POLLIN | POLLRDNORM | POLLPRI | POLLERR); mask |= (POLLIN | POLLRDNORM | POLLPRI | POLLERR);
if (dmxdevfilter->buffer.pread != dmxdevfilter->buffer.pwrite) if (!dvb_ringbuffer_empty(&dmxdevfilter->buffer))
mask |= (POLLIN | POLLRDNORM | POLLPRI); mask |= (POLLIN | POLLRDNORM | POLLPRI);
return mask; return mask;
...@@ -1047,7 +1009,7 @@ static unsigned int dvb_dvr_poll(struct file *file, poll_table *wait) ...@@ -1047,7 +1009,7 @@ static unsigned int dvb_dvr_poll(struct file *file, poll_table *wait)
if (dmxdev->dvr_buffer.error) if (dmxdev->dvr_buffer.error)
mask |= (POLLIN | POLLRDNORM | POLLPRI | POLLERR); mask |= (POLLIN | POLLRDNORM | POLLPRI | POLLERR);
if (dmxdev->dvr_buffer.pread != dmxdev->dvr_buffer.pwrite) if (!dvb_ringbuffer_empty(&dmxdev->dvr_buffer))
mask |= (POLLIN | POLLRDNORM | POLLPRI); mask |= (POLLIN | POLLRDNORM | POLLPRI);
} else } else
mask |= (POLLOUT | POLLWRNORM | POLLPRI); mask |= (POLLOUT | POLLWRNORM | POLLPRI);
...@@ -1097,7 +1059,7 @@ int dvb_dmxdev_init(struct dmxdev *dmxdev, struct dvb_adapter *dvb_adapter) ...@@ -1097,7 +1059,7 @@ int dvb_dmxdev_init(struct dmxdev *dmxdev, struct dvb_adapter *dvb_adapter)
dvb_register_device(dvb_adapter, &dmxdev->dvr_dvbdev, &dvbdev_dvr, dvb_register_device(dvb_adapter, &dmxdev->dvr_dvbdev, &dvbdev_dvr,
dmxdev, DVB_DEVICE_DVR); dmxdev, DVB_DEVICE_DVR);
dvb_dmxdev_buffer_init(&dmxdev->dvr_buffer); dvb_ringbuffer_init(&dmxdev->dvr_buffer, NULL, 8192);
return 0; return 0;
} }
......
...@@ -36,6 +36,7 @@ ...@@ -36,6 +36,7 @@
#include "dvbdev.h" #include "dvbdev.h"
#include "demux.h" #include "demux.h"
#include "dvb_ringbuffer.h"
enum dmxdev_type { enum dmxdev_type {
DMXDEV_TYPE_NONE, DMXDEV_TYPE_NONE,
...@@ -52,15 +53,6 @@ enum dmxdev_state { ...@@ -52,15 +53,6 @@ enum dmxdev_state {
DMXDEV_STATE_TIMEDOUT DMXDEV_STATE_TIMEDOUT
}; };
struct dmxdev_buffer {
u8 *data;
int size;
int pread;
int pwrite;
wait_queue_head_t queue;
int error;
};
struct dmxdev_filter { struct dmxdev_filter {
union { union {
struct dmx_section_filter *sec; struct dmx_section_filter *sec;
...@@ -79,7 +71,7 @@ struct dmxdev_filter { ...@@ -79,7 +71,7 @@ struct dmxdev_filter {
enum dmxdev_type type; enum dmxdev_type type;
enum dmxdev_state state; enum dmxdev_state state;
struct dmxdev *dev; struct dmxdev *dev;
struct dmxdev_buffer buffer; struct dvb_ringbuffer buffer;
struct mutex mutex; struct mutex mutex;
...@@ -102,7 +94,7 @@ struct dmxdev { ...@@ -102,7 +94,7 @@ struct dmxdev {
#define DMXDEV_CAP_DUPLEX 1 #define DMXDEV_CAP_DUPLEX 1
struct dmx_frontend *dvr_orig_fe; struct dmx_frontend *dvr_orig_fe;
struct dmxdev_buffer dvr_buffer; struct dvb_ringbuffer dvr_buffer;
#define DVR_BUFFER_SIZE (10*188*1024) #define DVR_BUFFER_SIZE (10*188*1024)
struct mutex mutex; struct mutex mutex;
......
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