From eef01923b77627b1aeead66d2ba596b3dbc0c35d Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Tue, 14 Mar 2006 17:30:09 -0300 Subject: Ringbuffer: don't reset pointers to zero From: Andreas Oberritter Oliver Endriss spotted, that resetting read and write pointers on flush() requires additional locking and breaks the av7110 driver. Therefore this patch partially reverts the previous patch titled "make dvb_ringbuffer compatible to dmxdev_buffer". Signed-off-by: Andreas Oberritter Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/dvb/dvb-core/dvb_ringbuffer.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'linux/drivers/media/dvb') diff --git a/linux/drivers/media/dvb/dvb-core/dvb_ringbuffer.c b/linux/drivers/media/dvb/dvb-core/dvb_ringbuffer.c index f23324835..c972fe014 100644 --- a/linux/drivers/media/dvb/dvb-core/dvb_ringbuffer.c +++ b/linux/drivers/media/dvb/dvb-core/dvb_ringbuffer.c @@ -87,7 +87,7 @@ ssize_t dvb_ringbuffer_avail(struct dvb_ringbuffer *rbuf) void dvb_ringbuffer_flush(struct dvb_ringbuffer *rbuf) { - rbuf->pread = rbuf->pwrite = 0; + rbuf->pread = rbuf->pwrite; rbuf->error = 0; } -- cgit v1.2.3 From 93d4ff1bf42268c291a14a04c34d700189f42a27 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Tue, 14 Mar 2006 17:31:01 -0300 Subject: Dmxdev: use dvb_ringbuffer From: Andreas Oberritter Use dvb_ringbuffer instead of an own buffer implementation in dmxdev.[ch]. Signed-off-by: Andreas Oberritter Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/dvb/dvb-core/dmxdev.c | 156 +++++++++++------------------- linux/drivers/media/dvb/dvb-core/dmxdev.h | 14 +-- 2 files changed, 62 insertions(+), 108 deletions(-) (limited to 'linux/drivers/media/dvb') diff --git a/linux/drivers/media/dvb/dvb-core/dmxdev.c b/linux/drivers/media/dvb/dvb-core/dmxdev.c index f6932d6c6..09e96e9dd 100644 --- a/linux/drivers/media/dvb/dvb-core/dmxdev.c +++ b/linux/drivers/media/dvb/dvb-core/dmxdev.c @@ -40,110 +40,72 @@ MODULE_PARM_DESC(debug, "Turn on/off debugging (default:off)."); #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; - 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; + ssize_t free; if (!len) return 0; if (!buf->data) return 0; - free = buf->pread - buf->pwrite; - split = 0; - if (free <= 0) { - free += buf->size; - split = buf->size - buf->pwrite; - } - if (len >= free) { + free = dvb_ringbuffer_free(buf); + if (len > free) { dprintk("dmxdev: buffer overflow\n"); - return -1; - } - if (split >= len) - split = 0; - todo = len; - if (split) { - memcpy(buf->data + buf->pwrite, src, split); - todo -= split; - buf->pwrite = 0; + return -EOVERFLOW; } - memcpy(buf->data + buf->pwrite, src + split, todo); - buf->pwrite = (buf->pwrite + todo) % buf->size; - return len; + + return dvb_ringbuffer_write(buf, src, 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, size_t count, loff_t *ppos) { - unsigned long todo = count; - int split, avail, error; + size_t todo; + ssize_t avail; + ssize_t ret = 0; if (!src->data) return 0; - if ((error = src->error)) { - src->pwrite = src->pread; - src->error = 0; - return error; + if (src->error) { + ret = src->error; + dvb_ringbuffer_flush(src); + return ret; } - if (non_blocking && (src->pwrite == src->pread)) - return -EWOULDBLOCK; - - while (todo > 0) { - if (non_blocking && (src->pwrite == src->pread)) - return (count - todo) ? (count - todo) : -EWOULDBLOCK; + for (todo = count; todo > 0; todo -= ret) { + if (non_blocking && dvb_ringbuffer_empty(src)) { + ret = -EWOULDBLOCK; + break; + } - if (wait_event_interruptible(src->queue, - (src->pread != src->pwrite) || - (src->error)) < 0) - return count - todo; + ret = wait_event_interruptible(src->queue, + !dvb_ringbuffer_empty(src) || + (src->error != 0)); + if (ret < 0) + break; - if ((error = src->error)) { - src->pwrite = src->pread; - src->error = 0; - return error; + if (src->error) { + ret = src->error; + dvb_ringbuffer_flush(src); + break; } - split = src->size; - avail = src->pwrite - src->pread; - if (avail < 0) { - avail += src->size; - split = src->size - src->pread; - } + avail = dvb_ringbuffer_avail(src); if (avail > todo) avail = todo; - if (split < avail) { - if (copy_to_user(buf, src->data + src->pread, split)) - return -EFAULT; - buf += split; - src->pread = 0; - todo -= split; - 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; - } + + ret = dvb_ringbuffer_read(src, buf, avail, 1); + if (ret < 0) + break; + + buf += ret; } - return count; + + return (count - todo) ? (count - todo) : ret; } 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) } if ((file->f_flags & O_ACCMODE) == O_RDONLY) { - dvb_dmxdev_buffer_init(&dmxdev->dvr_buffer); - dmxdev->dvr_buffer.size = DVR_BUFFER_SIZE; - dmxdev->dvr_buffer.data = vmalloc(DVR_BUFFER_SIZE); - if (!dmxdev->dvr_buffer.data) { + void *mem = vmalloc(DVR_BUFFER_SIZE); + if (!mem) { mutex_unlock(&dmxdev->mutex); return -ENOMEM; } + dvb_ringbuffer_init(&dmxdev->dvr_buffer, mem, DVR_BUFFER_SIZE); } if ((file->f_flags & O_ACCMODE) == O_WRONLY) { @@ -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, unsigned long size) { - struct dmxdev_buffer *buf = &dmxdevfilter->buffer; + struct dvb_ringbuffer *buf = &dmxdevfilter->buffer; void *mem; if (buf->size == size) @@ -291,7 +252,7 @@ static int dvb_dmxdev_set_buffer_size(struct dmxdev_filter *dmxdevfilter, mem = buf->data; buf->data = NULL; buf->size = size; - buf->pwrite = buf->pread = 0; + dvb_ringbuffer_flush(buf); spin_unlock_irq(&dmxdevfilter->dev->lock); vfree(mem); @@ -359,8 +320,8 @@ static int dvb_dmxdev_section_callback(const u8 *buffer1, size_t buffer1_len, buffer2_len); } if (ret < 0) { - dmxdevfilter->buffer.pwrite = dmxdevfilter->buffer.pread; - dmxdevfilter->buffer.error = -EOVERFLOW; + dvb_ringbuffer_flush(&dmxdevfilter->buffer); + dmxdevfilter->buffer.error = ret; } if (dmxdevfilter->params.sec.flags & DMX_ONESHOT) dmxdevfilter->state = DMXDEV_STATE_DONE; @@ -375,7 +336,7 @@ static int dvb_dmxdev_ts_callback(const u8 *buffer1, size_t buffer1_len, enum dmx_success success) { struct dmxdev_filter *dmxdevfilter = feed->priv; - struct dmxdev_buffer *buffer; + struct dvb_ringbuffer *buffer; int ret; spin_lock(&dmxdevfilter->dev->lock); @@ -397,8 +358,8 @@ static int dvb_dmxdev_ts_callback(const u8 *buffer1, size_t buffer1_len, if (ret == buffer1_len) ret = dvb_dmxdev_buffer_write(buffer, buffer2, buffer2_len); if (ret < 0) { - buffer->pwrite = buffer->pread; - buffer->error = -EOVERFLOW; + dvb_ringbuffer_flush(buffer); + buffer->error = ret; } spin_unlock(&dmxdevfilter->dev->lock); wake_up(&buffer->queue); @@ -494,7 +455,8 @@ static int dvb_dmxdev_filter_stop(struct dmxdev_filter *dmxdevfilter) return 0; return -EINVAL; } - dmxdevfilter->buffer.pwrite = dmxdevfilter->buffer.pread = 0; + + dvb_ringbuffer_flush(&dmxdevfilter->buffer); return 0; } @@ -520,16 +482,16 @@ static int dvb_dmxdev_filter_start(struct dmxdev_filter *filter) if (filter->state >= DMXDEV_STATE_GO) dvb_dmxdev_filter_stop(filter); - if (!(mem = filter->buffer.data)) { + if (!filter->buffer.data) { mem = vmalloc(filter->buffer.size); + if (!mem) + return -ENOMEM; spin_lock_irq(&filter->dev->lock); filter->buffer.data = mem; 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) { case DMXDEV_TYPE_SEC: @@ -692,7 +654,7 @@ static int dvb_demux_open(struct inode *inode, struct file *file) mutex_init(&dmxdevfilter->mutex); file->private_data = dmxdevfilter; - dvb_dmxdev_buffer_init(&dmxdevfilter->buffer); + dvb_ringbuffer_init(&dmxdevfilter->buffer, NULL, 8192); dmxdevfilter->type = DMXDEV_TYPE_NONE; dvb_dmxdev_filter_state_set(dmxdevfilter, DMXDEV_STATE_ALLOCATED); dmxdevfilter->feed.ts = NULL; @@ -973,7 +935,7 @@ static unsigned int dvb_demux_poll(struct file *file, poll_table *wait) if (dmxdevfilter->buffer.error) mask |= (POLLIN | POLLRDNORM | POLLPRI | POLLERR); - if (dmxdevfilter->buffer.pread != dmxdevfilter->buffer.pwrite) + if (!dvb_ringbuffer_empty(&dmxdevfilter->buffer)) mask |= (POLLIN | POLLRDNORM | POLLPRI); return mask; @@ -1047,7 +1009,7 @@ static unsigned int dvb_dvr_poll(struct file *file, poll_table *wait) if (dmxdev->dvr_buffer.error) 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); } else mask |= (POLLOUT | POLLWRNORM | POLLPRI); @@ -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, dmxdev, DVB_DEVICE_DVR); - dvb_dmxdev_buffer_init(&dmxdev->dvr_buffer); + dvb_ringbuffer_init(&dmxdev->dvr_buffer, NULL, 8192); return 0; } diff --git a/linux/drivers/media/dvb/dvb-core/dmxdev.h b/linux/drivers/media/dvb/dvb-core/dmxdev.h index 73da838f8..080abd9a9 100644 --- a/linux/drivers/media/dvb/dvb-core/dmxdev.h +++ b/linux/drivers/media/dvb/dvb-core/dmxdev.h @@ -39,6 +39,7 @@ #include "dvbdev.h" #include "demux.h" +#include "dvb_ringbuffer.h" enum dmxdev_type { DMXDEV_TYPE_NONE, @@ -55,15 +56,6 @@ enum dmxdev_state { DMXDEV_STATE_TIMEDOUT }; -struct dmxdev_buffer { - u8 *data; - int size; - int pread; - int pwrite; - wait_queue_head_t queue; - int error; -}; - struct dmxdev_filter { union { struct dmx_section_filter *sec; @@ -82,7 +74,7 @@ struct dmxdev_filter { enum dmxdev_type type; enum dmxdev_state state; struct dmxdev *dev; - struct dmxdev_buffer buffer; + struct dvb_ringbuffer buffer; #if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,15) struct mutex mutex; @@ -109,7 +101,7 @@ struct dmxdev { #define DMXDEV_CAP_DUPLEX 1 struct dmx_frontend *dvr_orig_fe; - struct dmxdev_buffer dvr_buffer; + struct dvb_ringbuffer dvr_buffer; #define DVR_BUFFER_SIZE (10*188*1024) #if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,15) -- cgit v1.2.3