11a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil/*
21a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil    buffer queues.
31a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil    Copyright (C) 2003-2004  Kevin Thayer <nufan_wfk at yahoo.com>
41a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil    Copyright (C) 2004  Chris Kennedy <c@groovy.org>
51a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil    Copyright (C) 2005-2007  Hans Verkuil <hverkuil@xs4all.nl>
61a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil
71a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil    This program is free software; you can redistribute it and/or modify
81a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil    it under the terms of the GNU General Public License as published by
91a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil    the Free Software Foundation; either version 2 of the License, or
101a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil    (at your option) any later version.
111a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil
121a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil    This program is distributed in the hope that it will be useful,
131a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil    but WITHOUT ANY WARRANTY; without even the implied warranty of
141a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
151a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil    GNU General Public License for more details.
161a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil
171a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil    You should have received a copy of the GNU General Public License
181a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil    along with this program; if not, write to the Free Software
191a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
201a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil */
211a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil
221a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil#include "ivtv-driver.h"
231a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil#include "ivtv-queue.h"
241a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil
251a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuilint ivtv_buf_copy_from_user(struct ivtv_stream *s, struct ivtv_buffer *buf, const char __user *src, int copybytes)
261a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil{
271a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil	if (s->buf_size - buf->bytesused < copybytes)
281a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil		copybytes = s->buf_size - buf->bytesused;
291a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil	if (copy_from_user(buf->buf + buf->bytesused, src, copybytes)) {
301a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil		return -EFAULT;
311a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil	}
321a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil	buf->bytesused += copybytes;
331a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil	return copybytes;
341a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil}
351a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil
361a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuilvoid ivtv_buf_swap(struct ivtv_buffer *buf)
371a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil{
381a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil	int i;
391a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil
401a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil	for (i = 0; i < buf->bytesused; i += 4)
411a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil		swab32s((u32 *)(buf->buf + i));
421a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil}
431a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil
441a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuilvoid ivtv_queue_init(struct ivtv_queue *q)
451a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil{
461a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil	INIT_LIST_HEAD(&q->list);
471a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil	q->buffers = 0;
481a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil	q->length = 0;
491a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil	q->bytesused = 0;
501a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil}
511a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil
521a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuilvoid ivtv_enqueue(struct ivtv_stream *s, struct ivtv_buffer *buf, struct ivtv_queue *q)
531a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil{
547daa4a8897e79911f524ddac065adea05c7e9b16Guennadi Liakhovetski	unsigned long flags;
551a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil
561a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil	/* clear the buffer if it is going to be enqueued to the free queue */
571a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil	if (q == &s->q_free) {
581a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil		buf->bytesused = 0;
591a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil		buf->readpos = 0;
601a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil		buf->b_flags = 0;
61f4071b85ea0ca3bd06f63c330562b4cfdffa8473Hans Verkuil		buf->dma_xfer_cnt = 0;
621a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil	}
631a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil	spin_lock_irqsave(&s->qlock, flags);
641a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil	list_add_tail(&buf->list, &q->list);
651a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil	q->buffers++;
661a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil	q->length += s->buf_size;
671a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil	q->bytesused += buf->bytesused - buf->readpos;
681a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil	spin_unlock_irqrestore(&s->qlock, flags);
691a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil}
701a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil
711a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuilstruct ivtv_buffer *ivtv_dequeue(struct ivtv_stream *s, struct ivtv_queue *q)
721a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil{
731a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil	struct ivtv_buffer *buf = NULL;
747daa4a8897e79911f524ddac065adea05c7e9b16Guennadi Liakhovetski	unsigned long flags;
751a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil
761a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil	spin_lock_irqsave(&s->qlock, flags);
771a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil	if (!list_empty(&q->list)) {
781a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil		buf = list_entry(q->list.next, struct ivtv_buffer, list);
791a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil		list_del_init(q->list.next);
801a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil		q->buffers--;
811a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil		q->length -= s->buf_size;
821a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil		q->bytesused -= buf->bytesused - buf->readpos;
831a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil	}
841a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil	spin_unlock_irqrestore(&s->qlock, flags);
851a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil	return buf;
861a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil}
871a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil
881a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuilstatic void ivtv_queue_move_buf(struct ivtv_stream *s, struct ivtv_queue *from,
89f4071b85ea0ca3bd06f63c330562b4cfdffa8473Hans Verkuil		struct ivtv_queue *to, int clear)
901a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil{
911a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil	struct ivtv_buffer *buf = list_entry(from->list.next, struct ivtv_buffer, list);
921a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil
931a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil	list_move_tail(from->list.next, &to->list);
941a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil	from->buffers--;
951a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil	from->length -= s->buf_size;
961a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil	from->bytesused -= buf->bytesused - buf->readpos;
971a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil	/* special handling for q_free */
981a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil	if (clear)
99f4071b85ea0ca3bd06f63c330562b4cfdffa8473Hans Verkuil		buf->bytesused = buf->readpos = buf->b_flags = buf->dma_xfer_cnt = 0;
1001a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil	to->buffers++;
1011a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil	to->length += s->buf_size;
1021a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil	to->bytesused += buf->bytesused - buf->readpos;
1031a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil}
1041a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil
1051a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil/* Move 'needed_bytes' worth of buffers from queue 'from' into queue 'to'.
1061a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil   If 'needed_bytes' == 0, then move all buffers from 'from' into 'to'.
1071a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil   If 'steal' != NULL, then buffers may also taken from that queue if
108f4071b85ea0ca3bd06f63c330562b4cfdffa8473Hans Verkuil   needed, but only if 'from' is the free queue.
1091a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil
1101a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil   The buffer is automatically cleared if it goes to the free queue. It is
1111a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil   also cleared if buffers need to be taken from the 'steal' queue and
1121a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil   the 'from' queue is the free queue.
1131a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil
1141a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil   When 'from' is q_free, then needed_bytes is compared to the total
1151a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil   available buffer length, otherwise needed_bytes is compared to the
1161a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil   bytesused value. For the 'steal' queue the total available buffer
1171a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil   length is always used.
1181a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil
1191a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil   -ENOMEM is returned if the buffers could not be obtained, 0 if all
1201a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil   buffers where obtained from the 'from' list and if non-zero then
1211a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil   the number of stolen buffers is returned. */
1221a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuilint ivtv_queue_move(struct ivtv_stream *s, struct ivtv_queue *from, struct ivtv_queue *steal,
1231a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil		    struct ivtv_queue *to, int needed_bytes)
1241a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil{
1251a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil	unsigned long flags;
1261a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil	int rc = 0;
1271a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil	int from_free = from == &s->q_free;
1281a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil	int to_free = to == &s->q_free;
129f4071b85ea0ca3bd06f63c330562b4cfdffa8473Hans Verkuil	int bytes_available, bytes_steal;
1301a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil
1311a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil	spin_lock_irqsave(&s->qlock, flags);
1321a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil	if (needed_bytes == 0) {
1331a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil		from_free = 1;
1341a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil		needed_bytes = from->length;
1351a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil	}
1361a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil
1371a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil	bytes_available = from_free ? from->length : from->bytesused;
138f4071b85ea0ca3bd06f63c330562b4cfdffa8473Hans Verkuil	bytes_steal = (from_free && steal) ? steal->length : 0;
1391a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil
140f4071b85ea0ca3bd06f63c330562b4cfdffa8473Hans Verkuil	if (bytes_available + bytes_steal < needed_bytes) {
1411a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil		spin_unlock_irqrestore(&s->qlock, flags);
1421a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil		return -ENOMEM;
1431a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil	}
144f4071b85ea0ca3bd06f63c330562b4cfdffa8473Hans Verkuil	while (bytes_available < needed_bytes) {
145f4071b85ea0ca3bd06f63c330562b4cfdffa8473Hans Verkuil		struct ivtv_buffer *buf = list_entry(steal->list.prev, struct ivtv_buffer, list);
146f4071b85ea0ca3bd06f63c330562b4cfdffa8473Hans Verkuil		u16 dma_xfer_cnt = buf->dma_xfer_cnt;
147f4071b85ea0ca3bd06f63c330562b4cfdffa8473Hans Verkuil
148f4071b85ea0ca3bd06f63c330562b4cfdffa8473Hans Verkuil		/* move buffers from the tail of the 'steal' queue to the tail of the
149f4071b85ea0ca3bd06f63c330562b4cfdffa8473Hans Verkuil		   'from' queue. Always copy all the buffers with the same dma_xfer_cnt
150f4071b85ea0ca3bd06f63c330562b4cfdffa8473Hans Verkuil		   value, this ensures that you do not end up with partial frame data
151f4071b85ea0ca3bd06f63c330562b4cfdffa8473Hans Verkuil		   if one frame is stored in multiple buffers. */
152f4071b85ea0ca3bd06f63c330562b4cfdffa8473Hans Verkuil		while (dma_xfer_cnt == buf->dma_xfer_cnt) {
153f4071b85ea0ca3bd06f63c330562b4cfdffa8473Hans Verkuil			list_move_tail(steal->list.prev, &from->list);
154f4071b85ea0ca3bd06f63c330562b4cfdffa8473Hans Verkuil			rc++;
155f4071b85ea0ca3bd06f63c330562b4cfdffa8473Hans Verkuil			steal->buffers--;
156f4071b85ea0ca3bd06f63c330562b4cfdffa8473Hans Verkuil			steal->length -= s->buf_size;
157f4071b85ea0ca3bd06f63c330562b4cfdffa8473Hans Verkuil			steal->bytesused -= buf->bytesused - buf->readpos;
158f4071b85ea0ca3bd06f63c330562b4cfdffa8473Hans Verkuil			buf->bytesused = buf->readpos = buf->b_flags = buf->dma_xfer_cnt = 0;
159f4071b85ea0ca3bd06f63c330562b4cfdffa8473Hans Verkuil			from->buffers++;
160f4071b85ea0ca3bd06f63c330562b4cfdffa8473Hans Verkuil			from->length += s->buf_size;
161f4071b85ea0ca3bd06f63c330562b4cfdffa8473Hans Verkuil			bytes_available += s->buf_size;
162f4071b85ea0ca3bd06f63c330562b4cfdffa8473Hans Verkuil			if (list_empty(&steal->list))
163f4071b85ea0ca3bd06f63c330562b4cfdffa8473Hans Verkuil				break;
164f4071b85ea0ca3bd06f63c330562b4cfdffa8473Hans Verkuil			buf = list_entry(steal->list.prev, struct ivtv_buffer, list);
165f4071b85ea0ca3bd06f63c330562b4cfdffa8473Hans Verkuil		}
166f4071b85ea0ca3bd06f63c330562b4cfdffa8473Hans Verkuil	}
1671a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil	if (from_free) {
1681a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil		u32 old_length = to->length;
1691a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil
1701a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil		while (to->length - old_length < needed_bytes) {
171f4071b85ea0ca3bd06f63c330562b4cfdffa8473Hans Verkuil			ivtv_queue_move_buf(s, from, to, 1);
1721a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil		}
1731a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil	}
1741a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil	else {
1751a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil		u32 old_bytesused = to->bytesused;
1761a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil
1771a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil		while (to->bytesused - old_bytesused < needed_bytes) {
178f4071b85ea0ca3bd06f63c330562b4cfdffa8473Hans Verkuil			ivtv_queue_move_buf(s, from, to, to_free);
1791a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil		}
1801a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil	}
1811a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil	spin_unlock_irqrestore(&s->qlock, flags);
1821a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil	return rc;
1831a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil}
1841a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil
1851a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuilvoid ivtv_flush_queues(struct ivtv_stream *s)
1861a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil{
1871a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil	ivtv_queue_move(s, &s->q_io, NULL, &s->q_free, 0);
1881a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil	ivtv_queue_move(s, &s->q_full, NULL, &s->q_free, 0);
1891a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil	ivtv_queue_move(s, &s->q_dma, NULL, &s->q_free, 0);
1901a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil	ivtv_queue_move(s, &s->q_predma, NULL, &s->q_free, 0);
1911a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil}
1921a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil
1931a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuilint ivtv_stream_alloc(struct ivtv_stream *s)
1941a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil{
1951a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil	struct ivtv *itv = s->itv;
196b0510f8dc73dce56f35337487c6374ae84b15446Al Viro	int SGsize = sizeof(struct ivtv_sg_host_element) * s->buffers;
1971a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil	int i;
1981a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil
1991a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil	if (s->buffers == 0)
2001a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil		return 0;
2011a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil
2021a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil	IVTV_DEBUG_INFO("Allocate %s%s stream: %d x %d buffers (%dkB total)\n",
2031a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil		s->dma != PCI_DMA_NONE ? "DMA " : "",
2041a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil		s->name, s->buffers, s->buf_size, s->buffers * s->buf_size / 1024);
2051a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil
2063f98387efa9333c5765d36e144c47c107d6ba64aHans Verkuil	s->sg_pending = kzalloc(SGsize, GFP_KERNEL|__GFP_NOWARN);
20737093b1ea600d84fbf7252baf12eedec85ae40f1Hans Verkuil	if (s->sg_pending == NULL) {
20837093b1ea600d84fbf7252baf12eedec85ae40f1Hans Verkuil		IVTV_ERR("Could not allocate sg_pending for %s stream\n", s->name);
20937093b1ea600d84fbf7252baf12eedec85ae40f1Hans Verkuil		return -ENOMEM;
210dc02d50a6d71cba2b2edb78377af5a5965879a49Hans Verkuil	}
21137093b1ea600d84fbf7252baf12eedec85ae40f1Hans Verkuil	s->sg_pending_size = 0;
212dc02d50a6d71cba2b2edb78377af5a5965879a49Hans Verkuil
2133f98387efa9333c5765d36e144c47c107d6ba64aHans Verkuil	s->sg_processing = kzalloc(SGsize, GFP_KERNEL|__GFP_NOWARN);
21437093b1ea600d84fbf7252baf12eedec85ae40f1Hans Verkuil	if (s->sg_processing == NULL) {
21537093b1ea600d84fbf7252baf12eedec85ae40f1Hans Verkuil		IVTV_ERR("Could not allocate sg_processing for %s stream\n", s->name);
21637093b1ea600d84fbf7252baf12eedec85ae40f1Hans Verkuil		kfree(s->sg_pending);
21737093b1ea600d84fbf7252baf12eedec85ae40f1Hans Verkuil		s->sg_pending = NULL;
21837093b1ea600d84fbf7252baf12eedec85ae40f1Hans Verkuil		return -ENOMEM;
21937093b1ea600d84fbf7252baf12eedec85ae40f1Hans Verkuil	}
22037093b1ea600d84fbf7252baf12eedec85ae40f1Hans Verkuil	s->sg_processing_size = 0;
22137093b1ea600d84fbf7252baf12eedec85ae40f1Hans Verkuil
2223f98387efa9333c5765d36e144c47c107d6ba64aHans Verkuil	s->sg_dma = kzalloc(sizeof(struct ivtv_sg_element),
2233f98387efa9333c5765d36e144c47c107d6ba64aHans Verkuil					GFP_KERNEL|__GFP_NOWARN);
22437093b1ea600d84fbf7252baf12eedec85ae40f1Hans Verkuil	if (s->sg_dma == NULL) {
22537093b1ea600d84fbf7252baf12eedec85ae40f1Hans Verkuil		IVTV_ERR("Could not allocate sg_dma for %s stream\n", s->name);
22637093b1ea600d84fbf7252baf12eedec85ae40f1Hans Verkuil		kfree(s->sg_pending);
22737093b1ea600d84fbf7252baf12eedec85ae40f1Hans Verkuil		s->sg_pending = NULL;
22837093b1ea600d84fbf7252baf12eedec85ae40f1Hans Verkuil		kfree(s->sg_processing);
22937093b1ea600d84fbf7252baf12eedec85ae40f1Hans Verkuil		s->sg_processing = NULL;
230dc02d50a6d71cba2b2edb78377af5a5965879a49Hans Verkuil		return -ENOMEM;
231dc02d50a6d71cba2b2edb78377af5a5965879a49Hans Verkuil	}
232dc02d50a6d71cba2b2edb78377af5a5965879a49Hans Verkuil	if (ivtv_might_use_dma(s)) {
233e9e10124e269a39de089c5e0d9936fae2ff889b2Alan Cox		s->sg_handle = pci_map_single(itv->pdev, s->sg_dma,
234e9e10124e269a39de089c5e0d9936fae2ff889b2Alan Cox				sizeof(struct ivtv_sg_element), PCI_DMA_TODEVICE);
2351a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil		ivtv_stream_sync_for_cpu(s);
2361a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil	}
2371a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil
2381a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil	/* allocate stream buffers. Initially all buffers are in q_free. */
2391a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil	for (i = 0; i < s->buffers; i++) {
2403f98387efa9333c5765d36e144c47c107d6ba64aHans Verkuil		struct ivtv_buffer *buf = kzalloc(sizeof(struct ivtv_buffer),
2413f98387efa9333c5765d36e144c47c107d6ba64aHans Verkuil						GFP_KERNEL|__GFP_NOWARN);
2421a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil
2431a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil		if (buf == NULL)
2441a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil			break;
2453f98387efa9333c5765d36e144c47c107d6ba64aHans Verkuil		buf->buf = kmalloc(s->buf_size + 256, GFP_KERNEL|__GFP_NOWARN);
2461a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil		if (buf->buf == NULL) {
2471a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil			kfree(buf);
2481a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil			break;
2491a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil		}
2501a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil		INIT_LIST_HEAD(&buf->list);
251dc02d50a6d71cba2b2edb78377af5a5965879a49Hans Verkuil		if (ivtv_might_use_dma(s)) {
2528ac05ae3192ce8a71fc84e4a88772cce0c09173cHans Verkuil			buf->dma_handle = pci_map_single(s->itv->pdev,
2531a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil				buf->buf, s->buf_size + 256, s->dma);
2541a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil			ivtv_buf_sync_for_cpu(s, buf);
2551a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil		}
2561a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil		ivtv_enqueue(s, buf, &s->q_free);
2571a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil	}
2581a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil	if (i == s->buffers)
2591a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil		return 0;
2601a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil	IVTV_ERR("Couldn't allocate buffers for %s stream\n", s->name);
2611a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil	ivtv_stream_free(s);
2621a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil	return -ENOMEM;
2631a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil}
2641a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil
2651a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuilvoid ivtv_stream_free(struct ivtv_stream *s)
2661a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil{
2671a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil	struct ivtv_buffer *buf;
2681a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil
2691a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil	/* move all buffers to q_free */
2701a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil	ivtv_flush_queues(s);
2711a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil
2721a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil	/* empty q_free */
2731a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil	while ((buf = ivtv_dequeue(s, &s->q_free))) {
274dc02d50a6d71cba2b2edb78377af5a5965879a49Hans Verkuil		if (ivtv_might_use_dma(s))
2758ac05ae3192ce8a71fc84e4a88772cce0c09173cHans Verkuil			pci_unmap_single(s->itv->pdev, buf->dma_handle,
2761a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil				s->buf_size + 256, s->dma);
2771a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil		kfree(buf->buf);
2781a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil		kfree(buf);
2791a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil	}
2801a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil
2811a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil	/* Free SG Array/Lists */
28237093b1ea600d84fbf7252baf12eedec85ae40f1Hans Verkuil	if (s->sg_dma != NULL) {
28337093b1ea600d84fbf7252baf12eedec85ae40f1Hans Verkuil		if (s->sg_handle != IVTV_DMA_UNMAPPED) {
2848ac05ae3192ce8a71fc84e4a88772cce0c09173cHans Verkuil			pci_unmap_single(s->itv->pdev, s->sg_handle,
28537093b1ea600d84fbf7252baf12eedec85ae40f1Hans Verkuil				 sizeof(struct ivtv_sg_element), PCI_DMA_TODEVICE);
28637093b1ea600d84fbf7252baf12eedec85ae40f1Hans Verkuil			s->sg_handle = IVTV_DMA_UNMAPPED;
2871a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil		}
28837093b1ea600d84fbf7252baf12eedec85ae40f1Hans Verkuil		kfree(s->sg_pending);
28937093b1ea600d84fbf7252baf12eedec85ae40f1Hans Verkuil		kfree(s->sg_processing);
29037093b1ea600d84fbf7252baf12eedec85ae40f1Hans Verkuil		kfree(s->sg_dma);
29137093b1ea600d84fbf7252baf12eedec85ae40f1Hans Verkuil		s->sg_pending = NULL;
29237093b1ea600d84fbf7252baf12eedec85ae40f1Hans Verkuil		s->sg_processing = NULL;
29337093b1ea600d84fbf7252baf12eedec85ae40f1Hans Verkuil		s->sg_dma = NULL;
29437093b1ea600d84fbf7252baf12eedec85ae40f1Hans Verkuil		s->sg_pending_size = 0;
29537093b1ea600d84fbf7252baf12eedec85ae40f1Hans Verkuil		s->sg_processing_size = 0;
2961a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil	}
2971a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil}
298