Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

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

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
Loading
Loading
Loading
Loading
+59 −97
Original line number Diff line number Diff line
@@ -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;
		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 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;
}
+3 −11
Original line number Diff line number Diff line
@@ -36,6 +36,7 @@

#include "dvbdev.h"
#include "demux.h"
#include "dvb_ringbuffer.h"

enum dmxdev_type {
	DMXDEV_TYPE_NONE,
@@ -52,15 +53,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;
@@ -79,7 +71,7 @@ struct dmxdev_filter {
	enum dmxdev_type type;
	enum dmxdev_state state;
	struct dmxdev *dev;
	struct dmxdev_buffer buffer;
	struct dvb_ringbuffer buffer;

	struct mutex mutex;

@@ -102,7 +94,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)

	struct mutex mutex;