drivers/iio/buffer/industrialio-buffer-dmaengine.c
Source file repositories/reference/linux-study-clean/drivers/iio/buffer/industrialio-buffer-dmaengine.c
File Facts
- System
- Linux kernel
- Corpus path
drivers/iio/buffer/industrialio-buffer-dmaengine.c- Extension
.c- Size
- 12553 bytes
- Lines
- 424
- 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.
- 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.
- Exports symbols or registers init work; inspect boot/module ordering and who consumes the exported contract.
- Allocates kernel memory; connect allocation flags and lifetime to context constraints.
- Defines or uses C structs; map object ownership, embedded links, reference counts, and lock ownership.
Dependency Surface
linux/slab.hlinux/kernel.hlinux/cleanup.hlinux/dmaengine.hlinux/dma-mapping.hlinux/spinlock.hlinux/err.hlinux/module.hlinux/iio/iio.hlinux/iio/sysfs.hlinux/iio/buffer.hlinux/iio/buffer_impl.hlinux/iio/buffer-dma.hlinux/iio/buffer-dmaengine.h
Detected Declarations
struct dmaengine_bufferfunction iio_dmaengine_buffer_block_donefunction iio_dmaengine_buffer_submit_blockfunction iio_dmaengine_buffer_abortfunction iio_dmaengine_buffer_releasefunction iio_dmaengine_buffer_get_length_alignfunction iio_dmaengine_buffer_allocfunction iio_dmaengine_buffer_freefunction iio_dmaengine_buffer_teardownfunction iio_dmaengine_buffer_setup_extfunction devm_iio_dmaengine_buffer_teardownfunction devm_iio_dmaengine_buffer_setup_extfunction devm_iio_dmaengine_buffer_freefunction devm_iio_dmaengine_buffer_setup_with_handle
Annotated Snippet
struct dmaengine_buffer {
struct iio_dma_buffer_queue queue;
struct dma_chan *chan;
struct list_head active;
size_t align;
size_t max_size;
};
static struct dmaengine_buffer *iio_buffer_to_dmaengine_buffer(struct iio_buffer *buffer)
{
return container_of(buffer, struct dmaengine_buffer, queue.buffer);
}
static void iio_dmaengine_buffer_block_done(void *data,
const struct dmaengine_result *result)
{
struct iio_dma_buffer_block *block = data;
scoped_guard(spinlock_irqsave, &block->queue->list_lock)
list_del(&block->head);
block->bytes_used -= result->residue;
iio_dma_buffer_block_done(block);
}
static int iio_dmaengine_buffer_submit_block(struct iio_dma_buffer_queue *queue,
struct iio_dma_buffer_block *block)
{
struct dmaengine_buffer *dmaengine_buffer =
iio_buffer_to_dmaengine_buffer(&queue->buffer);
struct dma_async_tx_descriptor *desc;
enum dma_transfer_direction dma_dir;
struct scatterlist *sgl;
struct dma_vec *vecs;
size_t max_size;
dma_cookie_t cookie;
size_t len_total;
unsigned int i;
int nents;
max_size = min(block->size, dmaengine_buffer->max_size);
max_size = round_down(max_size, dmaengine_buffer->align);
if (queue->buffer.direction == IIO_BUFFER_DIRECTION_IN)
dma_dir = DMA_DEV_TO_MEM;
else
dma_dir = DMA_MEM_TO_DEV;
if (block->sg_table) {
sgl = block->sg_table->sgl;
nents = sg_nents_for_len(sgl, block->bytes_used);
if (nents < 0)
return nents;
vecs = kmalloc_array(nents, sizeof(*vecs), GFP_ATOMIC);
if (!vecs)
return -ENOMEM;
len_total = block->bytes_used;
for (i = 0; i < nents; i++) {
vecs[i].addr = sg_dma_address(sgl);
vecs[i].len = min(sg_dma_len(sgl), len_total);
len_total -= vecs[i].len;
sgl = sg_next(sgl);
}
desc = dmaengine_prep_peripheral_dma_vec(dmaengine_buffer->chan,
vecs, nents, dma_dir,
DMA_PREP_INTERRUPT);
kfree(vecs);
} else {
max_size = min(block->size, dmaengine_buffer->max_size);
max_size = round_down(max_size, dmaengine_buffer->align);
if (queue->buffer.direction == IIO_BUFFER_DIRECTION_IN)
block->bytes_used = max_size;
if (!block->bytes_used || block->bytes_used > max_size)
return -EINVAL;
desc = dmaengine_prep_slave_single(dmaengine_buffer->chan,
block->phys_addr,
block->bytes_used,
dma_dir,
DMA_PREP_INTERRUPT);
}
if (!desc)
Annotation
- Immediate include surface: `linux/slab.h`, `linux/kernel.h`, `linux/cleanup.h`, `linux/dmaengine.h`, `linux/dma-mapping.h`, `linux/spinlock.h`, `linux/err.h`, `linux/module.h`.
- Detected declarations: `struct dmaengine_buffer`, `function iio_dmaengine_buffer_block_done`, `function iio_dmaengine_buffer_submit_block`, `function iio_dmaengine_buffer_abort`, `function iio_dmaengine_buffer_release`, `function iio_dmaengine_buffer_get_length_align`, `function iio_dmaengine_buffer_alloc`, `function iio_dmaengine_buffer_free`, `function iio_dmaengine_buffer_teardown`, `function iio_dmaengine_buffer_setup_ext`.
- Atlas domain: Driver Families / drivers/iio.
- Implementation status: integration implementation candidate.
Implementation Notes
- This generated page is the file-by-file coverage layer; curated subsystem chapters should link here when they synthesize a multi-file control flow.
- Core OS pages should be promoted from atlas-only to deep-reviewed when they explain data structures, invariants, locking, lifecycle, and C implementation snippets.
- Driver-family pages are intentionally pattern-oriented unless they are part of the selected PCIe/NVMe representative device path.