diff options
author | Andreas Oberritter <obi@linuxtv.org> | 2006-03-14 15:31:01 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@g5.osdl.org> | 2006-03-21 11:53:29 -0500 |
commit | 34731df288a5ffe4b0c396caf8cd24c6a710a222 (patch) | |
tree | 06738b1c00d2bee0df3b42d125b2ca4e03fc18b0 | |
parent | 4304954eb668ce66fc58f1cab9abb9a9e2584549 (diff) |
V4L/DVB (3501): Dmxdev: use dvb_ringbuffer
Use dvb_ringbuffer instead of an own buffer implementation in
dmxdev.[ch].
Signed-off-by: Andreas Oberritter <obi@linuxtv.org>
Signed-off-by: Mauro Carvalho Chehab <mchehab@infradead.org>
-rw-r--r-- | drivers/media/dvb/dvb-core/dmxdev.c | 156 | ||||
-rw-r--r-- | drivers/media/dvb/dvb-core/dmxdev.h | 14 |
2 files changed, 62 insertions, 108 deletions
diff --git a/drivers/media/dvb/dvb-core/dmxdev.c b/drivers/media/dvb/dvb-core/dmxdev.c index f6932d6c62e3..09e96e9ddbdf 100644 --- a/drivers/media/dvb/dvb-core/dmxdev.c +++ b/drivers/media/dvb/dvb-core/dmxdev.c | |||
@@ -40,110 +40,72 @@ MODULE_PARM_DESC(debug, "Turn on/off debugging (default:off)."); | |||
40 | 40 | ||
41 | #define dprintk if (debug) printk | 41 | #define dprintk if (debug) printk |
42 | 42 | ||
43 | static inline void dvb_dmxdev_buffer_init(struct dmxdev_buffer *buffer) | 43 | static int dvb_dmxdev_buffer_write(struct dvb_ringbuffer *buf, |
44 | const u8 *src, size_t len) | ||
44 | { | 45 | { |
45 | buffer->data = NULL; | 46 | ssize_t free; |
46 | buffer->size = 8192; | ||
47 | buffer->pread = 0; | ||
48 | buffer->pwrite = 0; | ||
49 | buffer->error = 0; | ||
50 | init_waitqueue_head(&buffer->queue); | ||
51 | } | ||
52 | |||
53 | static inline int dvb_dmxdev_buffer_write(struct dmxdev_buffer *buf, | ||
54 | const u8 *src, int len) | ||
55 | { | ||
56 | int split; | ||
57 | int free; | ||
58 | int todo; | ||
59 | 47 | ||
60 | if (!len) | 48 | if (!len) |
61 | return 0; | 49 | return 0; |
62 | if (!buf->data) | 50 | if (!buf->data) |
63 | return 0; | 51 | return 0; |
64 | 52 | ||
65 | free = buf->pread - buf->pwrite; | 53 | free = dvb_ringbuffer_free(buf); |
66 | split = 0; | 54 | if (len > free) { |
67 | if (free <= 0) { | ||
68 | free += buf->size; | ||
69 | split = buf->size - buf->pwrite; | ||
70 | } | ||
71 | if (len >= free) { | ||
72 | dprintk("dmxdev: buffer overflow\n"); | 55 | dprintk("dmxdev: buffer overflow\n"); |
73 | return -1; | 56 | return -EOVERFLOW; |
74 | } | ||
75 | if (split >= len) | ||
76 | split = 0; | ||
77 | todo = len; | ||
78 | if (split) { | ||
79 | memcpy(buf->data + buf->pwrite, src, split); | ||
80 | todo -= split; | ||
81 | buf->pwrite = 0; | ||
82 | } | 57 | } |
83 | memcpy(buf->data + buf->pwrite, src + split, todo); | 58 | |
84 | buf->pwrite = (buf->pwrite + todo) % buf->size; | 59 | return dvb_ringbuffer_write(buf, src, len); |
85 | return len; | ||
86 | } | 60 | } |
87 | 61 | ||
88 | static ssize_t dvb_dmxdev_buffer_read(struct dmxdev_buffer *src, | 62 | static ssize_t dvb_dmxdev_buffer_read(struct dvb_ringbuffer *src, |
89 | int non_blocking, char __user *buf, | 63 | int non_blocking, char __user *buf, |
90 | size_t count, loff_t *ppos) | 64 | size_t count, loff_t *ppos) |
91 | { | 65 | { |
92 | unsigned long todo = count; | 66 | size_t todo; |
93 | int split, avail, error; | 67 | ssize_t avail; |
68 | ssize_t ret = 0; | ||
94 | 69 | ||
95 | if (!src->data) | 70 | if (!src->data) |
96 | return 0; | 71 | return 0; |
97 | 72 | ||
98 | if ((error = src->error)) { | 73 | if (src->error) { |
99 | src->pwrite = src->pread; | 74 | ret = src->error; |
100 | src->error = 0; | 75 | dvb_ringbuffer_flush(src); |
101 | return error; | 76 | return ret; |
102 | } | 77 | } |
103 | 78 | ||
104 | if (non_blocking && (src->pwrite == src->pread)) | 79 | for (todo = count; todo > 0; todo -= ret) { |
105 | return -EWOULDBLOCK; | 80 | if (non_blocking && dvb_ringbuffer_empty(src)) { |
106 | 81 | ret = -EWOULDBLOCK; | |
107 | while (todo > 0) { | 82 | break; |
108 | if (non_blocking && (src->pwrite == src->pread)) | 83 | } |
109 | return (count - todo) ? (count - todo) : -EWOULDBLOCK; | ||
110 | 84 | ||
111 | if (wait_event_interruptible(src->queue, | 85 | ret = wait_event_interruptible(src->queue, |
112 | (src->pread != src->pwrite) || | 86 | !dvb_ringbuffer_empty(src) || |
113 | (src->error)) < 0) | 87 | (src->error != 0)); |
114 | return count - todo; | 88 | if (ret < 0) |
89 | break; | ||
115 | 90 | ||
116 | if ((error = src->error)) { | 91 | if (src->error) { |
117 | src->pwrite = src->pread; | 92 | ret = src->error; |
118 | src->error = 0; | 93 | dvb_ringbuffer_flush(src); |
119 | return error; | 94 | break; |
120 | } | 95 | } |
121 | 96 | ||
122 | split = src->size; | 97 | avail = dvb_ringbuffer_avail(src); |
123 | avail = src->pwrite - src->pread; | ||
124 | if (avail < 0) { | ||
125 | avail += src->size; | ||
126 | split = src->size - src->pread; | ||
127 | } | ||
128 | if (avail > todo) | 98 | if (avail > todo) |
129 | avail = todo; | 99 | avail = todo; |
130 | if (split < avail) { | 100 | |
131 | if (copy_to_user(buf, src->data + src->pread, split)) | 101 | ret = dvb_ringbuffer_read(src, buf, avail, 1); |
132 | return -EFAULT; | 102 | if (ret < 0) |
133 | buf += split; | 103 | break; |
134 | src->pread = 0; | 104 | |
135 | todo -= split; | 105 | buf += ret; |
136 | avail -= split; | ||
137 | } | ||
138 | if (avail) { | ||
139 | if (copy_to_user(buf, src->data + src->pread, avail)) | ||
140 | return -EFAULT; | ||
141 | src->pread = (src->pread + avail) % src->size; | ||
142 | todo -= avail; | ||
143 | buf += avail; | ||
144 | } | ||
145 | } | 106 | } |
146 | return count; | 107 | |
108 | return (count - todo) ? (count - todo) : ret; | ||
147 | } | 109 | } |
148 | 110 | ||
149 | static struct dmx_frontend *get_fe(struct dmx_demux *demux, int type) | 111 | 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 | } | 141 | } |
180 | 142 | ||
181 | if ((file->f_flags & O_ACCMODE) == O_RDONLY) { | 143 | if ((file->f_flags & O_ACCMODE) == O_RDONLY) { |
182 | dvb_dmxdev_buffer_init(&dmxdev->dvr_buffer); | 144 | void *mem = vmalloc(DVR_BUFFER_SIZE); |
183 | dmxdev->dvr_buffer.size = DVR_BUFFER_SIZE; | 145 | if (!mem) { |
184 | dmxdev->dvr_buffer.data = vmalloc(DVR_BUFFER_SIZE); | ||
185 | if (!dmxdev->dvr_buffer.data) { | ||
186 | mutex_unlock(&dmxdev->mutex); | 146 | mutex_unlock(&dmxdev->mutex); |
187 | return -ENOMEM; | 147 | return -ENOMEM; |
188 | } | 148 | } |
149 | dvb_ringbuffer_init(&dmxdev->dvr_buffer, mem, DVR_BUFFER_SIZE); | ||
189 | } | 150 | } |
190 | 151 | ||
191 | if ((file->f_flags & O_ACCMODE) == O_WRONLY) { | 152 | if ((file->f_flags & O_ACCMODE) == O_WRONLY) { |
@@ -280,7 +241,7 @@ static inline void dvb_dmxdev_filter_state_set(struct dmxdev_filter | |||
280 | static int dvb_dmxdev_set_buffer_size(struct dmxdev_filter *dmxdevfilter, | 241 | static int dvb_dmxdev_set_buffer_size(struct dmxdev_filter *dmxdevfilter, |
281 | unsigned long size) | 242 | unsigned long size) |
282 | { | 243 | { |
283 | struct dmxdev_buffer *buf = &dmxdevfilter->buffer; | 244 | struct dvb_ringbuffer *buf = &dmxdevfilter->buffer; |
284 | void *mem; | 245 | void *mem; |
285 | 246 | ||
286 | if (buf->size == size) | 247 | if (buf->size == size) |
@@ -291,7 +252,7 @@ static int dvb_dmxdev_set_buffer_size(struct dmxdev_filter *dmxdevfilter, | |||
291 | mem = buf->data; | 252 | mem = buf->data; |
292 | buf->data = NULL; | 253 | buf->data = NULL; |
293 | buf->size = size; | 254 | buf->size = size; |
294 | buf->pwrite = buf->pread = 0; | 255 | dvb_ringbuffer_flush(buf); |
295 | spin_unlock_irq(&dmxdevfilter->dev->lock); | 256 | spin_unlock_irq(&dmxdevfilter->dev->lock); |
296 | vfree(mem); | 257 | vfree(mem); |
297 | 258 | ||
@@ -359,8 +320,8 @@ static int dvb_dmxdev_section_callback(const u8 *buffer1, size_t buffer1_len, | |||
359 | buffer2_len); | 320 | buffer2_len); |
360 | } | 321 | } |
361 | if (ret < 0) { | 322 | if (ret < 0) { |
362 | dmxdevfilter->buffer.pwrite = dmxdevfilter->buffer.pread; | 323 | dvb_ringbuffer_flush(&dmxdevfilter->buffer); |
363 | dmxdevfilter->buffer.error = -EOVERFLOW; | 324 | dmxdevfilter->buffer.error = ret; |
364 | } | 325 | } |
365 | if (dmxdevfilter->params.sec.flags & DMX_ONESHOT) | 326 | if (dmxdevfilter->params.sec.flags & DMX_ONESHOT) |
366 | dmxdevfilter->state = DMXDEV_STATE_DONE; | 327 | dmxdevfilter->state = DMXDEV_STATE_DONE; |
@@ -375,7 +336,7 @@ static int dvb_dmxdev_ts_callback(const u8 *buffer1, size_t buffer1_len, | |||
375 | enum dmx_success success) | 336 | enum dmx_success success) |
376 | { | 337 | { |
377 | struct dmxdev_filter *dmxdevfilter = feed->priv; | 338 | struct dmxdev_filter *dmxdevfilter = feed->priv; |
378 | struct dmxdev_buffer *buffer; | 339 | struct dvb_ringbuffer *buffer; |
379 | int ret; | 340 | int ret; |
380 | 341 | ||
381 | spin_lock(&dmxdevfilter->dev->lock); | 342 | spin_lock(&dmxdevfilter->dev->lock); |
@@ -397,8 +358,8 @@ static int dvb_dmxdev_ts_callback(const u8 *buffer1, size_t buffer1_len, | |||
397 | if (ret == buffer1_len) | 358 | if (ret == buffer1_len) |
398 | ret = dvb_dmxdev_buffer_write(buffer, buffer2, buffer2_len); | 359 | ret = dvb_dmxdev_buffer_write(buffer, buffer2, buffer2_len); |
399 | if (ret < 0) { | 360 | if (ret < 0) { |
400 | buffer->pwrite = buffer->pread; | 361 | dvb_ringbuffer_flush(buffer); |
401 | buffer->error = -EOVERFLOW; | 362 | buffer->error = ret; |
402 | } | 363 | } |
403 | spin_unlock(&dmxdevfilter->dev->lock); | 364 | spin_unlock(&dmxdevfilter->dev->lock); |
404 | wake_up(&buffer->queue); | 365 | wake_up(&buffer->queue); |
@@ -494,7 +455,8 @@ static int dvb_dmxdev_filter_stop(struct dmxdev_filter *dmxdevfilter) | |||
494 | return 0; | 455 | return 0; |
495 | return -EINVAL; | 456 | return -EINVAL; |
496 | } | 457 | } |
497 | dmxdevfilter->buffer.pwrite = dmxdevfilter->buffer.pread = 0; | 458 | |
459 | dvb_ringbuffer_flush(&dmxdevfilter->buffer); | ||
498 | return 0; | 460 | return 0; |
499 | } | 461 | } |
500 | 462 | ||
@@ -520,16 +482,16 @@ static int dvb_dmxdev_filter_start(struct dmxdev_filter *filter) | |||
520 | if (filter->state >= DMXDEV_STATE_GO) | 482 | if (filter->state >= DMXDEV_STATE_GO) |
521 | dvb_dmxdev_filter_stop(filter); | 483 | dvb_dmxdev_filter_stop(filter); |
522 | 484 | ||
523 | if (!(mem = filter->buffer.data)) { | 485 | if (!filter->buffer.data) { |
524 | mem = vmalloc(filter->buffer.size); | 486 | mem = vmalloc(filter->buffer.size); |
487 | if (!mem) | ||
488 | return -ENOMEM; | ||
525 | spin_lock_irq(&filter->dev->lock); | 489 | spin_lock_irq(&filter->dev->lock); |
526 | filter->buffer.data = mem; | 490 | filter->buffer.data = mem; |
527 | spin_unlock_irq(&filter->dev->lock); | 491 | spin_unlock_irq(&filter->dev->lock); |
528 | if (!filter->buffer.data) | ||
529 | return -ENOMEM; | ||
530 | } | 492 | } |
531 | 493 | ||
532 | filter->buffer.pwrite = filter->buffer.pread = 0; | 494 | dvb_ringbuffer_flush(&filter->buffer); |
533 | 495 | ||
534 | switch (filter->type) { | 496 | switch (filter->type) { |
535 | case DMXDEV_TYPE_SEC: | 497 | case DMXDEV_TYPE_SEC: |
@@ -692,7 +654,7 @@ static int dvb_demux_open(struct inode *inode, struct file *file) | |||
692 | mutex_init(&dmxdevfilter->mutex); | 654 | mutex_init(&dmxdevfilter->mutex); |
693 | file->private_data = dmxdevfilter; | 655 | file->private_data = dmxdevfilter; |
694 | 656 | ||
695 | dvb_dmxdev_buffer_init(&dmxdevfilter->buffer); | 657 | dvb_ringbuffer_init(&dmxdevfilter->buffer, NULL, 8192); |
696 | dmxdevfilter->type = DMXDEV_TYPE_NONE; | 658 | dmxdevfilter->type = DMXDEV_TYPE_NONE; |
697 | dvb_dmxdev_filter_state_set(dmxdevfilter, DMXDEV_STATE_ALLOCATED); | 659 | dvb_dmxdev_filter_state_set(dmxdevfilter, DMXDEV_STATE_ALLOCATED); |
698 | dmxdevfilter->feed.ts = NULL; | 660 | dmxdevfilter->feed.ts = NULL; |
@@ -973,7 +935,7 @@ static unsigned int dvb_demux_poll(struct file *file, poll_table *wait) | |||
973 | if (dmxdevfilter->buffer.error) | 935 | if (dmxdevfilter->buffer.error) |
974 | mask |= (POLLIN | POLLRDNORM | POLLPRI | POLLERR); | 936 | mask |= (POLLIN | POLLRDNORM | POLLPRI | POLLERR); |
975 | 937 | ||
976 | if (dmxdevfilter->buffer.pread != dmxdevfilter->buffer.pwrite) | 938 | if (!dvb_ringbuffer_empty(&dmxdevfilter->buffer)) |
977 | mask |= (POLLIN | POLLRDNORM | POLLPRI); | 939 | mask |= (POLLIN | POLLRDNORM | POLLPRI); |
978 | 940 | ||
979 | return mask; | 941 | return mask; |
@@ -1047,7 +1009,7 @@ static unsigned int dvb_dvr_poll(struct file *file, poll_table *wait) | |||
1047 | if (dmxdev->dvr_buffer.error) | 1009 | if (dmxdev->dvr_buffer.error) |
1048 | mask |= (POLLIN | POLLRDNORM | POLLPRI | POLLERR); | 1010 | mask |= (POLLIN | POLLRDNORM | POLLPRI | POLLERR); |
1049 | 1011 | ||
1050 | if (dmxdev->dvr_buffer.pread != dmxdev->dvr_buffer.pwrite) | 1012 | if (!dvb_ringbuffer_empty(&dmxdev->dvr_buffer)) |
1051 | mask |= (POLLIN | POLLRDNORM | POLLPRI); | 1013 | mask |= (POLLIN | POLLRDNORM | POLLPRI); |
1052 | } else | 1014 | } else |
1053 | mask |= (POLLOUT | POLLWRNORM | POLLPRI); | 1015 | mask |= (POLLOUT | POLLWRNORM | POLLPRI); |
@@ -1097,7 +1059,7 @@ int dvb_dmxdev_init(struct dmxdev *dmxdev, struct dvb_adapter *dvb_adapter) | |||
1097 | dvb_register_device(dvb_adapter, &dmxdev->dvr_dvbdev, &dvbdev_dvr, | 1059 | dvb_register_device(dvb_adapter, &dmxdev->dvr_dvbdev, &dvbdev_dvr, |
1098 | dmxdev, DVB_DEVICE_DVR); | 1060 | dmxdev, DVB_DEVICE_DVR); |
1099 | 1061 | ||
1100 | dvb_dmxdev_buffer_init(&dmxdev->dvr_buffer); | 1062 | dvb_ringbuffer_init(&dmxdev->dvr_buffer, NULL, 8192); |
1101 | 1063 | ||
1102 | return 0; | 1064 | return 0; |
1103 | } | 1065 | } |
diff --git a/drivers/media/dvb/dvb-core/dmxdev.h b/drivers/media/dvb/dvb-core/dmxdev.h index 1b3e49bd9aa2..d2bee9ffe43c 100644 --- a/drivers/media/dvb/dvb-core/dmxdev.h +++ b/drivers/media/dvb/dvb-core/dmxdev.h | |||
@@ -36,6 +36,7 @@ | |||
36 | 36 | ||
37 | #include "dvbdev.h" | 37 | #include "dvbdev.h" |
38 | #include "demux.h" | 38 | #include "demux.h" |
39 | #include "dvb_ringbuffer.h" | ||
39 | 40 | ||
40 | enum dmxdev_type { | 41 | enum dmxdev_type { |
41 | DMXDEV_TYPE_NONE, | 42 | DMXDEV_TYPE_NONE, |
@@ -52,15 +53,6 @@ enum dmxdev_state { | |||
52 | DMXDEV_STATE_TIMEDOUT | 53 | DMXDEV_STATE_TIMEDOUT |
53 | }; | 54 | }; |
54 | 55 | ||
55 | struct dmxdev_buffer { | ||
56 | u8 *data; | ||
57 | int size; | ||
58 | int pread; | ||
59 | int pwrite; | ||
60 | wait_queue_head_t queue; | ||
61 | int error; | ||
62 | }; | ||
63 | |||
64 | struct dmxdev_filter { | 56 | struct dmxdev_filter { |
65 | union { | 57 | union { |
66 | struct dmx_section_filter *sec; | 58 | struct dmx_section_filter *sec; |
@@ -79,7 +71,7 @@ struct dmxdev_filter { | |||
79 | enum dmxdev_type type; | 71 | enum dmxdev_type type; |
80 | enum dmxdev_state state; | 72 | enum dmxdev_state state; |
81 | struct dmxdev *dev; | 73 | struct dmxdev *dev; |
82 | struct dmxdev_buffer buffer; | 74 | struct dvb_ringbuffer buffer; |
83 | 75 | ||
84 | struct mutex mutex; | 76 | struct mutex mutex; |
85 | 77 | ||
@@ -102,7 +94,7 @@ struct dmxdev { | |||
102 | #define DMXDEV_CAP_DUPLEX 1 | 94 | #define DMXDEV_CAP_DUPLEX 1 |
103 | struct dmx_frontend *dvr_orig_fe; | 95 | struct dmx_frontend *dvr_orig_fe; |
104 | 96 | ||
105 | struct dmxdev_buffer dvr_buffer; | 97 | struct dvb_ringbuffer dvr_buffer; |
106 | #define DVR_BUFFER_SIZE (10*188*1024) | 98 | #define DVR_BUFFER_SIZE (10*188*1024) |
107 | 99 | ||
108 | struct mutex mutex; | 100 | struct mutex mutex; |