drivers/dma/nbpfaxi.c

Source file repositories/reference/linux-study-clean/drivers/dma/nbpfaxi.c

File Facts

System
Linux kernel
Corpus path
drivers/dma/nbpfaxi.c
Extension
.c
Size
41529 bytes
Lines
1536
Domain
Driver Families
Bucket
drivers/dma
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

struct nbpf_config {
	int num_channels;
	int buffer_size;
};

/*
 * We've got 3 types of objects, used to describe DMA transfers:
 * 1. high-level descriptor, containing a struct dma_async_tx_descriptor object
 *	in it, used to communicate with the user
 * 2. hardware DMA link descriptors, that we pass to DMAC for DMA transfer
 *	queuing, these must be DMAable, using either the streaming DMA API or
 *	allocated from coherent memory - one per SG segment
 * 3. one per SG segment descriptors, used to manage HW link descriptors from
 *	(2). They do not have to be DMAable. They can either be (a) allocated
 *	together with link descriptors as mixed (DMA / CPU) objects, or (b)
 *	separately. Even if allocated separately it would be best to link them
 *	to link descriptors once during channel resource allocation and always
 *	use them as a single object.
 * Therefore for both cases (a) and (b) at run-time objects (2) and (3) shall be
 * treated as a single SG segment descriptor.
 */

struct nbpf_link_reg {
	u32	header;
	u32	src_addr;
	u32	dst_addr;
	u32	transaction_size;
	u32	config;
	u32	interval;
	u32	extension;
	u32	next;
} __packed;

struct nbpf_device;
struct nbpf_channel;
struct nbpf_desc;

struct nbpf_link_desc {
	struct nbpf_link_reg *hwdesc;
	dma_addr_t hwdesc_dma_addr;
	struct nbpf_desc *desc;
	struct list_head node;
};

/**
 * struct nbpf_desc - DMA transfer descriptor
 * @async_tx:	dmaengine object
 * @user_wait:	waiting for a user ack
 * @length:	total transfer length
 * @chan:	associated DMAC channel
 * @sg:		list of hardware descriptors, represented by struct nbpf_link_desc
 * @node:	member in channel descriptor lists
 */
struct nbpf_desc {
	struct dma_async_tx_descriptor async_tx;
	bool user_wait;
	size_t length;
	struct nbpf_channel *chan;
	struct list_head sg;
	struct list_head node;
};

/* Take a wild guess: allocate 4 segments per descriptor */
#define NBPF_SEGMENTS_PER_DESC 4
#define NBPF_DESCS_PER_PAGE ((PAGE_SIZE - sizeof(struct list_head)) /	\
	(sizeof(struct nbpf_desc) +					\
	 NBPF_SEGMENTS_PER_DESC *					\
	 (sizeof(struct nbpf_link_desc) + sizeof(struct nbpf_link_reg))))
#define NBPF_SEGMENTS_PER_PAGE (NBPF_SEGMENTS_PER_DESC * NBPF_DESCS_PER_PAGE)

struct nbpf_desc_page {
	struct list_head node;
	struct nbpf_desc desc[NBPF_DESCS_PER_PAGE];
	struct nbpf_link_desc ldesc[NBPF_SEGMENTS_PER_PAGE];
	struct nbpf_link_reg hwdesc[NBPF_SEGMENTS_PER_PAGE];
};

/**
 * struct nbpf_channel - one DMAC channel
 * @dma_chan:	standard dmaengine channel object
 * @tasklet:	channel specific tasklet used for callbacks
 * @base:	register address base
 * @nbpf:	DMAC
 * @name:	IRQ name
 * @irq:	IRQ number
 * @slave_src_addr:	source address for slave DMA
 * @slave_src_width:	source slave data size in bytes
 * @slave_src_burst:	maximum source slave burst size in bytes
 * @slave_dst_addr:	destination address for slave DMA
 * @slave_dst_width:	destination slave data size in bytes

Annotation

Implementation Notes