drivers/media/pci/ivtv/ivtv-queue.c

Source file repositories/reference/linux-study-clean/drivers/media/pci/ivtv/ivtv-queue.c

File Facts

System
Linux kernel
Corpus path
drivers/media/pci/ivtv/ivtv-queue.c
Extension
.c
Size
8379 bytes
Lines
288
Domain
Driver Families
Bucket
drivers/media
Inferred role
Driver Families: implementation source
Status
source implementation candidate

Why This File Exists

Repeatable hardware-adapter layer. Deep compatibility for every driver is out of scope; this atlas records patterns, probe lifecycles, bus glue, IRQ/DMA usage, and links back to core abstractions.

Dependency Surface

Detected Declarations

Annotated Snippet

while (dma_xfer_cnt == buf->dma_xfer_cnt) {
			list_move_tail(steal->list.prev, &from->list);
			rc++;
			steal->buffers--;
			steal->length -= s->buf_size;
			steal->bytesused -= buf->bytesused - buf->readpos;
			buf->bytesused = buf->readpos = buf->b_flags = buf->dma_xfer_cnt = 0;
			from->buffers++;
			from->length += s->buf_size;
			bytes_available += s->buf_size;
			if (list_empty(&steal->list))
				break;
			buf = list_entry(steal->list.prev, struct ivtv_buffer, list);
		}
	}
	if (from_free) {
		u32 old_length = to->length;

		while (to->length - old_length < needed_bytes) {
			ivtv_queue_move_buf(s, from, to, 1);
		}
	}
	else {
		u32 old_bytesused = to->bytesused;

		while (to->bytesused - old_bytesused < needed_bytes) {
			ivtv_queue_move_buf(s, from, to, to_free);
		}
	}
	spin_unlock_irqrestore(&s->qlock, flags);
	return rc;
}

void ivtv_flush_queues(struct ivtv_stream *s)
{
	ivtv_queue_move(s, &s->q_io, NULL, &s->q_free, 0);
	ivtv_queue_move(s, &s->q_full, NULL, &s->q_free, 0);
	ivtv_queue_move(s, &s->q_dma, NULL, &s->q_free, 0);
	ivtv_queue_move(s, &s->q_predma, NULL, &s->q_free, 0);
}

int ivtv_stream_alloc(struct ivtv_stream *s)
{
	struct ivtv *itv = s->itv;
	int SGsize = sizeof(struct ivtv_sg_host_element) * s->buffers;
	int i;

	if (s->buffers == 0)
		return 0;

	IVTV_DEBUG_INFO("Allocate %s%s stream: %d x %d buffers (%dkB total)\n",
		s->dma != DMA_NONE ? "DMA " : "",
		s->name, s->buffers, s->buf_size, s->buffers * s->buf_size / 1024);

	s->sg_pending = kzalloc(SGsize, GFP_KERNEL|__GFP_NOWARN);
	if (s->sg_pending == NULL) {
		IVTV_ERR("Could not allocate sg_pending for %s stream\n", s->name);
		return -ENOMEM;
	}
	s->sg_pending_size = 0;

	s->sg_processing = kzalloc(SGsize, GFP_KERNEL|__GFP_NOWARN);
	if (s->sg_processing == NULL) {
		IVTV_ERR("Could not allocate sg_processing for %s stream\n", s->name);
		kfree(s->sg_pending);
		s->sg_pending = NULL;
		return -ENOMEM;
	}
	s->sg_processing_size = 0;

	s->sg_dma = kzalloc_obj(struct ivtv_sg_element,
				GFP_KERNEL | __GFP_NOWARN);
	if (s->sg_dma == NULL) {
		IVTV_ERR("Could not allocate sg_dma for %s stream\n", s->name);
		kfree(s->sg_pending);
		s->sg_pending = NULL;
		kfree(s->sg_processing);
		s->sg_processing = NULL;
		return -ENOMEM;
	}
	if (ivtv_might_use_dma(s)) {
		s->sg_handle = dma_map_single(&itv->pdev->dev, s->sg_dma,
					      sizeof(struct ivtv_sg_element),
					      DMA_TO_DEVICE);
		ivtv_stream_sync_for_cpu(s);
	}

	/* allocate stream buffers. Initially all buffers are in q_free. */
	for (i = 0; i < s->buffers; i++) {
		struct ivtv_buffer *buf = kzalloc_obj(struct ivtv_buffer,

Annotation

Implementation Notes