Lines Matching +full:- +full:s

1 // SPDX-License-Identifier: GPL-2.0-or-later
4 Copyright (C) 2003-2004 Kevin Thayer <nufan_wfk at yahoo.com>
6 Copyright (C) 2005-2007 Hans Verkuil <[email protected]>
10 #include "ivtv-driver.h"
11 #include "ivtv-queue.h"
13 int ivtv_buf_copy_from_user(struct ivtv_stream *s, struct ivtv_buffer *buf, const char __user *src,… in ivtv_buf_copy_from_user() argument
15 if (s->buf_size - buf->bytesused < copybytes) in ivtv_buf_copy_from_user()
16 copybytes = s->buf_size - buf->bytesused; in ivtv_buf_copy_from_user()
17 if (copy_from_user(buf->buf + buf->bytesused, src, copybytes)) { in ivtv_buf_copy_from_user()
18 return -EFAULT; in ivtv_buf_copy_from_user()
20 buf->bytesused += copybytes; in ivtv_buf_copy_from_user()
28 for (i = 0; i < buf->bytesused; i += 4) in ivtv_buf_swap()
29 swab32s((u32 *)(buf->buf + i)); in ivtv_buf_swap()
34 INIT_LIST_HEAD(&q->list); in ivtv_queue_init()
35 q->buffers = 0; in ivtv_queue_init()
36 q->length = 0; in ivtv_queue_init()
37 q->bytesused = 0; in ivtv_queue_init()
40 void ivtv_enqueue(struct ivtv_stream *s, struct ivtv_buffer *buf, struct ivtv_queue *q) in ivtv_enqueue() argument
45 if (q == &s->q_free) { in ivtv_enqueue()
46 buf->bytesused = 0; in ivtv_enqueue()
47 buf->readpos = 0; in ivtv_enqueue()
48 buf->b_flags = 0; in ivtv_enqueue()
49 buf->dma_xfer_cnt = 0; in ivtv_enqueue()
51 spin_lock_irqsave(&s->qlock, flags); in ivtv_enqueue()
52 list_add_tail(&buf->list, &q->list); in ivtv_enqueue()
53 q->buffers++; in ivtv_enqueue()
54 q->length += s->buf_size; in ivtv_enqueue()
55 q->bytesused += buf->bytesused - buf->readpos; in ivtv_enqueue()
56 spin_unlock_irqrestore(&s->qlock, flags); in ivtv_enqueue()
59 struct ivtv_buffer *ivtv_dequeue(struct ivtv_stream *s, struct ivtv_queue *q) in ivtv_dequeue() argument
64 spin_lock_irqsave(&s->qlock, flags); in ivtv_dequeue()
65 if (!list_empty(&q->list)) { in ivtv_dequeue()
66 buf = list_entry(q->list.next, struct ivtv_buffer, list); in ivtv_dequeue()
67 list_del_init(q->list.next); in ivtv_dequeue()
68 q->buffers--; in ivtv_dequeue()
69 q->length -= s->buf_size; in ivtv_dequeue()
70 q->bytesused -= buf->bytesused - buf->readpos; in ivtv_dequeue()
72 spin_unlock_irqrestore(&s->qlock, flags); in ivtv_dequeue()
76 static void ivtv_queue_move_buf(struct ivtv_stream *s, struct ivtv_queue *from, in ivtv_queue_move_buf() argument
79 struct ivtv_buffer *buf = list_entry(from->list.next, struct ivtv_buffer, list); in ivtv_queue_move_buf()
81 list_move_tail(from->list.next, &to->list); in ivtv_queue_move_buf()
82 from->buffers--; in ivtv_queue_move_buf()
83 from->length -= s->buf_size; in ivtv_queue_move_buf()
84 from->bytesused -= buf->bytesused - buf->readpos; in ivtv_queue_move_buf()
87 buf->bytesused = buf->readpos = buf->b_flags = buf->dma_xfer_cnt = 0; in ivtv_queue_move_buf()
88 to->buffers++; in ivtv_queue_move_buf()
89 to->length += s->buf_size; in ivtv_queue_move_buf()
90 to->bytesused += buf->bytesused - buf->readpos; in ivtv_queue_move_buf()
107 -ENOMEM is returned if the buffers could not be obtained, 0 if all
108 buffers where obtained from the 'from' list and if non-zero then
110 int ivtv_queue_move(struct ivtv_stream *s, struct ivtv_queue *from, struct ivtv_queue *steal, in ivtv_queue_move() argument
115 int from_free = from == &s->q_free; in ivtv_queue_move()
116 int to_free = to == &s->q_free; in ivtv_queue_move()
119 spin_lock_irqsave(&s->qlock, flags); in ivtv_queue_move()
122 needed_bytes = from->length; in ivtv_queue_move()
125 bytes_available = from_free ? from->length : from->bytesused; in ivtv_queue_move()
126 bytes_steal = (from_free && steal) ? steal->length : 0; in ivtv_queue_move()
129 spin_unlock_irqrestore(&s->qlock, flags); in ivtv_queue_move()
130 return -ENOMEM; in ivtv_queue_move()
133 struct ivtv_buffer *buf = list_entry(steal->list.prev, struct ivtv_buffer, list); in ivtv_queue_move()
134 u16 dma_xfer_cnt = buf->dma_xfer_cnt; in ivtv_queue_move()
140 while (dma_xfer_cnt == buf->dma_xfer_cnt) { in ivtv_queue_move()
141 list_move_tail(steal->list.prev, &from->list); in ivtv_queue_move()
143 steal->buffers--; in ivtv_queue_move()
144 steal->length -= s->buf_size; in ivtv_queue_move()
145 steal->bytesused -= buf->bytesused - buf->readpos; in ivtv_queue_move()
146 buf->bytesused = buf->readpos = buf->b_flags = buf->dma_xfer_cnt = 0; in ivtv_queue_move()
147 from->buffers++; in ivtv_queue_move()
148 from->length += s->buf_size; in ivtv_queue_move()
149 bytes_available += s->buf_size; in ivtv_queue_move()
150 if (list_empty(&steal->list)) in ivtv_queue_move()
152 buf = list_entry(steal->list.prev, struct ivtv_buffer, list); in ivtv_queue_move()
156 u32 old_length = to->length; in ivtv_queue_move()
158 while (to->length - old_length < needed_bytes) { in ivtv_queue_move()
159 ivtv_queue_move_buf(s, from, to, 1); in ivtv_queue_move()
163 u32 old_bytesused = to->bytesused; in ivtv_queue_move()
165 while (to->bytesused - old_bytesused < needed_bytes) { in ivtv_queue_move()
166 ivtv_queue_move_buf(s, from, to, to_free); in ivtv_queue_move()
169 spin_unlock_irqrestore(&s->qlock, flags); in ivtv_queue_move()
173 void ivtv_flush_queues(struct ivtv_stream *s) in ivtv_flush_queues() argument
175 ivtv_queue_move(s, &s->q_io, NULL, &s->q_free, 0); in ivtv_flush_queues()
176 ivtv_queue_move(s, &s->q_full, NULL, &s->q_free, 0); in ivtv_flush_queues()
177 ivtv_queue_move(s, &s->q_dma, NULL, &s->q_free, 0); in ivtv_flush_queues()
178 ivtv_queue_move(s, &s->q_predma, NULL, &s->q_free, 0); in ivtv_flush_queues()
181 int ivtv_stream_alloc(struct ivtv_stream *s) in ivtv_stream_alloc() argument
183 struct ivtv *itv = s->itv; in ivtv_stream_alloc()
184 int SGsize = sizeof(struct ivtv_sg_host_element) * s->buffers; in ivtv_stream_alloc()
187 if (s->buffers == 0) in ivtv_stream_alloc()
190 IVTV_DEBUG_INFO("Allocate %s%s stream: %d x %d buffers (%dkB total)\n", in ivtv_stream_alloc()
191 s->dma != DMA_NONE ? "DMA " : "", in ivtv_stream_alloc()
192 s->name, s->buffers, s->buf_size, s->buffers * s->buf_size / 1024); in ivtv_stream_alloc()
194 s->sg_pending = kzalloc(SGsize, GFP_KERNEL|__GFP_NOWARN); in ivtv_stream_alloc()
195 if (s->sg_pending == NULL) { in ivtv_stream_alloc()
196 IVTV_ERR("Could not allocate sg_pending for %s stream\n", s->name); in ivtv_stream_alloc()
197 return -ENOMEM; in ivtv_stream_alloc()
199 s->sg_pending_size = 0; in ivtv_stream_alloc()
201 s->sg_processing = kzalloc(SGsize, GFP_KERNEL|__GFP_NOWARN); in ivtv_stream_alloc()
202 if (s->sg_processing == NULL) { in ivtv_stream_alloc()
203 IVTV_ERR("Could not allocate sg_processing for %s stream\n", s->name); in ivtv_stream_alloc()
204 kfree(s->sg_pending); in ivtv_stream_alloc()
205 s->sg_pending = NULL; in ivtv_stream_alloc()
206 return -ENOMEM; in ivtv_stream_alloc()
208 s->sg_processing_size = 0; in ivtv_stream_alloc()
210 s->sg_dma = kzalloc(sizeof(struct ivtv_sg_element), in ivtv_stream_alloc()
212 if (s->sg_dma == NULL) { in ivtv_stream_alloc()
213 IVTV_ERR("Could not allocate sg_dma for %s stream\n", s->name); in ivtv_stream_alloc()
214 kfree(s->sg_pending); in ivtv_stream_alloc()
215 s->sg_pending = NULL; in ivtv_stream_alloc()
216 kfree(s->sg_processing); in ivtv_stream_alloc()
217 s->sg_processing = NULL; in ivtv_stream_alloc()
218 return -ENOMEM; in ivtv_stream_alloc()
220 if (ivtv_might_use_dma(s)) { in ivtv_stream_alloc()
221 s->sg_handle = dma_map_single(&itv->pdev->dev, s->sg_dma, in ivtv_stream_alloc()
224 ivtv_stream_sync_for_cpu(s); in ivtv_stream_alloc()
228 for (i = 0; i < s->buffers; i++) { in ivtv_stream_alloc()
234 buf->buf = kmalloc(s->buf_size + 256, GFP_KERNEL|__GFP_NOWARN); in ivtv_stream_alloc()
235 if (buf->buf == NULL) { in ivtv_stream_alloc()
239 INIT_LIST_HEAD(&buf->list); in ivtv_stream_alloc()
240 if (ivtv_might_use_dma(s)) { in ivtv_stream_alloc()
241 buf->dma_handle = dma_map_single(&s->itv->pdev->dev, in ivtv_stream_alloc()
242 buf->buf, s->buf_size + 256, s->dma); in ivtv_stream_alloc()
243 ivtv_buf_sync_for_cpu(s, buf); in ivtv_stream_alloc()
245 ivtv_enqueue(s, buf, &s->q_free); in ivtv_stream_alloc()
247 if (i == s->buffers) in ivtv_stream_alloc()
249 IVTV_ERR("Couldn't allocate buffers for %s stream\n", s->name); in ivtv_stream_alloc()
250 ivtv_stream_free(s); in ivtv_stream_alloc()
251 return -ENOMEM; in ivtv_stream_alloc()
254 void ivtv_stream_free(struct ivtv_stream *s) in ivtv_stream_free() argument
259 ivtv_flush_queues(s); in ivtv_stream_free()
262 while ((buf = ivtv_dequeue(s, &s->q_free))) { in ivtv_stream_free()
263 if (ivtv_might_use_dma(s)) in ivtv_stream_free()
264 dma_unmap_single(&s->itv->pdev->dev, buf->dma_handle, in ivtv_stream_free()
265 s->buf_size + 256, s->dma); in ivtv_stream_free()
266 kfree(buf->buf); in ivtv_stream_free()
271 if (s->sg_dma != NULL) { in ivtv_stream_free()
272 if (s->sg_handle != IVTV_DMA_UNMAPPED) { in ivtv_stream_free()
273 dma_unmap_single(&s->itv->pdev->dev, s->sg_handle, in ivtv_stream_free()
276 s->sg_handle = IVTV_DMA_UNMAPPED; in ivtv_stream_free()
278 kfree(s->sg_pending); in ivtv_stream_free()
279 kfree(s->sg_processing); in ivtv_stream_free()
280 kfree(s->sg_dma); in ivtv_stream_free()
281 s->sg_pending = NULL; in ivtv_stream_free()
282 s->sg_processing = NULL; in ivtv_stream_free()
283 s->sg_dma = NULL; in ivtv_stream_free()
284 s->sg_pending_size = 0; in ivtv_stream_free()
285 s->sg_processing_size = 0; in ivtv_stream_free()