drivers/iio/buffer/industrialio-buffer-dma.c

Source file repositories/reference/linux-study-clean/drivers/iio/buffer/industrialio-buffer-dma.c

File Facts

System
Linux kernel
Corpus path
drivers/iio/buffer/industrialio-buffer-dma.c
Extension
.c
Size
26377 bytes
Lines
876
Domain
Driver Families
Bucket
drivers/iio
Inferred role
Driver Families: exported/initcall integration point
Status
integration 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

list_for_each_entry_safe(block, _block, list, head) {
			list_del(&block->head);
			block->bytes_used = 0;
			_iio_dma_buffer_block_done(block);

			if (!block->fileio)
				iio_buffer_signal_dmabuf_done(block->fence,
							      -EINTR);
			iio_buffer_block_put_atomic(block);
		}
	}

	if (queue->fileio.enabled)
		queue->fileio.enabled = false;

	iio_dma_buffer_queue_wake(queue);
	dma_fence_end_signalling(cookie);
}
EXPORT_SYMBOL_NS_GPL(iio_dma_buffer_block_list_abort, "IIO_DMA_BUFFER");

static bool iio_dma_block_reusable(struct iio_dma_buffer_block *block)
{
	/*
	 * If the core owns the block it can be re-used. This should be the
	 * default case when enabling the buffer, unless the DMA controller does
	 * not support abort and has not given back the block yet.
	 */
	switch (block->state) {
	case IIO_BLOCK_STATE_QUEUED:
	case IIO_BLOCK_STATE_DONE:
		return true;
	default:
		return false;
	}
}

static bool iio_dma_buffer_can_use_fileio(struct iio_dma_buffer_queue *queue)
{
	/*
	 * Note that queue->num_dmabufs cannot increase while the queue is
	 * locked, it can only decrease, so it does not race against
	 * iio_dma_buffer_alloc_block().
	 */
	return queue->fileio.enabled || !atomic_read(&queue->num_dmabufs);
}

/**
 * iio_dma_buffer_request_update() - DMA buffer request_update callback
 * @buffer: The buffer which to request an update
 *
 * Should be used as the iio_dma_buffer_request_update() callback for
 * iio_buffer_access_ops struct for DMA buffers.
 */
int iio_dma_buffer_request_update(struct iio_buffer *buffer)
{
	struct iio_dma_buffer_queue *queue = iio_buffer_to_queue(buffer);
	struct iio_dma_buffer_block *block;
	bool try_reuse = false;
	size_t size;
	int i;

	/*
	 * Split the buffer into two even parts. This is used as a double
	 * buffering scheme with usually one block at a time being used by the
	 * DMA and the other one by the application.
	 */
	size = DIV_ROUND_UP(queue->buffer.bytes_per_datum *
		queue->buffer.length, 2);

	guard(mutex)(&queue->lock);

	queue->fileio.enabled = iio_dma_buffer_can_use_fileio(queue);

	/* If DMABUFs were created, disable fileio interface */
	if (!queue->fileio.enabled)
		return 0;

	/* Allocations are page aligned */
	if (PAGE_ALIGN(queue->fileio.block_size) == PAGE_ALIGN(size))
		try_reuse = true;

	queue->fileio.block_size = size;
	queue->fileio.active_block = NULL;

	scoped_guard(spinlock_irq, &queue->list_lock) {
		for (i = 0; i < ARRAY_SIZE(queue->fileio.blocks); i++) {
			block = queue->fileio.blocks[i];

			/* If we can't re-use it free it */
			if (block && (!iio_dma_block_reusable(block) || !try_reuse))

Annotation

Implementation Notes