04、DMA client device结构体抽象
一、struct dma_slave_config
struct dma_slave_config结构体包含了完成一次DMA传输所需要的所有可能的参数,用于配置DMA slave通道运行时参数,定义在include/linux/dmaengine.h:
/**
* struct dma_slave_config - dma slave channel runtime config
* @direction: whether the data shall go in or out on this slave
* channel, right now. DMA_MEM_TO_DEV and DMA_DEV_TO_MEM are
* legal values. DEPRECATED, drivers should use the direction argument
* to the device_prep_slave_sg and device_prep_dma_cyclic functions or
* the dir field in the dma_interleaved_template structure.
* @src_addr: this is the physical address where DMA slave data
* should be read (RX), if the source is memory this argument is
* ignored.
* @dst_addr: this is the physical address where DMA slave data
* should be written (TX), if the destination is memory this argument
* is ignored.
* @src_addr_width: this is the width in bytes of the source (RX)
* register where DMA data shall be read. If the source
* is memory this may be ignored depending on architecture.
* Legal values: 1, 2, 3, 4, 8, 16, 32, 64, 128.
* @dst_addr_width: same as src_addr_width but for destination
* target (TX) mutatis mutandis.
* @src_maxburst: the maximum number of words (note: words, as in
* units of the src_addr_width member, not bytes) that can be sent
* in one burst to the device. Typically something like half the
* FIFO depth on I/O peripherals so you don't overflow it. This
* may or may not be applicable on memory sources.
* @dst_maxburst: same as src_maxburst but for destination target
* mutatis mutandis.
* @src_port_window_size: The length of the register area in words the data need
* to be accessed on the device side. It is only used for devices which is using
* an area instead of a single register to receive the data. Typically the DMA
* loops in this area in order to transfer the data.
* @dst_port_window_size: same as src_port_window_size but for the destination
* port.
* @device_fc: Flow Controller Settings. Only valid for slave channels. Fill
* with 'true' if peripheral should be flow controller. Direction will be
* selected at Runtime.
* @peripheral_config: peripheral configuration for programming peripheral
* for dmaengine transfer
* @peripheral_size: peripheral configuration buffer size
*
* This struct is passed in as configuration data to a DMA engine
* in order to set up a certain channel for DMA transport at runtime.
* The DMA device/engine has to provide support for an additional
* callback in the dma_device structure, device_config and this struct
* will then be passed in as an argument to the function.
*
* The rationale for adding configuration information to this struct is as
* follows: if it is likely that more than one DMA slave controllers in
* the world will support the configuration option, then make it generic.
* If not: if it is fixed so that it be sent in static from the platform
* data, then prefer to do that.
*/
struct dma_slave_config {
enum dma_transfer_direction direction;
phys_addr_t src_addr;
phys_addr_t dst_addr;
enum dma_slave_buswidth src_addr_width;
enum dma_slave_buswidth dst_addr_width;
u32 src_maxburst;
u32 dst_maxburst;
u32 src_port_window_size;
u32 dst_port_window_size;
bool device_fc;
void *peripheral_config;
size_t peripheral_size;
};
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
DMA配置结构体说明
该结构体用于向DMA控制器驱动传递传输参数,驱动需通过device_config
函数读取这些参数设置通道。
各字段含义:
方向(direction)
- 已弃用字段,表示传输方向(设备到内存或内存到设备)。
- 新驱动应改用其他函数参数或结构体中的方向字段。
源物理地址(src_addr)
- 当源是设备(如设备→内存或设备→设备)时,填入设备的物理地址。
- 若源是内存(如内存→设备或内存→内存),此参数会被忽略。
目标物理地址(dst_addr)
- 当目标是设备(如内存→设备或设备→设备)时,填入设备的物理地址。
- 若目标是内存(如内存→内存或设备→内存),此参数会被忽略。
源地址宽度(src_addr_width)
- 读取数据时,源寄存器的字节宽度(如1、2、4字节等)。
- 若源是内存,某些架构可能忽略此参数。
目标地址宽度(dst_addr_width)
- 写入数据时,目标寄存器的字节宽度。规则与源地址宽度相同。
源端最大突发传输量(src_maxburst)
- 每次传输到设备的最大数据块,单位为「字」(字长度由
src_addr_width
决定)。 - 通常设为设备FIFO深度的一半,防止数据溢出。
- 每次传输到设备的最大数据块,单位为「字」(字长度由
目标端最大突发传输量(dst_maxburst)
- 目标端(如设备接收端)的突发传输量设置,规则与源端相同。
源端口窗口大小(src_port_window_size)
- 设备源端需要访问的寄存器区域长度(单位为字)。
- 用于需要循环传输数据的设备。
目标端口窗口大小(dst_port_window_size)
- 目标端设备的寄存器区域大小,规则与源端相同。
流控制(device_fc)
布尔值,表示是否由外设控制数据流。
仅对设备通道有效,设为
true
时外设成为流控制器。
外设配置(peripheral_config)
- 存储外设的DMA配置参数。
外设配置大小(peripheral_size)
- 上述配置参数的字节大小。
使用场景
该结构体作为参数传递给DMA控制器驱动的device_config
函数,用于初始化通道的传输参数。驱动需确保支持此函数,并正确解析结构体中的配置。
二、struct dma_async_tx_descriptor
struct dma_async_tx_descriptor用于描述一次DMA传输,表示DMA异步传输描述符,定义在include/linux/dmaengine.h:
/**
* struct dma_async_tx_descriptor - async transaction descriptor
* ---dma generic offload fields---
* @cookie: tracking cookie for this transaction, set to -EBUSY if
* this tx is sitting on a dependency list
* @flags: flags to augment operation preparation, control completion, and
* communicate status
* @phys: physical address of the descriptor
* @chan: target channel for this operation
* @tx_submit: accept the descriptor, assign ordered cookie and mark the
* descriptor pending. To be pushed on .issue_pending() call
* @callback: routine to call after this operation is complete
* @callback_param: general parameter to pass to the callback routine
* @desc_metadata_mode: core managed metadata mode to protect mixed use of
* DESC_METADATA_CLIENT or DESC_METADATA_ENGINE. Otherwise
* DESC_METADATA_NONE
* @metadata_ops: DMA driver provided metadata mode ops, need to be set by the
* DMA driver if metadata mode is supported with the descriptor
* ---async_tx api specific fields---
* @next: at completion submit this descriptor
* @parent: pointer to the next level up in the dependency chain
* @lock: protect the parent and next pointers
*/
struct dma_async_tx_descriptor {
dma_cookie_t cookie;
enum dma_ctrl_flags flags; /* not a 'long' to pack with cookie */
dma_addr_t phys;
struct dma_chan *chan;
dma_cookie_t (*tx_submit)(struct dma_async_tx_descriptor *tx);
int (*desc_free)(struct dma_async_tx_descriptor *tx);
dma_async_tx_callback callback;
dma_async_tx_callback_result callback_result;
void *callback_param;
struct dmaengine_unmap_data *unmap;
enum dma_desc_metadata_mode desc_metadata_mode;
struct dma_descriptor_metadata_ops *metadata_ops;
#ifdef CONFIG_ASYNC_TX_ENABLE_CHANNEL_SWITCH
struct dma_async_tx_descriptor *next;
struct dma_async_tx_descriptor *parent;
spinlock_t lock;
#endif
};
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
以下是该结构体字段的解释:
cookie
用于标识当前数据传输的唯一编号。当传输因等待资源而被挂起时,会标记为-EBUSY
(表示资源占用中)。flags
控制操作的标志位,用于管理操作准备、完成状态以及描述符的状态信息。phys
存储描述符的物理地址(内存位置)。chan
指向目标通道(Channel),即执行该操作的具体硬件通道。tx_submit
一个方法,负责接收描述符并分配唯一标识符,标记其为“已提交”状态。当调用.issue_pending()
时,该描述符会被加入待处理队列。callback
操作完成后需要调用的回调函数。callback_param
传递给回调函数的参数(数据或指针)。desc_metadata_mode
管理描述符元数据的模式:DESC_METADATA_CLIENT
或DESC_METADATA_ENGINE
(混合使用时需保护数据安全)DESC_METADATA_NONE
(不使用元数据)
metadata_ops
DMA驱动提供的元数据操作接口。若支持元数据模式,驱动必须设置此字段。next
指向完成后需要自动提交的下一个描述符。parent
指向上一级依赖的描述符(用于构建依赖关系链)。lock
一个自旋锁,用于保护parent
和next
指针,避免多线程访问冲突。