STRUCT DMA_DEVICE(9)

πŸ“¦ version 7.3.1, in nixpkgs unstable

πŸ’– struct dma_device(9) πŸ’–

okay bestie, so you've stumbled into the Kernel API Manual page for struct dma_device(9) and honestly? slay. this is the struct that describes the entity supplying DMA services β€” like, the whole DMA controller's little ID card. it's a big one, so grab a snack πŸ“.


✨ NAME ✨

struct dma_device β€” the info on the entity supplying DMA services 🫢


🌸 SYNOPSIS 🌸

here's the whole struct, no cap, every single line:

struct dma_device {
    struct kref ref;
    unsigned int chancnt;
    unsigned int privatecnt;
    struct list_head channels;
    struct list_head global_node;
    struct dma_filter filter;
    dma_cap_mask_t cap_mask;
    enum dma_desc_metadata_mode desc_metadata_modes;
    unsigned short max_xor;
    unsigned short max_pq;
    enum dmaengine_alignment copy_align;
    enum dmaengine_alignment xor_align;
    enum dmaengine_alignment pq_align;
    enum dmaengine_alignment fill_align;
  #define DMA_HAS_PQ_CONTINUE (1 << 15);
    int dev_id;
    struct device *dev;
    struct module *owner;
    struct ida chan_ida;
    u32 src_addr_widths;
    u32 dst_addr_widths;
    u32 directions;
    u32 min_burst;
    u32 max_burst;
    u32 max_sg_burst;
    bool descriptor_reuse;
    enum dma_residue_granularity residue_granularity;
    int (*device_alloc_chan_resources)(struct dma_chan *chan);
    int (*device_router_config)(struct dma_chan *chan);
    void (*device_free_chan_resources)(struct dma_chan *chan);
    struct dma_async_tx_descriptor *(*device_prep_dma_memcpy)( struct
dma_chan *chan, dma_addr_t dst, dma_addr_t src, size_t len, unsigned
long flags);
    struct dma_async_tx_descriptor *(*device_prep_dma_xor)( struct
dma_chan *chan, dma_addr_t dst, dma_addr_t *src, unsigned int src_cnt,
size_t len, unsigned long flags);
    struct dma_async_tx_descriptor *(*device_prep_dma_xor_val)( struct
dma_chan *chan, dma_addr_t *src, unsigned int src_cnt, size_t len, enum
sum_check_flags *result, unsigned long flags);
    struct dma_async_tx_descriptor *(*device_prep_dma_pq)( struct
dma_chan *chan, dma_addr_t *dst, dma_addr_t *src, unsigned int src_cnt,
const unsigned char *scf, size_t len, unsigned long flags);
    struct dma_async_tx_descriptor *(*device_prep_dma_pq_val)( struct
dma_chan *chan, dma_addr_t *pq, dma_addr_t *src, unsigned int src_cnt,
const unsigned char *scf, size_t len, enum sum_check_flags *pqres,
unsigned long flags);
    struct dma_async_tx_descriptor *(*device_prep_dma_memset)( struct
dma_chan *chan, dma_addr_t dest, int value, size_t len, unsigned long
flags);
    struct dma_async_tx_descriptor *(*device_prep_dma_memset_sg)( struct
dma_chan *chan, struct scatterlist *sg, unsigned int nents, int value,
unsigned long flags);
    struct dma_async_tx_descriptor *(*device_prep_dma_interrupt)( struct
dma_chan *chan, unsigned long flags);
    struct dma_async_tx_descriptor *(*device_prep_peripheral_dma_vec)(
struct dma_chan *chan, const struct dma_vec *vecs, size_t nents, enum
dma_transfer_direction direction, unsigned long flags);
    struct dma_async_tx_descriptor *(*device_prep_slave_sg)( struct
dma_chan *chan, struct scatterlist *sgl, unsigned int sg_len, enum
dma_transfer_direction direction, unsigned long flags, void *context);
    struct dma_async_tx_descriptor *(*device_prep_config_sg)( struct
dma_chan *chan, struct scatterlist *sgl, unsigned int sg_len, enum
dma_transfer_direction direction, unsigned long flags, struct
dma_slave_config *config);
    struct dma_async_tx_descriptor *(*device_prep_dma_cyclic)( struct
dma_chan *chan, dma_addr_t buf_addr, size_t buf_len, size_t period_len,
enum dma_transfer_direction direction, unsigned long flags);
    struct dma_async_tx_descriptor *(*device_prep_interleaved_dma)(
struct dma_chan *chan, struct dma_interleaved_template *xt, unsigned
long flags);
    void (*device_caps)(struct dma_chan *chan, struct dma_slave_caps
*caps);
    int (*device_config)(struct dma_chan *chan, struct dma_slave_config
*config);
    int (*device_pause)(struct dma_chan *chan);
    int (*device_resume)(struct dma_chan *chan);
    int (*device_terminate_all)(struct dma_chan *chan);
    void (*device_synchronize)(struct dma_chan *chan);
    enum dma_status (*device_tx_status)(struct dma_chan *chan,
dma_cookie_t cookie, struct dma_tx_state *txstate);
    void (*device_issue_pending)(struct dma_chan *chan);
    void (*device_release)(struct dma_device *dev);
    void (*dbg_summary_show)(struct seq_file *s, struct dma_device
*dev);
    struct dentry *dbg_dev_root;
 };

πŸŽ€ Members πŸŽ€

okay this is the part where we go field by field, and yes there are a LOT of them. it's giving "main character energy" for like thirty bullet points straight. let's go πŸ’…

🌈 the bookkeeping girlies

  • ref β€” a reference is taken and put every time a channel is allocated or freed. basically the popularity counter πŸ”₯
  • chancnt β€” how many DMA channels are supported, periodt.
  • privatecnt β€” how many DMA channels are requested by dma_request_channel.
  • channels β€” the list of struct dma_chan. the whole squad.
  • global_node β€” the list_head for the global dma_device_list.
  • filter β€” the info for the device/slave to filter function/param mapping.
  • cap_mask β€” one or more dma_capability flags. like a little badge collection ✨
  • desc_metadata_modes β€” the metadata modes supported by the DMA device.
  • dev_id β€” a unique device ID. no two controllers share, iykyk.
  • dev β€” the struct device reference for the dma mapping api.
  • owner β€” owner module, and it's automatically set based on the provided dev πŸͺ„
  • chan_ida β€” a unique channel ID.

πŸ”₯ the capability counts & alignments

  • max_xor β€” maximum number of xor sources, 0 if there's no capability.
  • max_pq β€” maximum number of PQ sources and PQ-continue capability.
  • copy_align β€” the alignment shift for memcpy operations.
  • xor_align β€” the alignment shift for xor operations.
  • pq_align β€” the alignment shift for pq operations.
  • fill_align β€” the alignment shift for memset operations.

πŸ¦‹ the address / direction / burst zone

  • src_addr_widths β€” a bit mask of the src addr widths the device supports. the width is specified in bytes, so like, for a device supporting a width of 4 the mask should have BIT(4) set. lowkey important, don't fumble that πŸ™ˆ
  • dst_addr_widths β€” a bit mask of the dst addr widths the device supports.
  • directions β€” a bit mask of the slave directions the device supports. and this is the fun one: since the enum dma_transfer_direction is not defined as a bit flag for each type, the dma controller should set BIT(<TYPE>) and the same should be checked by the controller as well. consistency is the vibe check bestie.
  • min_burst β€” min burst capability per-transfer.
  • max_burst β€” max burst capability per-transfer.
  • max_sg_burst β€” the max number of SG list entries executed in a single burst DMA transaction with no software intervention for reinitialization. a zero value means unlimited number of entries πŸ‘‘
  • descriptor_reuse β€” a submitted transfer can be resubmitted after completion.
  • residue_granularity β€” the granularity of the transfer residue reported by tx_status.

πŸ’œ the resource-management callbacks

  • device_alloc_chan_resources β€” allocate resources and return the number of allocated descriptors.
  • device_router_config β€” optional callback for DMA router configuration.
  • device_free_chan_resources β€” release the DMA channel's resources.

🌟 the prep callbacks (the big group, stay with me)

  • device_prep_dma_memcpy β€” prepares a memcpy operation.
  • device_prep_dma_xor β€” prepares a xor operation.
  • device_prep_dma_xor_val β€” prepares a xor validation operation.
  • device_prep_dma_pq β€” prepares a pq operation.
  • device_prep_dma_pq_val β€” prepares a pqzero_sum operation.
  • device_prep_dma_memset β€” prepares a memset operation.
  • device_prep_dma_memset_sg β€” prepares a memset operation over a scatter list.
  • device_prep_dma_interrupt β€” prepares an end of chain interrupt operation.
  • device_prep_peripheral_dma_vec β€” prepares a scatter-gather DMA transfer, where the address and size of each segment is located in one entry of the dma_vec array. cute and efficient fr fr.
  • device_prep_slave_sg β€” prepares a slave dma operation.
  • device_prep_config_sg β€” prepares a slave DMA operation with dma_slave_config.
  • device_prep_dma_cyclic β€” prepare a cyclic dma operation suitable for audio 🎧 the function takes a buffer of size buf_len, and the callback function will be called after period_len bytes have been transferred. loop girlie behavior.
  • device_prep_interleaved_dma β€” Transfer expression in a generic way.

🌸 the control-plane callbacks

  • device_caps β€” may be used to override the generic DMA slave capabilities with per-channel specific ones.
  • device_config β€” pushes a new configuration to a channel, returns 0 or an error code.
  • device_pause β€” pauses any transfer happening on a channel. returns 0 or an error code.
  • device_resume β€” resumes any transfer on a channel previously paused. returns 0 or an error code.
  • device_terminate_all β€” aborts all transfers on a channel. returns 0 or an error code.
  • device_synchronize β€” synchronizes the termination of a transfers to the current context.
  • device_tx_status β€” poll for transaction completion. the optional txstate parameter can be supplied with a pointer to get a struct with auxiliary transfer status information, otherwise the call will just return a simple status code. pick your fighter πŸ’€
  • device_issue_pending β€” push pending transactions to hardware. the "go go go" button πŸ”₯

🧚 the teardown & debug bits

  • device_release β€” called sometime after dma_async_device_unregister is called and there are no further references to this structure. this must be implemented to free resources β€” however, many existing drivers do not, and are therefore not safe to unbind while in use. bestie. read that twice 😭 that's a real hazard, not a vibe.
  • dbg_summary_show β€” optional routine to show contents in debugfs; the default code will be used when this is omitted, but custom code can show extra, controller specific information.
  • dbg_dev_root β€” the root folder in debugfs for this device.

heads up bestie, there's more of this page coming β€” don't close the tab πŸ’–

✨ SEE ALSO ✨

okay bestie, this is the part where we hand you the whole friend group 🫢 every single one of these lives in the kernel file ./include/linux/dmaengine.h, and they're all in section 9, so you already know the vibe. go say hi:

  • dma_cookie_t(9) β€” the cookie type, yes it's literally called a cookie, we love a whimsical naming moment πŸͺ
  • enum dma_status(9) β€” the status enum, your vibe check for a transfer
  • enum dma_transaction_type(9) β€” the enum of transaction types
  • enum dma_transfer_direction(9) β€” the direction enum, which way the data's going
  • struct data_chunk(9) β€” the data chunk struct
  • struct dma_interleaved_template(9) β€” the interleaved template struct, fancy
  • struct dma_vec(9) β€” the dma vec struct
  • enum dma_ctrl_flags(9) β€” the control flags enum
  • enum sum_check_bits(9) β€” the sum check bits enum
  • enum sum_check_flags(9) β€” the sum check flags enum
  • enum dma_desc_metadata_mode(9) β€” the descriptor metadata mode enum
  • struct dma_chan_percpu(9) β€” the per-cpu channel struct
  • struct dma_router(9) β€” the router struct
  • struct dma_chan(9) β€” the channel struct itself, main character energy πŸ‘‘
  • struct dma_chan_dev(9) β€” the channel device struct
  • enum dma_slave_buswidth(9) β€” the slave bus width enum
  • struct dma_slave_config(9) β€” the slave config struct
  • enum dma_residue_granularity(9) β€” the residue granularity enum
  • struct dma_slave_caps(9) β€” the slave caps struct
  • dma_filter_fn(9) β€” the filter function type
  • struct dma_async_tx_descriptor(9) β€” the async tx descriptor struct, absolute icon
  • struct dma_tx_state(9) β€” the tx state struct
  • enum dmaengine_alignment(9) β€” the dmaengine alignment enum
  • struct dma_slave_map(9) β€” the slave map struct
  • struct dma_filter(9) β€” the filter struct
  • dmaengine_prep_peripheral_dma_vec(9) β€” preps a peripheral dma vec
  • dmaengine_prep_config_sg_safe(9) β€” the sg-safe prep config call
  • dmaengine_prep_config_single_safe(9) β€” the single-safe prep config call
  • dmaengine_prep_dma_memset(9) β€” preps a dma memset, yes that's a thing
  • dmaengine_terminate_all(9) β€” terminates all of it 😭
  • dmaengine_terminate_async(9) β€” the async terminate
  • dmaengine_synchronize(9) β€” synchronizes, get in sync bestie
  • dmaengine_terminate_sync(9) β€” the sync terminate
  • dma_async_issue_pending(9) β€” issues the pending async work
  • dma_async_is_tx_complete(9) β€” asks "is the tx complete?" πŸ”₯
  • dma_async_is_complete(9) β€” asks "is it complete?" πŸ”₯

ngl that's a whole lotta pages but they're all right there in ./include/linux/dmaengine.h, so like… one tab and you're set πŸ’…

and that's the whole manual page, bestie β€” periodt πŸŽ€ this one came out of the tree at ./include/linux, dated October 2026, and it's filed under struct dma_device(9). go forth and DMA responsibly, mwah πŸ’–βœ¨πŸ¦‹

πŸ“¦ where this page comes from