STRUCT SPI_MESSAGE(9)

πŸ“¦ version 7.3.1, in nixpkgs unstable

πŸ¦‹ struct spi_message(9) β€” like, the whole vibe πŸ¦‹

okay bestie, welcome to the struct spi_message(9) page from the Kernel API Manual β€” yes that's the manual name, we're in kernel API territory, put your big-girl hat on πŸ’…


✨ NAME ✨

struct spi_message β€” one multi-segment SPI transaction, aka the whole group-chat of transfers that has to go out together, no cap 🌈


πŸŽ€ SYNOPSIS πŸŽ€

struct spi_message {
    struct list_head        transfers;
    struct spi_device       *spi;
    bool pre_optimized;
    bool optimized;
    bool prepared;
    int status;
    void (*complete)(void *context);
    void *context;
    unsigned frame_length;
    unsigned actual_length;
    struct list_head        queue;
    void *state;
    void *opt_state;
    struct spi_offload      *offload;
    struct list_head        resources;
 };

πŸ’– Members πŸ’–

girl, let's meet the cast, one field at a time 🫢

  • transfers β€” the list of transfer segments in this transaction. it's the roster. the lineup. the main characters ✨
  • spi β€” the SPI device this transaction gets queued to πŸ‘‘
  • pre_optimized β€” a bool; the peripheral driver pre-optimized the message
  • optimized β€” a bool; the message is in the optimized state
  • prepared β€” a bool; spi_prepare_message was called for the this message (yes, "the this" β€” that's the original wording, i don't make the rules πŸ™ˆ)
  • status β€” zero for success, else negative errno. iconic little pass/fail meter πŸ’€
  • complete β€” called to report transaction completions. it's the "we're done here" callback 🎬
  • context β€” the argument to complete when it's called
  • frame_length β€” the total number of bytes in the message
  • actual_length β€” the total number of bytes that were transferred in all successful segments. emphasis on successful, bestie 🌸
  • queue β€” for use by whichever driver currently owns the message
  • state β€” for use by whichever driver currently owns the message
  • opt_state β€” for use by whichever driver currently owns the message
  • offload β€” (optional) offload instance used by this message πŸ”₯
  • resources β€” for resource management when the SPI message is processed
yeah queue, state and opt_state all have the exact same description. that's not me being lazy, that's the API. three separate little scratchpads for whoever owns the message 🧚

🌸 Description 🌸

so a spi_message is used to execute an atomic sequence of data transfers, and each one of those transfers is represented by a struct spi_transfer ✨

the sequence is "atomic" in the sense that no other spi_message may use that SPI bus until that sequence completes β€” like, the bus is busy, do not perceive her πŸ’…

on some systems, many such sequences can execute as a single programmed DMA transfer. highkey efficient πŸ”₯

on all systems, these messages are queued, and might complete after transactions to other devices. so like, don't hold your breath waiting, she'll get there when she gets there 😌

messages sent to a given spi_device are always executed in FIFO order β€” first in, first out, no cutting the line, periodt ⭐

the code that submits an spi_message (and its spi_transfers) to the lower layers is responsible for managing its memory 🫢

zero-initialize every field you don't set up explicitly, to insulate against future API updates. this one matters, bestie β€” it's literally future-proofing yourself 🌈

after you submit a message and its transfers, ignore them until its completion callback. like, leave them on read. don't touch. do not go poking at memory that isn't yours yet πŸ’€

πŸ¦‹ SEE ALSO πŸ¦‹


and that's the page, bestie πŸŽ€ this whole thing came out of ./include/linux/spi and it's the October 2026 edition β€” so like, slay, go forth and queue your messages in FIFO order πŸ’œβœ¨

πŸ“¦ where this page comes from