Day 100 - DMA Controller and DMA Channel¶
Today's Goal¶
Continue learning the Linux DMA Engine Framework by focusing on DMA controller drivers and DMA channel management.
The objective of Day100 is to understand how a hardware-specific DMA controller is represented inside the DMA Engine Framework, how its channels are registered and managed, and how a client driver obtains the correct channel through Device Tree.
What I Learned¶
Today focused on the relationship between DMA controller drivers, the DMA Engine Framework, and client drivers.
Why Linux Needs DMA Controller Drivers¶
Different SoCs provide different DMA controller hardware.
The hardware may differ in:
- Register layout
- Channel organization
- Descriptor format
- DMA request routing
- Interrupt handling
- Supported transaction types
- Hardware limitations
Without a common framework, every client driver would need controller-specific code and would become tightly coupled to a particular SoC.
Linux separates the DMA subsystem into the following layers:
The client driver describes the transfer it needs, while the DMA controller driver handles hardware-specific operations.
DMA Engine Framework and Controller Driver¶
The DMA Engine Framework provides a generic interface between DMA clients and hardware-specific controller drivers.
The responsibility of each layer is:
| Layer | Responsibility |
|---|---|
| Client Driver | Requests DMA resources and prepares DMA transfers without accessing controller registers. |
| DMA Engine Framework | Manages DMA controllers and channels and provides common DMA APIs. |
| DMA Controller Driver | Implements controller-specific operations and controls the hardware. |
| DMA Controller Hardware | Performs the actual data transfer. |
The framework does not understand the register layout of a particular controller. Instead, it invokes operation callbacks supplied by the DMA controller driver.
This follows the same Linux framework pattern used by VFS, gpiolib, and other kernel subsystems:
struct dma_device¶
A DMA controller driver represents one DMA controller using:
The object describes the controller to the DMA Engine Framework.
Its major responsibilities include:
- Identifying the underlying Linux device
- Advertising supported DMA capabilities
- Maintaining the controller's DMA channel list
- Providing controller-specific operation callbacks
- Linking the controller into the framework's global device list
A useful first-level classification of its members is:
| Category | Purpose |
|---|---|
| Identity | Associates the DMA controller with the Linux Device Model. |
| Capabilities | Describes the transaction types supported by the controller. |
| Channels | Maintains the channels provided by the controller. |
| Operations | Provides hardware-specific callback implementations. |
| Framework linkage | Connects the controller to the DMA Engine global device list. |
A DMA controller driver normally initializes this object during its probe() function and registers it using the DMA Engine registration interface.
Controller and Channel Lists¶
Two list members in struct dma_device operate at different hierarchy levels:
| Member | Purpose |
|---|---|
channels |
List head for all struct dma_chan objects owned by this controller. |
global_node |
Node used to link this struct dma_device into the framework's global DMA device list. |
This creates two levels of linked lists:
DMA Engine Global Device List
│
├── dma_device A
│ └── Local Channel List
│ ├── dma_chan 0
│ └── dma_chan 1
│
└── dma_device B
└── Local Channel List
├── dma_chan 0
└── dma_chan 1
The framework uses the global list to manage registered DMA controllers, while each controller uses its local channel list to manage its own resources.
Advanced DMA Capabilities¶
Some members of struct dma_device are intended for specialized DMA hardware rather than ordinary peripheral DMA.
Examples include:
| Member | Purpose |
|---|---|
max_xor |
Maximum number of source buffers supported by a hardware XOR operation. |
max_pq |
Maximum number of source buffers supported when generating RAID6 P/Q parity. |
These capabilities are primarily used by storage and RAID acceleration hardware.
They are normally unrelated to common UART, SPI, I2S, or other peripheral DMA transfers.
struct dma_chan¶
A DMA controller normally provides one or more DMA channels.
Each channel is represented by:
The relationship is:
struct dma_chan represents a DMA resource that can be assigned to a client driver.
Important conceptual responsibilities include:
- Identifying the parent
struct dma_device - Representing one controller-provided channel
- Maintaining channel allocation or reference state
- Providing the object used by client-facing DMA APIs
The client driver normally stores a pointer such as:
The client does not create these channel objects. They are created and initialized by the DMA controller driver and later assigned through the DMA Engine Framework.
DMA Controller Registration Lifecycle¶
The DMA controller is normally initialized during kernel boot when its driver is probed.
A simplified lifecycle is:
Kernel Boot
│
▼
DMA Controller Driver Probe
│
▼
Initialize Hardware Resources
│
▼
Initialize struct dma_device
│
▼
Initialize struct dma_chan Objects
│
▼
Register with DMA Engine Framework
│
▼
Controller and Channels Become Available
The probe function commonly performs operations such as:
- Mapping controller registers
- Requesting interrupts
- Initializing controller-private state
- Configuring
struct dma_device - Creating and linking DMA channels
- Registering the DMA controller with the framework
If a client driver probes before its DMA provider is ready, channel acquisition may return -EPROBE_DEFER, allowing the client probe to be retried later.
DMA Channel Allocation¶
A client driver obtains a DMA channel using a logical name:
For example:
The string "rx" is a logical channel name rather than a hardware channel number.
The name is matched against the client's firmware description, commonly through Device Tree.
Device Tree DMA Description¶
A peripheral node can describe its DMA connections using dmas and dma-names.
Example:
The entries correspond by index:
| Index | dma-names |
dmas |
|---|---|---|
| 0 | "rx" |
<&dma0 5> |
| 1 | "tx" |
<&dma0 6> |
When the client requests "rx", the framework locates index 0 and retrieves the corresponding DMA specifier.
The cells following the DMA controller phandle form a controller-specific DMA specifier. Their meaning is defined by the DMA controller binding and interpreted by the controller driver.
They may describe information such as:
- DMA request line
- Physical channel or stream
- DMA multiplexer selection
- Transfer configuration flags
- Priority or routing information
The specifier must not be assumed to match dma_chan->chan_id.
dma_request_chan() Lookup Flow¶
The conceptual lookup flow is:
Client Driver
│
│ dma_request_chan(dev, "rx")
▼
DMA Engine Framework
│
▼
Find "rx" in dma-names
│
▼
Read the Corresponding dmas Entry
│
▼
Locate the DMA Controller Provider
│
▼
Perform Controller-Specific Translation
│
▼
Return struct dma_chan *
The framework coordinates the lookup, but the DMA controller provider interprets the controller-specific DMA specifier.
Therefore, dma_request_chan() does not create a new channel and does not simply choose a random unused channel from every registered controller.
It resolves the DMA connection described for the requesting device and returns an existing channel managed by the selected provider.
Operation Callbacks¶
Many callback members in struct dma_device use names beginning with device_, such as:
device_alloc_chan_resourcesdevice_free_chan_resourcesdevice_prep_dma_memcpydevice_prep_slave_sgdevice_issue_pendingdevice_tx_status
These are controller-driver callbacks rather than the normal public APIs called directly by client drivers.
The typical call path is:
Client Driver
│
▼
Public DMA Engine API
│
▼
DMA Engine Framework
│
▼
dma_device Operation Callback
│
▼
DMA Controller Driver
│
▼
DMA Hardware
This separates generic client-facing APIs from hardware-specific controller implementations.
Linux Source Tour¶
Important source locations studied today include:
| Location | Purpose |
|---|---|
include/linux/dmaengine.h |
Defines the public DMA Engine objects, capabilities, and interfaces. |
drivers/dma/dmaengine.c |
Implements the DMA Engine core and generic framework behavior. |
drivers/dma/of-dma.c |
Provides Device Tree DMA provider and lookup support. |
drivers/dma/virt-dma.c |
Provides reusable virtual-channel and descriptor queue helpers. |
drivers/dma/ |
Contains hardware-specific DMA controller drivers. |
The source tree contains both framework code and controller-specific drivers. These responsibilities must be distinguished when reading the implementation.
Important Observations¶
Several important distinctions were clarified today:
- The DMA Engine Framework is not a DMA controller.
- One
struct dma_devicenormally represents one DMA controller. - One
struct dma_devicemay own multiplestruct dma_chanobjects. - The controller driver creates and registers the controller and channel objects.
- The client driver obtains an existing channel rather than creating one.
dma-namesprovides logical names used by client drivers.dmasprovides controller references and controller-specific specifiers.- A DMA specifier is not necessarily a Linux channel ID.
- Framework APIs and
struct dma_deviceoperation callbacks belong to different abstraction layers. - No actual DMA transaction has occurred at the channel-allocation stage.
A concise mental model is:
Client drivers use
struct dma_chan, the DMA Engine Framework managesstruct dma_device, and DMA controller drivers implementstruct dma_device.
Summary¶
Day100 established how Linux represents and manages DMA controllers and DMA channels.
A DMA controller driver initializes a struct dma_device, creates its struct dma_chan objects, provides hardware-specific operation callbacks, and registers the controller with the DMA Engine Framework.
A client driver later calls dma_request_chan() with a logical name. The framework uses the client's firmware description, including dmas and dma-names, to locate the correct DMA provider and obtain a suitable channel.
This completes the resource-management portion of the DMA Engine mental model.
No DMA transfer has started yet. The next stage is to understand how a client uses an acquired struct dma_chan to prepare, submit, start, and complete a DMA transaction.
Next Plan¶
Continue with Day101 - DMA Transaction and Descriptor Lifecycle, including:
- DMA transaction model
struct dma_async_tx_descriptor- Descriptor preparation
device_prep_*()callbacksdmaengine_submit()dma_async_issue_pending()- DMA cookies
- Completion interrupts and callbacks