* [PATCH 1/2] mailbox: Documentation: remove the old documentation @ 2024-10-19 19:55 anish kumar 2024-10-19 19:55 ` [PATCH 2/2] mailbox: Documentation: add the latest documentation anish kumar 0 siblings, 1 reply; 12+ messages in thread From: anish kumar @ 2024-10-19 19:55 UTC (permalink / raw) To: jassisinghbrar, corbet; +Cc: linux-doc, linux-kernel, anish kumar In preparation of better and latest documentation, remove the current documentation. Signed-off-by: anish kumar <yesanishhere@gmail.com> --- Documentation/driver-api/mailbox.rst | 129 --------------------------- 1 file changed, 129 deletions(-) delete mode 100644 Documentation/driver-api/mailbox.rst diff --git a/Documentation/driver-api/mailbox.rst b/Documentation/driver-api/mailbox.rst deleted file mode 100644 index 0ed95009cc30..000000000000 --- a/Documentation/driver-api/mailbox.rst +++ /dev/null @@ -1,129 +0,0 @@ -============================ -The Common Mailbox Framework -============================ - -:Author: Jassi Brar <jaswinder.singh@linaro.org> - -This document aims to help developers write client and controller -drivers for the API. But before we start, let us note that the -client (especially) and controller drivers are likely going to be -very platform specific because the remote firmware is likely to be -proprietary and implement non-standard protocol. So even if two -platforms employ, say, PL320 controller, the client drivers can't -be shared across them. Even the PL320 driver might need to accommodate -some platform specific quirks. So the API is meant mainly to avoid -similar copies of code written for each platform. Having said that, -nothing prevents the remote f/w to also be Linux based and use the -same api there. However none of that helps us locally because we only -ever deal at client's protocol level. - -Some of the choices made during implementation are the result of this -peculiarity of this "common" framework. - - - -Controller Driver (See include/linux/mailbox_controller.h) -========================================================== - - -Allocate mbox_controller and the array of mbox_chan. -Populate mbox_chan_ops, except peek_data() all are mandatory. -The controller driver might know a message has been consumed -by the remote by getting an IRQ or polling some hardware flag -or it can never know (the client knows by way of the protocol). -The method in order of preference is IRQ -> Poll -> None, which -the controller driver should set via 'txdone_irq' or 'txdone_poll' -or neither. - - -Client Driver (See include/linux/mailbox_client.h) -================================================== - - -The client might want to operate in blocking mode (synchronously -send a message through before returning) or non-blocking/async mode (submit -a message and a callback function to the API and return immediately). - -:: - - struct demo_client { - struct mbox_client cl; - struct mbox_chan *mbox; - struct completion c; - bool async; - /* ... */ - }; - - /* - * This is the handler for data received from remote. The behaviour is purely - * dependent upon the protocol. This is just an example. - */ - static void message_from_remote(struct mbox_client *cl, void *mssg) - { - struct demo_client *dc = container_of(cl, struct demo_client, cl); - if (dc->async) { - if (is_an_ack(mssg)) { - /* An ACK to our last sample sent */ - return; /* Or do something else here */ - } else { /* A new message from remote */ - queue_req(mssg); - } - } else { - /* Remote f/w sends only ACK packets on this channel */ - return; - } - } - - static void sample_sent(struct mbox_client *cl, void *mssg, int r) - { - struct demo_client *dc = container_of(cl, struct demo_client, cl); - complete(&dc->c); - } - - static void client_demo(struct platform_device *pdev) - { - struct demo_client *dc_sync, *dc_async; - /* The controller already knows async_pkt and sync_pkt */ - struct async_pkt ap; - struct sync_pkt sp; - - dc_sync = kzalloc(sizeof(*dc_sync), GFP_KERNEL); - dc_async = kzalloc(sizeof(*dc_async), GFP_KERNEL); - - /* Populate non-blocking mode client */ - dc_async->cl.dev = &pdev->dev; - dc_async->cl.rx_callback = message_from_remote; - dc_async->cl.tx_done = sample_sent; - dc_async->cl.tx_block = false; - dc_async->cl.tx_tout = 0; /* doesn't matter here */ - dc_async->cl.knows_txdone = false; /* depending upon protocol */ - dc_async->async = true; - init_completion(&dc_async->c); - - /* Populate blocking mode client */ - dc_sync->cl.dev = &pdev->dev; - dc_sync->cl.rx_callback = message_from_remote; - dc_sync->cl.tx_done = NULL; /* operate in blocking mode */ - dc_sync->cl.tx_block = true; - dc_sync->cl.tx_tout = 500; /* by half a second */ - dc_sync->cl.knows_txdone = false; /* depending upon protocol */ - dc_sync->async = false; - - /* ASync mailbox is listed second in 'mboxes' property */ - dc_async->mbox = mbox_request_channel(&dc_async->cl, 1); - /* Populate data packet */ - /* ap.xxx = 123; etc */ - /* Send async message to remote */ - mbox_send_message(dc_async->mbox, &ap); - - /* Sync mailbox is listed first in 'mboxes' property */ - dc_sync->mbox = mbox_request_channel(&dc_sync->cl, 0); - /* Populate data packet */ - /* sp.abc = 123; etc */ - /* Send message to remote in blocking mode */ - mbox_send_message(dc_sync->mbox, &sp); - /* At this point 'sp' has been sent */ - - /* Now wait for async chan to be done */ - wait_for_completion(&dc_async->c); - } -- 2.39.3 (Apple Git-146) ^ permalink raw reply [flat|nested] 12+ messages in thread
* [PATCH 2/2] mailbox: Documentation: add the latest documentation 2024-10-19 19:55 [PATCH 1/2] mailbox: Documentation: remove the old documentation anish kumar @ 2024-10-19 19:55 ` anish kumar 2024-10-24 18:42 ` anish kumar 2024-10-25 3:38 ` Bagas Sanjaya 0 siblings, 2 replies; 12+ messages in thread From: anish kumar @ 2024-10-19 19:55 UTC (permalink / raw) To: jassisinghbrar, corbet; +Cc: linux-doc, linux-kernel, anish kumar [-- Warning: decoded text below may be mangled, UTF-8 assumed --] [-- Attachment #1: Type: text/plain; charset=y, Size: 23131 bytes --] 1. added client documentation 2. added controller documentation. 3. added framework documentation Signed-off-by: anish kumar <yesanishhere@gmail.com> --- Documentation/driver-api/mailbox/client.rst | 192 ++++++++++++++++++ Documentation/driver-api/mailbox/core.rst | 182 +++++++++++++++++ Documentation/driver-api/mailbox/index.rst | 45 ++++ .../writing_mailbox_controller_drivers.rst | 179 ++++++++++++++++ 4 files changed, 598 insertions(+) create mode 100644 Documentation/driver-api/mailbox/client.rst create mode 100644 Documentation/driver-api/mailbox/core.rst create mode 100644 Documentation/driver-api/mailbox/index.rst create mode 100644 Documentation/driver-api/mailbox/writing_mailbox_controller_drivers.rst diff --git a/Documentation/driver-api/mailbox/client.rst b/Documentation/driver-api/mailbox/client.rst new file mode 100644 index 000000000000..9088f8373423 --- /dev/null +++ b/Documentation/driver-api/mailbox/client.rst @@ -0,0 +1,192 @@ +Mailbox Client Documentation +============================ + +Overview +-------- +The mailbox client driver is responsible for sending and receiving messages +to and from a remote processor. It uses mailbox APIs provided by the +mailbox framework. + +Mailbox Structure +----------------- +The mailbox structure is defined as follows: + +.. code-block:: c + + struct mbox_client { + //device associated with the mailbox + struct device *dev; + // callback for transmission completion + void (*tx_done)(struct mbox_client *client); + // callback to prepare for sending a message + void (*tx_prepare)(struct mbox_client *client); + // callback for received messages + void (*rx_callback)(struct mbox_client *client, void *data); + // flag to indicate if transmission should block + bool tx_block; + // indicates if the client knows when transmission is done + bool knows_txdone; + }; + +Key Functions +------------- +1. Requesting a Mailbox Channel + - **Function**: `mbox_request_channel(struct mbox_client *client, + unsigned int channel)` + - **Description**: Requests a mailbox channel for sending messages. + - **Parameters**: + - `client`: Pointer to the mailbox client structure. + - `channel`: The specific mailbox channel to request. + - **Returns**: A pointer to the mailbox channel on success, or an error + code on failure. + +2. Sending a Message + - **Function**: `mbox_send_message(struct mbox_chan *chan, void *msg)` + - **Description**: Sends a message through the mailbox channel. + - **Parameters**: + - `chan`: The mailbox channel used for communication. + - `msg`: Pointer to the message to be sent (usually NULL for dummy + messages). + - **Returns**: 0 on success, or a negative error code on failure. + +3. Transmitting Completion + - **Function**: `mbox_client_txdone(struct mbox_chan *chan, unsigned int + msg_id)` + - **Description**: Notifies the mailbox framework that message + transmission is complete. + - **Parameters**: + - `chan`: The mailbox channel associated with the message. + - `msg_id`: The identifier of the message that was transmitted. + +Usage Example +------------- +In a typical mailbox client driver, the following steps are typically +performed: + +1. Initialize the Mailbox Client: + + .. code-block:: c + + struct mbox_client my_mbox_client = { + .dev = &my_device, + .tx_done = my_tx_done_callback, + .rx_callback = my_rx_callback, + .tx_block = false, + .knows_txdone = true, + }; + +2. Request a Mailbox Channel: + + .. code-block:: c + + mbox_chan = mbox_request_channel(&my_mbox_client, 0); + if (IS_ERR(mbox_chan)) { + // Handle error + } + +3. Send a Message: + + .. code-block:: c + + int ret = mbox_send_message(mbox_chan, NULL); // Sending a dummy message + if (ret < 0) { + // Handle error + } + +4. Complete Transmission: + + .. code-block:: c + + mbox_client_txdone(mbox_chan, 0); + +Interrupt Handling +------------------ +The mailbox interface can trigger interrupts upon message receipt. Handlers +should be implemented in the `rx_callback` function defined in the mailbox +client structure to process incoming messages. + +Example Mailbox Client Driver +----------------------------- +.. code-block:: c + + struct demo_client { + struct mbox_client cl; + struct mbox_chan *mbox; + struct completion c; + bool async; + /* ... */ + }; + + /* + * This is the handler for data received from remote. The behaviour is purely + * dependent upon the protocol. This is just an example. + */ + static void message_from_remote(struct mbox_client *cl, void *mssg) + { + struct demo_client *dc = container_of(cl, struct demo_client, cl); + if (dc->async) { + if (is_an_ack(mssg)) { + /* An ACK to our last sample sent */ + return; /* Or do something else here */ + } else { /* A new message from remote */ + queue_req(mssg); + } + } else { + /* Remote f/w sends only ACK packets on this channel */ + return; + } + } + + static void sample_sent(struct mbox_client *cl, void *mssg, int r) + { + struct demo_client *dc = container_of(cl, struct demo_client, cl); + complete(&dc->c); + } + + static void client_demo(struct platform_device *pdev) + { + struct demo_client *dc_sync, *dc_async; + /* The controller already knows async_pkt and sync_pkt */ + struct async_pkt ap; + struct sync_pkt sp; + + dc_sync = kzalloc(sizeof(*dc_sync), GFP_KERNEL); + dc_async = kzalloc(sizeof(*dc_async), GFP_KERNEL); + + /* Populate non-blocking mode client */ + dc_async->cl.dev = &pdev->dev; + dc_async->cl.rx_callback = message_from_remote; + dc_async->cl.tx_done = sample_sent; + dc_async->cl.tx_block = false; + dc_async->cl.tx_tout = 0; /* doesn't matter here */ + dc_async->cl.knows_txdone = false; /* depending upon protocol */ + dc_async->async = true; + init_completion(&dc_async->c); + + /* Populate blocking mode client */ + dc_sync->cl.dev = &pdev->dev; + dc_sync->cl.rx_callback = message_from_remote; + dc_sync->cl.tx_done = NULL; /* operate in blocking mode */ + dc_sync->cl.tx_block = true; + dc_sync->cl.tx_tout = 500; /* by half a second */ + dc_sync->cl.knows_txdone = false; /* depending upon protocol */ + dc_sync->async = false; + + /* ASync mailbox is listed second in 'mboxes' property */ + dc_async->mbox = mbox_request_channel(&dc_async->cl, 1); + /* Populate data packet */ + /* ap.xxx = 123; etc */ + /* Send async message to remote */ + mbox_send_message(dc_async->mbox, &ap); + + /* Sync mailbox is listed first in 'mboxes' property */ + dc_sync->mbox = mbox_request_channel(&dc_sync->cl, 0); + /* Populate data packet */ + /* sp.abc = 123; etc */ + /* Send message to remote in blocking mode */ + mbox_send_message(dc_sync->mbox, &sp); + /* At this point 'sp' has been sent */ + + /* Now wait for async chan to be done */ + wait_for_completion(&dc_async->c); + } diff --git a/Documentation/driver-api/mailbox/core.rst b/Documentation/driver-api/mailbox/core.rst new file mode 100644 index 000000000000..d1220086da67 --- /dev/null +++ b/Documentation/driver-api/mailbox/core.rst @@ -0,0 +1,182 @@ +===================== +mailbox documentation +===================== + +Hardware Introduction +===================== + +Mailbox hardware is a specialized component found in multi-core +processors and embedded systems that facilitates inter-processor +communication (IPC) or communication between different hardware +components. It provides a structured mechanism for sending and +receiving messages, allowing various processors or devices to +exchange data efficiently. Here's an overview of its key +characteristics and functions: + +Key Characteristics of Mailbox Hardware +Interrupt Handling: Many mailbox implementations support +interrupt-driven communication. This allows a receiving processor +to be alerted when a new message arrives, facilitating immediate +processing without polling the mailbox constantly. + +Hardware Registers: Mailbox hardware often includes registers for +configuration and status monitoring. These registers can be used +to control the mailbox's behavior, check for available messages, +or acknowledge message receipt. + +Support for Multiple Protocols: Mailboxes can support various +communication protocols, enabling interoperability between different +hardware components and simplifying the integration of diverse systems. + +Synchronous and Asynchronous Modes: Mailbox hardware can operate in +both synchronous and asynchronous modes. In synchronous mode, the +sender may wait for the receiver to acknowledge receipt before +proceeding, while in asynchronous mode, the sender can continue +executing other tasks immediately after sending the message. + + +Mailbox framework design +======================== + +The mailbox facilitates interprocessor communication by allowing processors to +exchange messages or signals. The mailbox framework consists of: + +Mailbox Controller: This is platform-specific and is responsible for configuring +and managing interrupts from the remote processor. It offers a generic API for +the mailbox client. + +Mailbox Client: This component handles the sending and receiving of messages. + + +............................................................................ +: client driver client_a client_b : +............................................................................ + ^-------------------^ + | + | +............................................................................ +: controller framework mailbox : +....................................|....................................... + | + | +............................................................................ +: controller driver device specific : +....................................|....................................... + | + | +kernel | +............................................................................ +hardware | + | + | +............................................................................ +: remote processor : +............................................................................ + + +In the context of a mailbox framework, a channel refers to a dedicated +communication pathway between two or more processors or components. By using +channels, the framework abstracts the complexity of interprocessor communication. + +Data Structures +================ + +- **struct mbox_client** + This structure represents a client that communicates over a mailbox + channel. It holds information such as: + - A pointer to the device associated with the client (`dev`). + - Callback functions for handling message transmission events, including: + - `rx_callback`: Called when a message is received. + - `tx_done`: Called when a message transmission is acknowledged. + - Flags that specify the client’s configuration, such as whether it operates + in blocking mode. + +- **struct mbox_chan** + This structure represents an individual mailbox channel. It maintains the + state required for message queuing and transmission. Key members include: + - `msg_data`: Array of messages queued for transmission. + - `msg_count`: Number of messages currently queued. + - `msg_free`: Index of the next free slot in the message queue. + - `active_req`: Pointer to the currently active message being transmitted. + - Synchronization primitives to manage access from multiple contexts. + +- **struct mbox_controller** + This structure represents a mailbox controller that manages multiple + channels. It includes: + - A pointer to the device managing the mailbox. + - Operations for sending and receiving messages, as well as initializing + and shutting down the mailbox. + - A list of associated channels and the total number of channels available. + +controller framework APIs +========================= + +``struct `mbox_controller` Initialization +----------------------------------------- + +Just like any other kernel framework, the whole mailbox controller registration +relies on the driver filling a structure and registering against the +framework. In our case, that structure is mbox_controller. + +The first thing you need to do in your driver is to allocate this +structure. Any of the usual memory allocators will do, but you'll also +need to initialize a few fields in there: + +- ``dev``: should hold the pointer to the ``struct device`` associated + to your current driver instance. + +- ``ops``: Operators that work on each communication channel. + +- ``chans``: Array of channels. + +- ``num_chans``: Number of channels in the `chans` array. + +- ``txdone_irq``: Indicates if the controller can report to the API + when the last transmitted data was read by the + remote (e.g., if it has a TX ACK interrupt). + +All the below fields are not mandatory. + +- ``txdone_poll``: Indicates if the controller can read but not report + the TX done. For example, some register may show + the TX status, but no interrupt is raised. This + field is ignored if `txdone_irq` is set. + +- ``txpoll_period``: If `txdone_poll` is in effect, the API polls for + the last TX status after this many milliseconds. + +- ``of_xlate``: Controller driver-specific mapping of channel via + Device Tree (DT). + + +Key Functions +------------- + +- **int devm_mbox_controller_register(struct mbox_controller *mbox)** + This function registers a mailbox controller with the kernel. It makes the + channels associated with the controller available for client requests. The + function performs sanity checks on the controller structure to ensure all + necessary fields are populated. + +- **struct mbox_chan *mbox_request_channel(struct mbox_client *cl, int index)** + This function requests a mailbox channel for a specified client, identified + by an index. It searches for the appropriate mailbox channel, and if found, + it returns a pointer to the channel. If the request fails (e.g., if the + index is invalid), it returns an error pointer. + +- **void mbox_free_channel(struct mbox_chan *chan)** + This function releases a mailbox channel that was previously allocated for a + client. It ensures that the channel can be reused by other clients. If any + messages are still in the queue, they are aborted, and no callbacks are made. + +- **int mbox_send_message(struct mbox_chan *chan, void *mssg)** + This function is used by clients to send a message through the specified + mailbox channel. The function can operate in either blocking or non-blocking + mode, depending on the client’s configuration. It will queue the message for + transmission and notify the client once the message is acknowledged. + +- **void mbox_chan_received_data(struct mbox_chan *chan, void *mssg)** + This function is called by the controller driver to notify the mailbox + framework that a message has been received on the specified channel. The + received message is then passed to the appropriate client's `rx_callback` + function for processing. diff --git a/Documentation/driver-api/mailbox/index.rst b/Documentation/driver-api/mailbox/index.rst new file mode 100644 index 000000000000..e254a8fdb66a --- /dev/null +++ b/Documentation/driver-api/mailbox/index.rst @@ -0,0 +1,45 @@ +======================= +Mailbox documentation +======================= + +Mailbox documentation provides documents for various aspects of mailbox +framework. + +Mailbox development documentation +--------------------------------- + +This book helps with mailbox internal APIs and guide for mailbox device +driver writers. + +.. toctree:: + :maxdepth: 1 + + core + +mailbox controller driver documentation +------------------------------ + +This book is a guide to device driver writers on how to register +mailbox controller to the mailbox framework. + +.. toctree:: + :maxdepth: 1 + + writing_mailbox_controller_drivers + +mailbox client driver documentation +------------------------------ + +This book is a guide to mailbox client driver writers. + +.. toctree:: + :maxdepth: 1 + + client + +.. only:: subproject and html + + Indices + ======= + + * :ref:`genindex` diff --git a/Documentation/driver-api/mailbox/writing_mailbox_controller_drivers.rst b/Documentation/driver-api/mailbox/writing_mailbox_controller_drivers.rst new file mode 100644 index 000000000000..2a82645c1357 --- /dev/null +++ b/Documentation/driver-api/mailbox/writing_mailbox_controller_drivers.rst @@ -0,0 +1,179 @@ +.. SPDX-License-Identifier: GPL-2.0 + +.. _writing_mailbox_controller_drivers: + +================================== +Writing Mailbox Controller Drivers +================================== + +Introduction +============ + +This document serves as a basic guideline for driver programmers that need +to hack a new mailbox controller driver or understand the essentials of +the existing ones. + +Driver Boilerplate +================== + +As a bare minimum, a mailbox controller driver needs to call +``mbox_controller_register`` function to register with the framework. + +A basic driver skeleton could look like this for a mailbox hardware that +has the following characteristics: +a. It supports only a single channel, i.e., only the remote processor can + send interrupts. +b. Data transfer is over the registers associated with mailbox hardware. +c. Mailbox hardware is configured to receive interrupts. +d. When the remote processor is ready to send data, it triggers a mailbox + interrupt. +e. As part of interrupt handling by Linux, it copies data from the registers. + +.. code-block:: c + + #include <linux/device.h> + #include <linux/interrupt.h> + #include <linux/io.h> + #include <linux/kernel.h> + #include <linux/mailbox_controller.h> + #include <linux/module.h> + #include <linux/of.h> + #include <linux/platform_device.h> + #define DRIVER_NAME "dummy_controller" + + struct dummy_mbox { + struct device *dev; + struct mbox_controller controller; + int irq; + }; + + static void dummy_mbox_receive(struct mbox_chan *chan) + { + struct dummy_mbox *mbox = chan->con_priv; + int val; + + // Data copied from registers + val = read_register(); + mbox_chan_received_data(chan, &val); + } + + static irqreturn_t dummy_mbox_irq_handler(int irq, void *data) + { + struct mbox_chan *chan = data; + struct dummy_mbox *mbox = chan->con_priv; + u32 reg; + + // Read registers to see if data is received + dummy_mbox_receive(chan); + mbox_chan_txdone(chan, 0); + return reg ? IRQ_HANDLED : IRQ_NONE; + } + + static int dummy_mbox_send_data(struct mbox_chan *chan, void *data) + { + // Write data in registers to send it to the remote processor + return 0; + } + + static int dummy_mbox_startup(struct mbox_chan *chan) + { + struct dummy_mbox *mbox = chan->con_priv; + u32 reg; + int ret; + + ret = devm_request_irq(mbox->dev, mbox->irq, dummy_mbox_irq_handler, 0, + DRIVER_NAME, chan); + if (ret < 0) { + dev_err(mbox->dev, "Cannot request irq\n"); + return ret; + } + + /* Register write to enable IRQ generation */ + + return 0; + } + + static void dummy_mbox_shutdown(struct mbox_chan *chan) + { + struct dummy_mbox *mbox = chan->con_priv; + + /* Disable interrupt generation */ + devm_free_irq(mbox->dev, mbox->irq, chan); + } + + static const struct mbox_chan_ops dummy_mbox_ops = { + .send_data = dummy_mbox_send_data, + .startup = dummy_mbox_startup, + .shutdown = dummy_mbox_shutdown, + }; + + static int dummy_mbox_probe(struct platform_device *pdev) + { + struct dummy_mbox *mbox; + struct mbox_chan *chans; + int ret; + + mbox = devm_kzalloc(&pdev->dev, sizeof(*mbox), GFP_KERNEL); + if (!mbox) + return -ENOMEM; + + /* Allocate one channel */ + chans = devm_kzalloc(&pdev->dev, sizeof(*chans), GFP_KERNEL); + if (!chans) + return -ENOMEM; + + mbox->base = devm_platform_ioremap_resource(pdev, 0); + if (IS_ERR(mbox->base)) + return PTR_ERR(mbox->base); + + mbox->irq = platform_get_irq(pdev, 0); + if (mbox->irq < 0) + return mbox->irq; + + mbox->dev = &pdev->dev; + + /* Hardware supports only one channel. */ + mbox->controller.dev = mbox->dev; + mbox->controller.num_chans = 1; + mbox->controller.chans = chans; + mbox->controller.ops = &dummy_mbox_ops; + mbox->controller.txdone_irq = true; + + ret = devm_mbox_controller_register(mbox->dev, &mbox->controller); + if (ret) { + dev_err(&pdev->dev, "Could not register mailbox controller\n"); + return ret; + } + + return ret; + } + + static const struct of_device_id dummy_mbox_match[] = { + { .compatible = "dummy,dummy-mailbox" }, + { }, + }; + + MODULE_DEVICE_TABLE(of, dummy_mbox_match); + + static struct platform_driver dummy_mbox_driver = { + .probe = dummy_mbox_probe, + .driver = { + .name = DRIVER_NAME, + .of_match_table = dummy_mbox_match, + }, + }; + + module_platform_driver(dummy_mbox_driver); + MODULE_LICENSE("GPL v2"); + MODULE_DESCRIPTION("Dummy mailbox controller driver"); + +In the above code, a couple of things are done: +a. The controller is registered in the probe along with callbacks, which in + this case are the bare minimum: ``startup``, ``shutdown``, and + ``send_data``. +b. IRQ is registered to get notifications from the remote processor. +c. In the IRQ handler, registers are read to copy data, and + ``mbox_chan_received_data`` is called to hand over the data to the client. +d. ``mbox_chan_txdone`` is called to let the framework know that this data + is the last data and no more data is to be expected for the current transfer. + -- 2.39.3 (Apple Git-146) ^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH 2/2] mailbox: Documentation: add the latest documentation 2024-10-19 19:55 ` [PATCH 2/2] mailbox: Documentation: add the latest documentation anish kumar @ 2024-10-24 18:42 ` anish kumar 2024-10-25 3:38 ` Bagas Sanjaya 1 sibling, 0 replies; 12+ messages in thread From: anish kumar @ 2024-10-24 18:42 UTC (permalink / raw) To: jassisinghbrar, corbet; +Cc: linux-doc, linux-kernel Jassi, Wondering if you have any comments. Thanks. On Sat, Oct 19, 2024 at 12:55 PM anish kumar <yesanishhere@gmail.com> wrote: > > 1. added client documentation > 2. added controller documentation. > 3. added framework documentation > > Signed-off-by: anish kumar <yesanishhere@gmail.com> > --- > Documentation/driver-api/mailbox/client.rst | 192 ++++++++++++++++++ > Documentation/driver-api/mailbox/core.rst | 182 +++++++++++++++++ > Documentation/driver-api/mailbox/index.rst | 45 ++++ > .../writing_mailbox_controller_drivers.rst | 179 ++++++++++++++++ > 4 files changed, 598 insertions(+) > create mode 100644 Documentation/driver-api/mailbox/client.rst > create mode 100644 Documentation/driver-api/mailbox/core.rst > create mode 100644 Documentation/driver-api/mailbox/index.rst > create mode 100644 Documentation/driver-api/mailbox/writing_mailbox_controller_drivers.rst > > diff --git a/Documentation/driver-api/mailbox/client.rst b/Documentation/driver-api/mailbox/client.rst > new file mode 100644 > index 000000000000..9088f8373423 > --- /dev/null > +++ b/Documentation/driver-api/mailbox/client.rst > @@ -0,0 +1,192 @@ > +Mailbox Client Documentation > +============================ > + > +Overview > +-------- > +The mailbox client driver is responsible for sending and receiving messages > +to and from a remote processor. It uses mailbox APIs provided by the > +mailbox framework. > + > +Mailbox Structure > +----------------- > +The mailbox structure is defined as follows: > + > +.. code-block:: c > + > + struct mbox_client { > + //device associated with the mailbox > + struct device *dev; > + // callback for transmission completion > + void (*tx_done)(struct mbox_client *client); > + // callback to prepare for sending a message > + void (*tx_prepare)(struct mbox_client *client); > + // callback for received messages > + void (*rx_callback)(struct mbox_client *client, void *data); > + // flag to indicate if transmission should block > + bool tx_block; > + // indicates if the client knows when transmission is done > + bool knows_txdone; > + }; > + > +Key Functions > +------------- > +1. Requesting a Mailbox Channel > + - **Function**: `mbox_request_channel(struct mbox_client *client, > + unsigned int channel)` > + - **Description**: Requests a mailbox channel for sending messages. > + - **Parameters**: > + - `client`: Pointer to the mailbox client structure. > + - `channel`: The specific mailbox channel to request. > + - **Returns**: A pointer to the mailbox channel on success, or an error > + code on failure. > + > +2. Sending a Message > + - **Function**: `mbox_send_message(struct mbox_chan *chan, void *msg)` > + - **Description**: Sends a message through the mailbox channel. > + - **Parameters**: > + - `chan`: The mailbox channel used for communication. > + - `msg`: Pointer to the message to be sent (usually NULL for dummy > + messages). > + - **Returns**: 0 on success, or a negative error code on failure. > + > +3. Transmitting Completion > + - **Function**: `mbox_client_txdone(struct mbox_chan *chan, unsigned int > + msg_id)` > + - **Description**: Notifies the mailbox framework that message > + transmission is complete. > + - **Parameters**: > + - `chan`: The mailbox channel associated with the message. > + - `msg_id`: The identifier of the message that was transmitted. > + > +Usage Example > +------------- > +In a typical mailbox client driver, the following steps are typically > +performed: > + > +1. Initialize the Mailbox Client: > + > + .. code-block:: c > + > + struct mbox_client my_mbox_client = { > + .dev = &my_device, > + .tx_done = my_tx_done_callback, > + .rx_callback = my_rx_callback, > + .tx_block = false, > + .knows_txdone = true, > + }; > + > +2. Request a Mailbox Channel: > + > + .. code-block:: c > + > + mbox_chan = mbox_request_channel(&my_mbox_client, 0); > + if (IS_ERR(mbox_chan)) { > + // Handle error > + } > + > +3. Send a Message: > + > + .. code-block:: c > + > + int ret = mbox_send_message(mbox_chan, NULL); // Sending a dummy message > + if (ret < 0) { > + // Handle error > + } > + > +4. Complete Transmission: > + > + .. code-block:: c > + > + mbox_client_txdone(mbox_chan, 0); > + > +Interrupt Handling > +------------------ > +The mailbox interface can trigger interrupts upon message receipt. Handlers > +should be implemented in the `rx_callback` function defined in the mailbox > +client structure to process incoming messages. > + > +Example Mailbox Client Driver > +----------------------------- > +.. code-block:: c > + > + struct demo_client { > + struct mbox_client cl; > + struct mbox_chan *mbox; > + struct completion c; > + bool async; > + /* ... */ > + }; > + > + /* > + * This is the handler for data received from remote. The behaviour is purely > + * dependent upon the protocol. This is just an example. > + */ > + static void message_from_remote(struct mbox_client *cl, void *mssg) > + { > + struct demo_client *dc = container_of(cl, struct demo_client, cl); > + if (dc->async) { > + if (is_an_ack(mssg)) { > + /* An ACK to our last sample sent */ > + return; /* Or do something else here */ > + } else { /* A new message from remote */ > + queue_req(mssg); > + } > + } else { > + /* Remote f/w sends only ACK packets on this channel */ > + return; > + } > + } > + > + static void sample_sent(struct mbox_client *cl, void *mssg, int r) > + { > + struct demo_client *dc = container_of(cl, struct demo_client, cl); > + complete(&dc->c); > + } > + > + static void client_demo(struct platform_device *pdev) > + { > + struct demo_client *dc_sync, *dc_async; > + /* The controller already knows async_pkt and sync_pkt */ > + struct async_pkt ap; > + struct sync_pkt sp; > + > + dc_sync = kzalloc(sizeof(*dc_sync), GFP_KERNEL); > + dc_async = kzalloc(sizeof(*dc_async), GFP_KERNEL); > + > + /* Populate non-blocking mode client */ > + dc_async->cl.dev = &pdev->dev; > + dc_async->cl.rx_callback = message_from_remote; > + dc_async->cl.tx_done = sample_sent; > + dc_async->cl.tx_block = false; > + dc_async->cl.tx_tout = 0; /* doesn't matter here */ > + dc_async->cl.knows_txdone = false; /* depending upon protocol */ > + dc_async->async = true; > + init_completion(&dc_async->c); > + > + /* Populate blocking mode client */ > + dc_sync->cl.dev = &pdev->dev; > + dc_sync->cl.rx_callback = message_from_remote; > + dc_sync->cl.tx_done = NULL; /* operate in blocking mode */ > + dc_sync->cl.tx_block = true; > + dc_sync->cl.tx_tout = 500; /* by half a second */ > + dc_sync->cl.knows_txdone = false; /* depending upon protocol */ > + dc_sync->async = false; > + > + /* ASync mailbox is listed second in 'mboxes' property */ > + dc_async->mbox = mbox_request_channel(&dc_async->cl, 1); > + /* Populate data packet */ > + /* ap.xxx = 123; etc */ > + /* Send async message to remote */ > + mbox_send_message(dc_async->mbox, &ap); > + > + /* Sync mailbox is listed first in 'mboxes' property */ > + dc_sync->mbox = mbox_request_channel(&dc_sync->cl, 0); > + /* Populate data packet */ > + /* sp.abc = 123; etc */ > + /* Send message to remote in blocking mode */ > + mbox_send_message(dc_sync->mbox, &sp); > + /* At this point 'sp' has been sent */ > + > + /* Now wait for async chan to be done */ > + wait_for_completion(&dc_async->c); > + } > diff --git a/Documentation/driver-api/mailbox/core.rst b/Documentation/driver-api/mailbox/core.rst > new file mode 100644 > index 000000000000..d1220086da67 > --- /dev/null > +++ b/Documentation/driver-api/mailbox/core.rst > @@ -0,0 +1,182 @@ > +===================== > +mailbox documentation > +===================== > + > +Hardware Introduction > +===================== > + > +Mailbox hardware is a specialized component found in multi-core > +processors and embedded systems that facilitates inter-processor > +communication (IPC) or communication between different hardware > +components. It provides a structured mechanism for sending and > +receiving messages, allowing various processors or devices to > +exchange data efficiently. Here's an overview of its key > +characteristics and functions: > + > +Key Characteristics of Mailbox Hardware > +Interrupt Handling: Many mailbox implementations support > +interrupt-driven communication. This allows a receiving processor > +to be alerted when a new message arrives, facilitating immediate > +processing without polling the mailbox constantly. > + > +Hardware Registers: Mailbox hardware often includes registers for > +configuration and status monitoring. These registers can be used > +to control the mailbox's behavior, check for available messages, > +or acknowledge message receipt. > + > +Support for Multiple Protocols: Mailboxes can support various > +communication protocols, enabling interoperability between different > +hardware components and simplifying the integration of diverse systems. > + > +Synchronous and Asynchronous Modes: Mailbox hardware can operate in > +both synchronous and asynchronous modes. In synchronous mode, the > +sender may wait for the receiver to acknowledge receipt before > +proceeding, while in asynchronous mode, the sender can continue > +executing other tasks immediately after sending the message. > + > + > +Mailbox framework design > +======================== > + > +The mailbox facilitates interprocessor communication by allowing processors to > +exchange messages or signals. The mailbox framework consists of: > + > +Mailbox Controller: This is platform-specific and is responsible for configuring > +and managing interrupts from the remote processor. It offers a generic API for > +the mailbox client. > + > +Mailbox Client: This component handles the sending and receiving of messages. > + > + > +............................................................................ > +: client driver client_a client_b : > +............................................................................ > + ^-------------------^ > + | > + | > +............................................................................ > +: controller framework mailbox : > +....................................|....................................... > + | > + | > +............................................................................ > +: controller driver device specific : > +....................................|....................................... > + | > + | > +kernel | > +............................................................................ > +hardware | > + | > + | > +............................................................................ > +: remote processor : > +............................................................................ > + > + > +In the context of a mailbox framework, a channel refers to a dedicated > +communication pathway between two or more processors or components. By using > +channels, the framework abstracts the complexity of interprocessor communication. > + > +Data Structures > +================ > + > +- **struct mbox_client** > + This structure represents a client that communicates over a mailbox > + channel. It holds information such as: > + - A pointer to the device associated with the client (`dev`). > + - Callback functions for handling message transmission events, including: > + - `rx_callback`: Called when a message is received. > + - `tx_done`: Called when a message transmission is acknowledged. > + - Flags that specify the client’s configuration, such as whether it operates > + in blocking mode. > + > +- **struct mbox_chan** > + This structure represents an individual mailbox channel. It maintains the > + state required for message queuing and transmission. Key members include: > + - `msg_data`: Array of messages queued for transmission. > + - `msg_count`: Number of messages currently queued. > + - `msg_free`: Index of the next free slot in the message queue. > + - `active_req`: Pointer to the currently active message being transmitted. > + - Synchronization primitives to manage access from multiple contexts. > + > +- **struct mbox_controller** > + This structure represents a mailbox controller that manages multiple > + channels. It includes: > + - A pointer to the device managing the mailbox. > + - Operations for sending and receiving messages, as well as initializing > + and shutting down the mailbox. > + - A list of associated channels and the total number of channels available. > + > +controller framework APIs > +========================= > + > +``struct `mbox_controller` Initialization > +----------------------------------------- > + > +Just like any other kernel framework, the whole mailbox controller registration > +relies on the driver filling a structure and registering against the > +framework. In our case, that structure is mbox_controller. > + > +The first thing you need to do in your driver is to allocate this > +structure. Any of the usual memory allocators will do, but you'll also > +need to initialize a few fields in there: > + > +- ``dev``: should hold the pointer to the ``struct device`` associated > + to your current driver instance. > + > +- ``ops``: Operators that work on each communication channel. > + > +- ``chans``: Array of channels. > + > +- ``num_chans``: Number of channels in the `chans` array. > + > +- ``txdone_irq``: Indicates if the controller can report to the API > + when the last transmitted data was read by the > + remote (e.g., if it has a TX ACK interrupt). > + > +All the below fields are not mandatory. > + > +- ``txdone_poll``: Indicates if the controller can read but not report > + the TX done. For example, some register may show > + the TX status, but no interrupt is raised. This > + field is ignored if `txdone_irq` is set. > + > +- ``txpoll_period``: If `txdone_poll` is in effect, the API polls for > + the last TX status after this many milliseconds. > + > +- ``of_xlate``: Controller driver-specific mapping of channel via > + Device Tree (DT). > + > + > +Key Functions > +------------- > + > +- **int devm_mbox_controller_register(struct mbox_controller *mbox)** > + This function registers a mailbox controller with the kernel. It makes the > + channels associated with the controller available for client requests. The > + function performs sanity checks on the controller structure to ensure all > + necessary fields are populated. > + > +- **struct mbox_chan *mbox_request_channel(struct mbox_client *cl, int index)** > + This function requests a mailbox channel for a specified client, identified > + by an index. It searches for the appropriate mailbox channel, and if found, > + it returns a pointer to the channel. If the request fails (e.g., if the > + index is invalid), it returns an error pointer. > + > +- **void mbox_free_channel(struct mbox_chan *chan)** > + This function releases a mailbox channel that was previously allocated for a > + client. It ensures that the channel can be reused by other clients. If any > + messages are still in the queue, they are aborted, and no callbacks are made. > + > +- **int mbox_send_message(struct mbox_chan *chan, void *mssg)** > + This function is used by clients to send a message through the specified > + mailbox channel. The function can operate in either blocking or non-blocking > + mode, depending on the client’s configuration. It will queue the message for > + transmission and notify the client once the message is acknowledged. > + > +- **void mbox_chan_received_data(struct mbox_chan *chan, void *mssg)** > + This function is called by the controller driver to notify the mailbox > + framework that a message has been received on the specified channel. The > + received message is then passed to the appropriate client's `rx_callback` > + function for processing. > diff --git a/Documentation/driver-api/mailbox/index.rst b/Documentation/driver-api/mailbox/index.rst > new file mode 100644 > index 000000000000..e254a8fdb66a > --- /dev/null > +++ b/Documentation/driver-api/mailbox/index.rst > @@ -0,0 +1,45 @@ > +======================= > +Mailbox documentation > +======================= > + > +Mailbox documentation provides documents for various aspects of mailbox > +framework. > + > +Mailbox development documentation > +--------------------------------- > + > +This book helps with mailbox internal APIs and guide for mailbox device > +driver writers. > + > +.. toctree:: > + :maxdepth: 1 > + > + core > + > +mailbox controller driver documentation > +------------------------------ > + > +This book is a guide to device driver writers on how to register > +mailbox controller to the mailbox framework. > + > +.. toctree:: > + :maxdepth: 1 > + > + writing_mailbox_controller_drivers > + > +mailbox client driver documentation > +------------------------------ > + > +This book is a guide to mailbox client driver writers. > + > +.. toctree:: > + :maxdepth: 1 > + > + client > + > +.. only:: subproject and html > + > + Indices > + ======= > + > + * :ref:`genindex` > diff --git a/Documentation/driver-api/mailbox/writing_mailbox_controller_drivers.rst b/Documentation/driver-api/mailbox/writing_mailbox_controller_drivers.rst > new file mode 100644 > index 000000000000..2a82645c1357 > --- /dev/null > +++ b/Documentation/driver-api/mailbox/writing_mailbox_controller_drivers.rst > @@ -0,0 +1,179 @@ > +.. SPDX-License-Identifier: GPL-2.0 > + > +.. _writing_mailbox_controller_drivers: > + > +================================== > +Writing Mailbox Controller Drivers > +================================== > + > +Introduction > +============ > + > +This document serves as a basic guideline for driver programmers that need > +to hack a new mailbox controller driver or understand the essentials of > +the existing ones. > + > +Driver Boilerplate > +================== > + > +As a bare minimum, a mailbox controller driver needs to call > +``mbox_controller_register`` function to register with the framework. > + > +A basic driver skeleton could look like this for a mailbox hardware that > +has the following characteristics: > +a. It supports only a single channel, i.e., only the remote processor can > + send interrupts. > +b. Data transfer is over the registers associated with mailbox hardware. > +c. Mailbox hardware is configured to receive interrupts. > +d. When the remote processor is ready to send data, it triggers a mailbox > + interrupt. > +e. As part of interrupt handling by Linux, it copies data from the registers. > + > +.. code-block:: c > + > + #include <linux/device.h> > + #include <linux/interrupt.h> > + #include <linux/io.h> > + #include <linux/kernel.h> > + #include <linux/mailbox_controller.h> > + #include <linux/module.h> > + #include <linux/of.h> > + #include <linux/platform_device.h> > + #define DRIVER_NAME "dummy_controller" > + > + struct dummy_mbox { > + struct device *dev; > + struct mbox_controller controller; > + int irq; > + }; > + > + static void dummy_mbox_receive(struct mbox_chan *chan) > + { > + struct dummy_mbox *mbox = chan->con_priv; > + int val; > + > + // Data copied from registers > + val = read_register(); > + mbox_chan_received_data(chan, &val); > + } > + > + static irqreturn_t dummy_mbox_irq_handler(int irq, void *data) > + { > + struct mbox_chan *chan = data; > + struct dummy_mbox *mbox = chan->con_priv; > + u32 reg; > + > + // Read registers to see if data is received > + dummy_mbox_receive(chan); > + mbox_chan_txdone(chan, 0); > + return reg ? IRQ_HANDLED : IRQ_NONE; > + } > + > + static int dummy_mbox_send_data(struct mbox_chan *chan, void *data) > + { > + // Write data in registers to send it to the remote processor > + return 0; > + } > + > + static int dummy_mbox_startup(struct mbox_chan *chan) > + { > + struct dummy_mbox *mbox = chan->con_priv; > + u32 reg; > + int ret; > + > + ret = devm_request_irq(mbox->dev, mbox->irq, dummy_mbox_irq_handler, 0, > + DRIVER_NAME, chan); > + if (ret < 0) { > + dev_err(mbox->dev, "Cannot request irq\n"); > + return ret; > + } > + > + /* Register write to enable IRQ generation */ > + > + return 0; > + } > + > + static void dummy_mbox_shutdown(struct mbox_chan *chan) > + { > + struct dummy_mbox *mbox = chan->con_priv; > + > + /* Disable interrupt generation */ > + devm_free_irq(mbox->dev, mbox->irq, chan); > + } > + > + static const struct mbox_chan_ops dummy_mbox_ops = { > + .send_data = dummy_mbox_send_data, > + .startup = dummy_mbox_startup, > + .shutdown = dummy_mbox_shutdown, > + }; > + > + static int dummy_mbox_probe(struct platform_device *pdev) > + { > + struct dummy_mbox *mbox; > + struct mbox_chan *chans; > + int ret; > + > + mbox = devm_kzalloc(&pdev->dev, sizeof(*mbox), GFP_KERNEL); > + if (!mbox) > + return -ENOMEM; > + > + /* Allocate one channel */ > + chans = devm_kzalloc(&pdev->dev, sizeof(*chans), GFP_KERNEL); > + if (!chans) > + return -ENOMEM; > + > + mbox->base = devm_platform_ioremap_resource(pdev, 0); > + if (IS_ERR(mbox->base)) > + return PTR_ERR(mbox->base); > + > + mbox->irq = platform_get_irq(pdev, 0); > + if (mbox->irq < 0) > + return mbox->irq; > + > + mbox->dev = &pdev->dev; > + > + /* Hardware supports only one channel. */ > + mbox->controller.dev = mbox->dev; > + mbox->controller.num_chans = 1; > + mbox->controller.chans = chans; > + mbox->controller.ops = &dummy_mbox_ops; > + mbox->controller.txdone_irq = true; > + > + ret = devm_mbox_controller_register(mbox->dev, &mbox->controller); > + if (ret) { > + dev_err(&pdev->dev, "Could not register mailbox controller\n"); > + return ret; > + } > + > + return ret; > + } > + > + static const struct of_device_id dummy_mbox_match[] = { > + { .compatible = "dummy,dummy-mailbox" }, > + { }, > + }; > + > + MODULE_DEVICE_TABLE(of, dummy_mbox_match); > + > + static struct platform_driver dummy_mbox_driver = { > + .probe = dummy_mbox_probe, > + .driver = { > + .name = DRIVER_NAME, > + .of_match_table = dummy_mbox_match, > + }, > + }; > + > + module_platform_driver(dummy_mbox_driver); > + MODULE_LICENSE("GPL v2"); > + MODULE_DESCRIPTION("Dummy mailbox controller driver"); > + > +In the above code, a couple of things are done: > +a. The controller is registered in the probe along with callbacks, which in > + this case are the bare minimum: ``startup``, ``shutdown``, and > + ``send_data``. > +b. IRQ is registered to get notifications from the remote processor. > +c. In the IRQ handler, registers are read to copy data, and > + ``mbox_chan_received_data`` is called to hand over the data to the client. > +d. ``mbox_chan_txdone`` is called to let the framework know that this data > + is the last data and no more data is to be expected for the current transfer. > + > -- > 2.39.3 (Apple Git-146) > ^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH 2/2] mailbox: Documentation: add the latest documentation 2024-10-19 19:55 ` [PATCH 2/2] mailbox: Documentation: add the latest documentation anish kumar 2024-10-24 18:42 ` anish kumar @ 2024-10-25 3:38 ` Bagas Sanjaya 2024-10-25 19:24 ` anish kumar 1 sibling, 1 reply; 12+ messages in thread From: Bagas Sanjaya @ 2024-10-25 3:38 UTC (permalink / raw) To: anish kumar, jassisinghbrar, corbet; +Cc: linux-doc, linux-kernel [-- Attachment #1: Type: text/plain, Size: 37328 bytes --] On Sat, Oct 19, 2024 at 12:55:34PM -0700, anish kumar wrote: > 1. added client documentation > 2. added controller documentation. > 3. added framework documentation One doc topic on each patch, please. > > Signed-off-by: anish kumar <yesanishhere@gmail.com> > --- > Documentation/driver-api/mailbox/client.rst | 192 ++++++++++++++++++ > Documentation/driver-api/mailbox/core.rst | 182 +++++++++++++++++ > Documentation/driver-api/mailbox/index.rst | 45 ++++ > .../writing_mailbox_controller_drivers.rst | 179 ++++++++++++++++ > 4 files changed, 598 insertions(+) > create mode 100644 Documentation/driver-api/mailbox/client.rst > create mode 100644 Documentation/driver-api/mailbox/core.rst > create mode 100644 Documentation/driver-api/mailbox/index.rst > create mode 100644 Documentation/driver-api/mailbox/writing_mailbox_controller_drivers.rst > > diff --git a/Documentation/driver-api/mailbox/client.rst b/Documentation/driver-api/mailbox/client.rst > new file mode 100644 > index 000000000000..9088f8373423 > --- /dev/null > +++ b/Documentation/driver-api/mailbox/client.rst > @@ -0,0 +1,192 @@ > +Mailbox Client Documentation > +============================ > + > +Overview > +-------- > +The mailbox client driver is responsible for sending and receiving messages > +to and from a remote processor. It uses mailbox APIs provided by the > +mailbox framework. > + > +Mailbox Structure > +----------------- > +The mailbox structure is defined as follows: > + > +.. code-block:: c > + > + struct mbox_client { > + //device associated with the mailbox > + struct device *dev; > + // callback for transmission completion > + void (*tx_done)(struct mbox_client *client); > + // callback to prepare for sending a message > + void (*tx_prepare)(struct mbox_client *client); > + // callback for received messages > + void (*rx_callback)(struct mbox_client *client, void *data); > + // flag to indicate if transmission should block > + bool tx_block; > + // indicates if the client knows when transmission is done > + bool knows_txdone; > + }; > + > +Key Functions > +------------- > +1. Requesting a Mailbox Channel > + - **Function**: `mbox_request_channel(struct mbox_client *client, > + unsigned int channel)` > + - **Description**: Requests a mailbox channel for sending messages. > + - **Parameters**: > + - `client`: Pointer to the mailbox client structure. > + - `channel`: The specific mailbox channel to request. > + - **Returns**: A pointer to the mailbox channel on success, or an error > + code on failure. > + > +2. Sending a Message > + - **Function**: `mbox_send_message(struct mbox_chan *chan, void *msg)` > + - **Description**: Sends a message through the mailbox channel. > + - **Parameters**: > + - `chan`: The mailbox channel used for communication. > + - `msg`: Pointer to the message to be sent (usually NULL for dummy > + messages). > + - **Returns**: 0 on success, or a negative error code on failure. > + > +3. Transmitting Completion > + - **Function**: `mbox_client_txdone(struct mbox_chan *chan, unsigned int > + msg_id)` > + - **Description**: Notifies the mailbox framework that message > + transmission is complete. > + - **Parameters**: > + - `chan`: The mailbox channel associated with the message. > + - `msg_id`: The identifier of the message that was transmitted. These functions should've been documented as kernel-doc comments, though. > + > +Usage Example > +------------- > +In a typical mailbox client driver, the following steps are typically > +performed: > + > +1. Initialize the Mailbox Client: > + > + .. code-block:: c > + > + struct mbox_client my_mbox_client = { > + .dev = &my_device, > + .tx_done = my_tx_done_callback, > + .rx_callback = my_rx_callback, > + .tx_block = false, > + .knows_txdone = true, > + }; > + > +2. Request a Mailbox Channel: > + > + .. code-block:: c > + > + mbox_chan = mbox_request_channel(&my_mbox_client, 0); > + if (IS_ERR(mbox_chan)) { > + // Handle error > + } > + > +3. Send a Message: > + > + .. code-block:: c > + > + int ret = mbox_send_message(mbox_chan, NULL); // Sending a dummy message > + if (ret < 0) { > + // Handle error > + } > + > +4. Complete Transmission: > + > + .. code-block:: c > + > + mbox_client_txdone(mbox_chan, 0); > + > +Interrupt Handling > +------------------ > +The mailbox interface can trigger interrupts upon message receipt. Handlers > +should be implemented in the `rx_callback` function defined in the mailbox > +client structure to process incoming messages. > + > +Example Mailbox Client Driver > +----------------------------- > +.. code-block:: c > + > + struct demo_client { > + struct mbox_client cl; > + struct mbox_chan *mbox; > + struct completion c; > + bool async; > + /* ... */ > + }; > + > + /* > + * This is the handler for data received from remote. The behaviour is purely > + * dependent upon the protocol. This is just an example. > + */ > + static void message_from_remote(struct mbox_client *cl, void *mssg) > + { > + struct demo_client *dc = container_of(cl, struct demo_client, cl); > + if (dc->async) { > + if (is_an_ack(mssg)) { > + /* An ACK to our last sample sent */ > + return; /* Or do something else here */ > + } else { /* A new message from remote */ > + queue_req(mssg); > + } > + } else { > + /* Remote f/w sends only ACK packets on this channel */ > + return; > + } > + } > + > + static void sample_sent(struct mbox_client *cl, void *mssg, int r) > + { > + struct demo_client *dc = container_of(cl, struct demo_client, cl); > + complete(&dc->c); > + } > + > + static void client_demo(struct platform_device *pdev) > + { > + struct demo_client *dc_sync, *dc_async; > + /* The controller already knows async_pkt and sync_pkt */ > + struct async_pkt ap; > + struct sync_pkt sp; > + > + dc_sync = kzalloc(sizeof(*dc_sync), GFP_KERNEL); > + dc_async = kzalloc(sizeof(*dc_async), GFP_KERNEL); > + > + /* Populate non-blocking mode client */ > + dc_async->cl.dev = &pdev->dev; > + dc_async->cl.rx_callback = message_from_remote; > + dc_async->cl.tx_done = sample_sent; > + dc_async->cl.tx_block = false; > + dc_async->cl.tx_tout = 0; /* doesn't matter here */ > + dc_async->cl.knows_txdone = false; /* depending upon protocol */ > + dc_async->async = true; > + init_completion(&dc_async->c); > + > + /* Populate blocking mode client */ > + dc_sync->cl.dev = &pdev->dev; > + dc_sync->cl.rx_callback = message_from_remote; > + dc_sync->cl.tx_done = NULL; /* operate in blocking mode */ > + dc_sync->cl.tx_block = true; > + dc_sync->cl.tx_tout = 500; /* by half a second */ > + dc_sync->cl.knows_txdone = false; /* depending upon protocol */ > + dc_sync->async = false; > + > + /* ASync mailbox is listed second in 'mboxes' property */ > + dc_async->mbox = mbox_request_channel(&dc_async->cl, 1); > + /* Populate data packet */ > + /* ap.xxx = 123; etc */ > + /* Send async message to remote */ > + mbox_send_message(dc_async->mbox, &ap); > + > + /* Sync mailbox is listed first in 'mboxes' property */ > + dc_sync->mbox = mbox_request_channel(&dc_sync->cl, 0); > + /* Populate data packet */ > + /* sp.abc = 123; etc */ > + /* Send message to remote in blocking mode */ > + mbox_send_message(dc_sync->mbox, &sp); > + /* At this point 'sp' has been sent */ > + > + /* Now wait for async chan to be done */ > + wait_for_completion(&dc_async->c); > + } > diff --git a/Documentation/driver-api/mailbox/core.rst b/Documentation/driver-api/mailbox/core.rst > new file mode 100644 > index 000000000000..d1220086da67 > --- /dev/null > +++ b/Documentation/driver-api/mailbox/core.rst > @@ -0,0 +1,182 @@ > +===================== > +mailbox documentation > +===================== > + > +Hardware Introduction > +===================== > + > +Mailbox hardware is a specialized component found in multi-core > +processors and embedded systems that facilitates inter-processor > +communication (IPC) or communication between different hardware > +components. It provides a structured mechanism for sending and > +receiving messages, allowing various processors or devices to > +exchange data efficiently. Here's an overview of its key > +characteristics and functions: > + > +Key Characteristics of Mailbox Hardware > +Interrupt Handling: Many mailbox implementations support > +interrupt-driven communication. This allows a receiving processor > +to be alerted when a new message arrives, facilitating immediate > +processing without polling the mailbox constantly. > + > +Hardware Registers: Mailbox hardware often includes registers for > +configuration and status monitoring. These registers can be used > +to control the mailbox's behavior, check for available messages, > +or acknowledge message receipt. > + > +Support for Multiple Protocols: Mailboxes can support various > +communication protocols, enabling interoperability between different > +hardware components and simplifying the integration of diverse systems. > + > +Synchronous and Asynchronous Modes: Mailbox hardware can operate in > +both synchronous and asynchronous modes. In synchronous mode, the > +sender may wait for the receiver to acknowledge receipt before > +proceeding, while in asynchronous mode, the sender can continue > +executing other tasks immediately after sending the message. > + > + > +Mailbox framework design > +======================== > + > +The mailbox facilitates interprocessor communication by allowing processors to > +exchange messages or signals. The mailbox framework consists of: > + > +Mailbox Controller: This is platform-specific and is responsible for configuring > +and managing interrupts from the remote processor. It offers a generic API for > +the mailbox client. > + > +Mailbox Client: This component handles the sending and receiving of messages. > + > + > +............................................................................ > +: client driver client_a client_b : > +............................................................................ > + ^-------------------^ > + | > + | > +............................................................................ > +: controller framework mailbox : > +....................................|....................................... > + | > + | > +............................................................................ > +: controller driver device specific : > +....................................|....................................... > + | > + | > +kernel | > +............................................................................ > +hardware | > + | > + | > +............................................................................ > +: remote processor : > +............................................................................ htmldocs build errors out: Documentation/driver-api/mailbox/core.rst:57: WARNING: Block quote ends without a blank line; unexpected unindent. Documentation/driver-api/mailbox/core.rst:57: CRITICAL: Missing matching underline for section title overline. ............................................................................ : controller framework mailbox : ....................................|....................................... reST markup error: Documentation/driver-api/mailbox/core.rst:57: (SEVERE/4) Missing matching underline for section title overline. ............................................................................ : controller framework mailbox : ....................................|....................................... I have to fix up the design diagram and wrap it: ---- >8 ---- diff --git a/Documentation/driver-api/mailbox/core.rst b/Documentation/driver-api/mailbox/core.rst index d1220086da679f..8d56d81007c11c 100644 --- a/Documentation/driver-api/mailbox/core.rst +++ b/Documentation/driver-api/mailbox/core.rst @@ -47,31 +47,32 @@ the mailbox client. Mailbox Client: This component handles the sending and receiving of messages. +:: -............................................................................ -: client driver client_a client_b : -............................................................................ - ^-------------------^ - | - | -............................................................................ -: controller framework mailbox : -....................................|....................................... - | - | -............................................................................ -: controller driver device specific : -....................................|....................................... - | - | -kernel | -............................................................................ -hardware | - | - | -............................................................................ -: remote processor : -............................................................................ + +---------------------------------------------------------------------------+ + | client driver client_a client_b | + +---------------------------------------------------------------------------+ + ^-------------------^ + | + | + +--------------------------------------------------------------------------+ + | controller framework mailbox | + +-----------------------------------|--------------------------------------+ + | + | + +--------------------------------------------------------------------------+ + | controller driver device specific | + +-----------------------------------|--------------------------------------+ + | + | + kernel | + ---------------------------------------------------------------------------- + hardware | + | + | + +--------------------------------------------------------------------------+ + | remote processor | + +--------------------------------------------------------------------------+ In the context of a mailbox framework, a channel refers to a dedicated > + > + > +In the context of a mailbox framework, a channel refers to a dedicated > +communication pathway between two or more processors or components. By using > +channels, the framework abstracts the complexity of interprocessor communication. > + > +Data Structures > +================ > + > +- **struct mbox_client** > + This structure represents a client that communicates over a mailbox > + channel. It holds information such as: > + - A pointer to the device associated with the client (`dev`). > + - Callback functions for handling message transmission events, including: > + - `rx_callback`: Called when a message is received. > + - `tx_done`: Called when a message transmission is acknowledged. > + - Flags that specify the client’s configuration, such as whether it operates > + in blocking mode. > + > +- **struct mbox_chan** > + This structure represents an individual mailbox channel. It maintains the > + state required for message queuing and transmission. Key members include: > + - `msg_data`: Array of messages queued for transmission. > + - `msg_count`: Number of messages currently queued. > + - `msg_free`: Index of the next free slot in the message queue. > + - `active_req`: Pointer to the currently active message being transmitted. > + - Synchronization primitives to manage access from multiple contexts. > + > +- **struct mbox_controller** > + This structure represents a mailbox controller that manages multiple > + channels. It includes: > + - A pointer to the device managing the mailbox. > + - Operations for sending and receiving messages, as well as initializing > + and shutting down the mailbox. > + - A list of associated channels and the total number of channels available. Shouldn't these structs be documented as kernel-doc comments? tl;dr: see Documentation/doc-guide/kernel-doc.html > + > +controller framework APIs > +========================= > + > +``struct `mbox_controller` Initialization > +----------------------------------------- Properly double-backquote the struct name to format it as inline code: ---- >8 ---- diff --git a/Documentation/driver-api/mailbox/core.rst b/Documentation/driver-api/mailbox/core.rst index 239538f497e41a..d83456164464aa 100644 --- a/Documentation/driver-api/mailbox/core.rst +++ b/Documentation/driver-api/mailbox/core.rst @@ -117,7 +117,7 @@ Data Structures controller framework APIs ========================= -``struct `mbox_controller` Initialization +``struct mbox_controller`` Initialization ----------------------------------------- Just like any other kernel framework, the whole mailbox controller registration > + > +Just like any other kernel framework, the whole mailbox controller registration > +relies on the driver filling a structure and registering against the > +framework. In our case, that structure is mbox_controller. > + > +The first thing you need to do in your driver is to allocate this > +structure. Any of the usual memory allocators will do, but you'll also > +need to initialize a few fields in there: > + > +- ``dev``: should hold the pointer to the ``struct device`` associated > + to your current driver instance. > + > +- ``ops``: Operators that work on each communication channel. > + > +- ``chans``: Array of channels. > + > +- ``num_chans``: Number of channels in the `chans` array. > + > +- ``txdone_irq``: Indicates if the controller can report to the API > + when the last transmitted data was read by the > + remote (e.g., if it has a TX ACK interrupt). > + > +All the below fields are not mandatory. > + > +- ``txdone_poll``: Indicates if the controller can read but not report > + the TX done. For example, some register may show > + the TX status, but no interrupt is raised. This > + field is ignored if `txdone_irq` is set. > + > +- ``txpoll_period``: If `txdone_poll` is in effect, the API polls for > + the last TX status after this many milliseconds. > + > +- ``of_xlate``: Controller driver-specific mapping of channel via > + Device Tree (DT). > + > + > +Key Functions > +------------- > + > +- **int devm_mbox_controller_register(struct mbox_controller *mbox)** > + This function registers a mailbox controller with the kernel. It makes the > + channels associated with the controller available for client requests. The > + function performs sanity checks on the controller structure to ensure all > + necessary fields are populated. > + > +- **struct mbox_chan *mbox_request_channel(struct mbox_client *cl, int index)** > + This function requests a mailbox channel for a specified client, identified > + by an index. It searches for the appropriate mailbox channel, and if found, > + it returns a pointer to the channel. If the request fails (e.g., if the > + index is invalid), it returns an error pointer. > + > +- **void mbox_free_channel(struct mbox_chan *chan)** > + This function releases a mailbox channel that was previously allocated for a > + client. It ensures that the channel can be reused by other clients. If any > + messages are still in the queue, they are aborted, and no callbacks are made. > + > +- **int mbox_send_message(struct mbox_chan *chan, void *mssg)** > + This function is used by clients to send a message through the specified > + mailbox channel. The function can operate in either blocking or non-blocking > + mode, depending on the client’s configuration. It will queue the message for > + transmission and notify the client once the message is acknowledged. > + > +- **void mbox_chan_received_data(struct mbox_chan *chan, void *mssg)** > + This function is called by the controller driver to notify the mailbox > + framework that a message has been received on the specified channel. The > + received message is then passed to the appropriate client's `rx_callback` > + function for processing. Shouldn't these functions also be documented as kernel-doc comments? > diff --git a/Documentation/driver-api/mailbox/index.rst b/Documentation/driver-api/mailbox/index.rst > new file mode 100644 > index 000000000000..e254a8fdb66a > --- /dev/null > +++ b/Documentation/driver-api/mailbox/index.rst > @@ -0,0 +1,45 @@ > +======================= > +Mailbox documentation > +======================= > + > +Mailbox documentation provides documents for various aspects of mailbox > +framework. > + > +Mailbox development documentation > +--------------------------------- > + > +This book helps with mailbox internal APIs and guide for mailbox device > +driver writers. > + > +.. toctree:: > + :maxdepth: 1 > + > + core > + > +mailbox controller driver documentation > +------------------------------ > + > +This book is a guide to device driver writers on how to register > +mailbox controller to the mailbox framework. > + > +.. toctree:: > + :maxdepth: 1 > + > + writing_mailbox_controller_drivers > + > +mailbox client driver documentation > +------------------------------ Match up section underline length by its title: ---- >8 ---- diff --git a/Documentation/driver-api/mailbox/index.rst b/Documentation/driver-api/mailbox/index.rst index e254a8fdb66ac7..02d7d5e8660999 100644 --- a/Documentation/driver-api/mailbox/index.rst +++ b/Documentation/driver-api/mailbox/index.rst @@ -1,6 +1,6 @@ -======================= +===================== Mailbox documentation -======================= +===================== Mailbox documentation provides documents for various aspects of mailbox framework. @@ -17,7 +17,7 @@ driver writers. core mailbox controller driver documentation ------------------------------- +--------------------------------------- This book is a guide to device driver writers on how to register mailbox controller to the mailbox framework. @@ -28,7 +28,7 @@ mailbox controller to the mailbox framework. writing_mailbox_controller_drivers mailbox client driver documentation ------------------------------- +----------------------------------- This book is a guide to mailbox client driver writers. > + > +This book is a guide to mailbox client driver writers. > + > +.. toctree:: > + :maxdepth: 1 > + > + client > + > +.. only:: subproject and html > + > + Indices > + ======= > + > + * :ref:`genindex` Fix up also the reference link on parent toctree: ---- >8 ---- diff --git a/Documentation/driver-api/index.rst b/Documentation/driver-api/index.rst index 7f83e05769b4a4..b4d78b92fd921a 100644 --- a/Documentation/driver-api/index.rst +++ b/Documentation/driver-api/index.rst @@ -102,7 +102,7 @@ Subsystem-specific APIs ipmb ipmi libata - mailbox + mailbox/index md/index media/index mei/index > diff --git a/Documentation/driver-api/mailbox/writing_mailbox_controller_drivers.rst b/Documentation/driver-api/mailbox/writing_mailbox_controller_drivers.rst > new file mode 100644 > index 000000000000..2a82645c1357 > --- /dev/null > +++ b/Documentation/driver-api/mailbox/writing_mailbox_controller_drivers.rst > @@ -0,0 +1,179 @@ > +.. SPDX-License-Identifier: GPL-2.0 > + > +.. _writing_mailbox_controller_drivers: > + > +================================== > +Writing Mailbox Controller Drivers > +================================== > + > +Introduction > +============ > + > +This document serves as a basic guideline for driver programmers that need > +to hack a new mailbox controller driver or understand the essentials of > +the existing ones. > + > +Driver Boilerplate > +================== > + > +As a bare minimum, a mailbox controller driver needs to call > +``mbox_controller_register`` function to register with the framework. > + > +A basic driver skeleton could look like this for a mailbox hardware that > +has the following characteristics: > +a. It supports only a single channel, i.e., only the remote processor can > + send interrupts. > +b. Data transfer is over the registers associated with mailbox hardware. > +c. Mailbox hardware is configured to receive interrupts. > +d. When the remote processor is ready to send data, it triggers a mailbox > + interrupt. > +e. As part of interrupt handling by Linux, it copies data from the registers. > + > +.. code-block:: c > + > + #include <linux/device.h> > + #include <linux/interrupt.h> > + #include <linux/io.h> > + #include <linux/kernel.h> > + #include <linux/mailbox_controller.h> > + #include <linux/module.h> > + #include <linux/of.h> > + #include <linux/platform_device.h> > + #define DRIVER_NAME "dummy_controller" > + > + struct dummy_mbox { > + struct device *dev; > + struct mbox_controller controller; > + int irq; > + }; > + > + static void dummy_mbox_receive(struct mbox_chan *chan) > + { > + struct dummy_mbox *mbox = chan->con_priv; > + int val; > + > + // Data copied from registers > + val = read_register(); > + mbox_chan_received_data(chan, &val); > + } > + > + static irqreturn_t dummy_mbox_irq_handler(int irq, void *data) > + { > + struct mbox_chan *chan = data; > + struct dummy_mbox *mbox = chan->con_priv; > + u32 reg; > + > + // Read registers to see if data is received > + dummy_mbox_receive(chan); > + mbox_chan_txdone(chan, 0); > + return reg ? IRQ_HANDLED : IRQ_NONE; > + } > + > + static int dummy_mbox_send_data(struct mbox_chan *chan, void *data) > + { > + // Write data in registers to send it to the remote processor > + return 0; > + } > + > + static int dummy_mbox_startup(struct mbox_chan *chan) > + { > + struct dummy_mbox *mbox = chan->con_priv; > + u32 reg; > + int ret; > + > + ret = devm_request_irq(mbox->dev, mbox->irq, dummy_mbox_irq_handler, 0, > + DRIVER_NAME, chan); > + if (ret < 0) { > + dev_err(mbox->dev, "Cannot request irq\n"); > + return ret; > + } > + > + /* Register write to enable IRQ generation */ > + > + return 0; > + } > + > + static void dummy_mbox_shutdown(struct mbox_chan *chan) > + { > + struct dummy_mbox *mbox = chan->con_priv; > + > + /* Disable interrupt generation */ > + devm_free_irq(mbox->dev, mbox->irq, chan); > + } > + > + static const struct mbox_chan_ops dummy_mbox_ops = { > + .send_data = dummy_mbox_send_data, > + .startup = dummy_mbox_startup, > + .shutdown = dummy_mbox_shutdown, > + }; > + > + static int dummy_mbox_probe(struct platform_device *pdev) > + { > + struct dummy_mbox *mbox; > + struct mbox_chan *chans; > + int ret; > + > + mbox = devm_kzalloc(&pdev->dev, sizeof(*mbox), GFP_KERNEL); > + if (!mbox) > + return -ENOMEM; > + > + /* Allocate one channel */ > + chans = devm_kzalloc(&pdev->dev, sizeof(*chans), GFP_KERNEL); > + if (!chans) > + return -ENOMEM; > + > + mbox->base = devm_platform_ioremap_resource(pdev, 0); > + if (IS_ERR(mbox->base)) > + return PTR_ERR(mbox->base); > + > + mbox->irq = platform_get_irq(pdev, 0); > + if (mbox->irq < 0) > + return mbox->irq; > + > + mbox->dev = &pdev->dev; > + > + /* Hardware supports only one channel. */ > + mbox->controller.dev = mbox->dev; > + mbox->controller.num_chans = 1; > + mbox->controller.chans = chans; > + mbox->controller.ops = &dummy_mbox_ops; > + mbox->controller.txdone_irq = true; > + > + ret = devm_mbox_controller_register(mbox->dev, &mbox->controller); > + if (ret) { > + dev_err(&pdev->dev, "Could not register mailbox controller\n"); > + return ret; > + } > + > + return ret; > + } > + > + static const struct of_device_id dummy_mbox_match[] = { > + { .compatible = "dummy,dummy-mailbox" }, > + { }, > + }; > + > + MODULE_DEVICE_TABLE(of, dummy_mbox_match); > + > + static struct platform_driver dummy_mbox_driver = { > + .probe = dummy_mbox_probe, > + .driver = { > + .name = DRIVER_NAME, > + .of_match_table = dummy_mbox_match, > + }, > + }; > + > + module_platform_driver(dummy_mbox_driver); > + MODULE_LICENSE("GPL v2"); > + MODULE_DESCRIPTION("Dummy mailbox controller driver"); > + > +In the above code, a couple of things are done: > +a. The controller is registered in the probe along with callbacks, which in > + this case are the bare minimum: ``startup``, ``shutdown``, and > + ``send_data``. > +b. IRQ is registered to get notifications from the remote processor. > +c. In the IRQ handler, registers are read to copy data, and > + ``mbox_chan_received_data`` is called to hand over the data to the client. > +d. ``mbox_chan_txdone`` is called to let the framework know that this data > + is the last data and no more data is to be expected for the current transfer. > + Sphinx warns out numerous indentation warnings on the lists, so I have to fix them up: ---- >8 ---- diff --git a/Documentation/driver-api/mailbox/client.rst b/Documentation/driver-api/mailbox/client.rst index 9088f83734230d..17dafaca056777 100644 --- a/Documentation/driver-api/mailbox/client.rst +++ b/Documentation/driver-api/mailbox/client.rst @@ -31,6 +31,7 @@ The mailbox structure is defined as follows: Key Functions ------------- 1. Requesting a Mailbox Channel + - **Function**: `mbox_request_channel(struct mbox_client *client, unsigned int channel)` - **Description**: Requests a mailbox channel for sending messages. @@ -41,15 +42,19 @@ Key Functions code on failure. 2. Sending a Message + - **Function**: `mbox_send_message(struct mbox_chan *chan, void *msg)` - **Description**: Sends a message through the mailbox channel. - **Parameters**: + - `chan`: The mailbox channel used for communication. - `msg`: Pointer to the message to be sent (usually NULL for dummy messages). + - **Returns**: 0 on success, or a negative error code on failure. 3. Transmitting Completion + - **Function**: `mbox_client_txdone(struct mbox_chan *chan, unsigned int msg_id)` - **Description**: Notifies the mailbox framework that message diff --git a/Documentation/driver-api/mailbox/core.rst b/Documentation/driver-api/mailbox/core.rst index 8d56d81007c11c..239538f497e41a 100644 --- a/Documentation/driver-api/mailbox/core.rst +++ b/Documentation/driver-api/mailbox/core.rst @@ -85,16 +85,20 @@ Data Structures - **struct mbox_client** This structure represents a client that communicates over a mailbox channel. It holds information such as: + - A pointer to the device associated with the client (`dev`). - Callback functions for handling message transmission events, including: + - `rx_callback`: Called when a message is received. - `tx_done`: Called when a message transmission is acknowledged. + - Flags that specify the client’s configuration, such as whether it operates in blocking mode. - **struct mbox_chan** This structure represents an individual mailbox channel. It maintains the state required for message queuing and transmission. Key members include: + - `msg_data`: Array of messages queued for transmission. - `msg_count`: Number of messages currently queued. - `msg_free`: Index of the next free slot in the message queue. @@ -104,6 +108,7 @@ Data Structures - **struct mbox_controller** This structure represents a mailbox controller that manages multiple channels. It includes: + - A pointer to the device managing the mailbox. - Operations for sending and receiving messages, as well as initializing and shutting down the mailbox. @@ -133,21 +138,20 @@ need to initialize a few fields in there: - ``num_chans``: Number of channels in the `chans` array. - ``txdone_irq``: Indicates if the controller can report to the API - when the last transmitted data was read by the - remote (e.g., if it has a TX ACK interrupt). + when the last transmitted data was read by the remote (e.g., if it has a + TX ACK interrupt). All the below fields are not mandatory. - ``txdone_poll``: Indicates if the controller can read but not report - the TX done. For example, some register may show - the TX status, but no interrupt is raised. This - field is ignored if `txdone_irq` is set. + the TX done. For example, some register may show the TX status, but no + interrupt is raised. This field is ignored if `txdone_irq` is set. - ``txpoll_period``: If `txdone_poll` is in effect, the API polls for - the last TX status after this many milliseconds. + the last TX status after this many milliseconds. - ``of_xlate``: Controller driver-specific mapping of channel via - Device Tree (DT). + Device Tree (DT). Key Functions diff --git a/Documentation/driver-api/mailbox/writing_mailbox_controller_drivers.rst b/Documentation/driver-api/mailbox/writing_mailbox_controller_drivers.rst index 2a82645c13573e..853adf6918173d 100644 --- a/Documentation/driver-api/mailbox/writing_mailbox_controller_drivers.rst +++ b/Documentation/driver-api/mailbox/writing_mailbox_controller_drivers.rst @@ -21,6 +21,7 @@ As a bare minimum, a mailbox controller driver needs to call A basic driver skeleton could look like this for a mailbox hardware that has the following characteristics: + a. It supports only a single channel, i.e., only the remote processor can send interrupts. b. Data transfer is over the registers associated with mailbox hardware. @@ -168,6 +169,7 @@ e. As part of interrupt handling by Linux, it copies data from the registers. MODULE_DESCRIPTION("Dummy mailbox controller driver"); In the above code, a couple of things are done: + a. The controller is registered in the probe along with callbacks, which in this case are the bare minimum: ``startup``, ``shutdown``, and ``send_data``. Thanks. -- An old man doll... just what I always wanted! - Clara [-- Attachment #2: signature.asc --] [-- Type: application/pgp-signature, Size: 228 bytes --] ^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH 2/2] mailbox: Documentation: add the latest documentation 2024-10-25 3:38 ` Bagas Sanjaya @ 2024-10-25 19:24 ` anish kumar 2024-10-29 18:06 ` anish kumar 0 siblings, 1 reply; 12+ messages in thread From: anish kumar @ 2024-10-25 19:24 UTC (permalink / raw) To: jassisinghbrar, Jonathan Corbet; +Cc: linux-doc, linux-kernel, Bagas Sanjaya Hello Jassi, I hope to get some more comments from you before spinning up a new revision. On Thu, Oct 24, 2024 at 8:38 PM Bagas Sanjaya <bagasdotme@gmail.com> wrote: > > On Sat, Oct 19, 2024 at 12:55:34PM -0700, anish kumar wrote: > > 1. added client documentation > > 2. added controller documentation. > > 3. added framework documentation > > One doc topic on each patch, please. > > > > > Signed-off-by: anish kumar <yesanishhere@gmail.com> > > --- > > Documentation/driver-api/mailbox/client.rst | 192 ++++++++++++++++++ > > Documentation/driver-api/mailbox/core.rst | 182 +++++++++++++++++ > > Documentation/driver-api/mailbox/index.rst | 45 ++++ > > .../writing_mailbox_controller_drivers.rst | 179 ++++++++++++++++ > > 4 files changed, 598 insertions(+) > > create mode 100644 Documentation/driver-api/mailbox/client.rst > > create mode 100644 Documentation/driver-api/mailbox/core.rst > > create mode 100644 Documentation/driver-api/mailbox/index.rst > > create mode 100644 Documentation/driver-api/mailbox/writing_mailbox_controller_drivers.rst > > > > diff --git a/Documentation/driver-api/mailbox/client.rst b/Documentation/driver-api/mailbox/client.rst > > new file mode 100644 > > index 000000000000..9088f8373423 > > --- /dev/null > > +++ b/Documentation/driver-api/mailbox/client.rst > > @@ -0,0 +1,192 @@ > > +Mailbox Client Documentation > > +============================ > > + > > +Overview > > +-------- > > +The mailbox client driver is responsible for sending and receiving messages > > +to and from a remote processor. It uses mailbox APIs provided by the > > +mailbox framework. > > + > > +Mailbox Structure > > +----------------- > > +The mailbox structure is defined as follows: > > + > > +.. code-block:: c > > + > > + struct mbox_client { > > + //device associated with the mailbox > > + struct device *dev; > > + // callback for transmission completion > > + void (*tx_done)(struct mbox_client *client); > > + // callback to prepare for sending a message > > + void (*tx_prepare)(struct mbox_client *client); > > + // callback for received messages > > + void (*rx_callback)(struct mbox_client *client, void *data); > > + // flag to indicate if transmission should block > > + bool tx_block; > > + // indicates if the client knows when transmission is done > > + bool knows_txdone; > > + }; > > + > > +Key Functions > > +------------- > > +1. Requesting a Mailbox Channel > > + - **Function**: `mbox_request_channel(struct mbox_client *client, > > + unsigned int channel)` > > + - **Description**: Requests a mailbox channel for sending messages. > > + - **Parameters**: > > + - `client`: Pointer to the mailbox client structure. > > + - `channel`: The specific mailbox channel to request. > > + - **Returns**: A pointer to the mailbox channel on success, or an error > > + code on failure. > > + > > +2. Sending a Message > > + - **Function**: `mbox_send_message(struct mbox_chan *chan, void *msg)` > > + - **Description**: Sends a message through the mailbox channel. > > + - **Parameters**: > > + - `chan`: The mailbox channel used for communication. > > + - `msg`: Pointer to the message to be sent (usually NULL for dummy > > + messages). > > + - **Returns**: 0 on success, or a negative error code on failure. > > + > > +3. Transmitting Completion > > + - **Function**: `mbox_client_txdone(struct mbox_chan *chan, unsigned int > > + msg_id)` > > + - **Description**: Notifies the mailbox framework that message > > + transmission is complete. > > + - **Parameters**: > > + - `chan`: The mailbox channel associated with the message. > > + - `msg_id`: The identifier of the message that was transmitted. > > These functions should've been documented as kernel-doc comments, though. > > > + > > +Usage Example > > +------------- > > +In a typical mailbox client driver, the following steps are typically > > +performed: > > + > > +1. Initialize the Mailbox Client: > > + > > + .. code-block:: c > > + > > + struct mbox_client my_mbox_client = { > > + .dev = &my_device, > > + .tx_done = my_tx_done_callback, > > + .rx_callback = my_rx_callback, > > + .tx_block = false, > > + .knows_txdone = true, > > + }; > > + > > +2. Request a Mailbox Channel: > > + > > + .. code-block:: c > > + > > + mbox_chan = mbox_request_channel(&my_mbox_client, 0); > > + if (IS_ERR(mbox_chan)) { > > + // Handle error > > + } > > + > > +3. Send a Message: > > + > > + .. code-block:: c > > + > > + int ret = mbox_send_message(mbox_chan, NULL); // Sending a dummy message > > + if (ret < 0) { > > + // Handle error > > + } > > + > > +4. Complete Transmission: > > + > > + .. code-block:: c > > + > > + mbox_client_txdone(mbox_chan, 0); > > + > > +Interrupt Handling > > +------------------ > > +The mailbox interface can trigger interrupts upon message receipt. Handlers > > +should be implemented in the `rx_callback` function defined in the mailbox > > +client structure to process incoming messages. > > + > > +Example Mailbox Client Driver > > +----------------------------- > > +.. code-block:: c > > + > > + struct demo_client { > > + struct mbox_client cl; > > + struct mbox_chan *mbox; > > + struct completion c; > > + bool async; > > + /* ... */ > > + }; > > + > > + /* > > + * This is the handler for data received from remote. The behaviour is purely > > + * dependent upon the protocol. This is just an example. > > + */ > > + static void message_from_remote(struct mbox_client *cl, void *mssg) > > + { > > + struct demo_client *dc = container_of(cl, struct demo_client, cl); > > + if (dc->async) { > > + if (is_an_ack(mssg)) { > > + /* An ACK to our last sample sent */ > > + return; /* Or do something else here */ > > + } else { /* A new message from remote */ > > + queue_req(mssg); > > + } > > + } else { > > + /* Remote f/w sends only ACK packets on this channel */ > > + return; > > + } > > + } > > + > > + static void sample_sent(struct mbox_client *cl, void *mssg, int r) > > + { > > + struct demo_client *dc = container_of(cl, struct demo_client, cl); > > + complete(&dc->c); > > + } > > + > > + static void client_demo(struct platform_device *pdev) > > + { > > + struct demo_client *dc_sync, *dc_async; > > + /* The controller already knows async_pkt and sync_pkt */ > > + struct async_pkt ap; > > + struct sync_pkt sp; > > + > > + dc_sync = kzalloc(sizeof(*dc_sync), GFP_KERNEL); > > + dc_async = kzalloc(sizeof(*dc_async), GFP_KERNEL); > > + > > + /* Populate non-blocking mode client */ > > + dc_async->cl.dev = &pdev->dev; > > + dc_async->cl.rx_callback = message_from_remote; > > + dc_async->cl.tx_done = sample_sent; > > + dc_async->cl.tx_block = false; > > + dc_async->cl.tx_tout = 0; /* doesn't matter here */ > > + dc_async->cl.knows_txdone = false; /* depending upon protocol */ > > + dc_async->async = true; > > + init_completion(&dc_async->c); > > + > > + /* Populate blocking mode client */ > > + dc_sync->cl.dev = &pdev->dev; > > + dc_sync->cl.rx_callback = message_from_remote; > > + dc_sync->cl.tx_done = NULL; /* operate in blocking mode */ > > + dc_sync->cl.tx_block = true; > > + dc_sync->cl.tx_tout = 500; /* by half a second */ > > + dc_sync->cl.knows_txdone = false; /* depending upon protocol */ > > + dc_sync->async = false; > > + > > + /* ASync mailbox is listed second in 'mboxes' property */ > > + dc_async->mbox = mbox_request_channel(&dc_async->cl, 1); > > + /* Populate data packet */ > > + /* ap.xxx = 123; etc */ > > + /* Send async message to remote */ > > + mbox_send_message(dc_async->mbox, &ap); > > + > > + /* Sync mailbox is listed first in 'mboxes' property */ > > + dc_sync->mbox = mbox_request_channel(&dc_sync->cl, 0); > > + /* Populate data packet */ > > + /* sp.abc = 123; etc */ > > + /* Send message to remote in blocking mode */ > > + mbox_send_message(dc_sync->mbox, &sp); > > + /* At this point 'sp' has been sent */ > > + > > + /* Now wait for async chan to be done */ > > + wait_for_completion(&dc_async->c); > > + } > > diff --git a/Documentation/driver-api/mailbox/core.rst b/Documentation/driver-api/mailbox/core.rst > > new file mode 100644 > > index 000000000000..d1220086da67 > > --- /dev/null > > +++ b/Documentation/driver-api/mailbox/core.rst > > @@ -0,0 +1,182 @@ > > +===================== > > +mailbox documentation > > +===================== > > + > > +Hardware Introduction > > +===================== > > + > > +Mailbox hardware is a specialized component found in multi-core > > +processors and embedded systems that facilitates inter-processor > > +communication (IPC) or communication between different hardware > > +components. It provides a structured mechanism for sending and > > +receiving messages, allowing various processors or devices to > > +exchange data efficiently. Here's an overview of its key > > +characteristics and functions: > > + > > +Key Characteristics of Mailbox Hardware > > +Interrupt Handling: Many mailbox implementations support > > +interrupt-driven communication. This allows a receiving processor > > +to be alerted when a new message arrives, facilitating immediate > > +processing without polling the mailbox constantly. > > + > > +Hardware Registers: Mailbox hardware often includes registers for > > +configuration and status monitoring. These registers can be used > > +to control the mailbox's behavior, check for available messages, > > +or acknowledge message receipt. > > + > > +Support for Multiple Protocols: Mailboxes can support various > > +communication protocols, enabling interoperability between different > > +hardware components and simplifying the integration of diverse systems. > > + > > +Synchronous and Asynchronous Modes: Mailbox hardware can operate in > > +both synchronous and asynchronous modes. In synchronous mode, the > > +sender may wait for the receiver to acknowledge receipt before > > +proceeding, while in asynchronous mode, the sender can continue > > +executing other tasks immediately after sending the message. > > + > > + > > +Mailbox framework design > > +======================== > > + > > +The mailbox facilitates interprocessor communication by allowing processors to > > +exchange messages or signals. The mailbox framework consists of: > > + > > +Mailbox Controller: This is platform-specific and is responsible for configuring > > +and managing interrupts from the remote processor. It offers a generic API for > > +the mailbox client. > > + > > +Mailbox Client: This component handles the sending and receiving of messages. > > + > > + > > +............................................................................ > > +: client driver client_a client_b : > > +............................................................................ > > + ^-------------------^ > > + | > > + | > > +............................................................................ > > +: controller framework mailbox : > > +....................................|....................................... > > + | > > + | > > +............................................................................ > > +: controller driver device specific : > > +....................................|....................................... > > + | > > + | > > +kernel | > > +............................................................................ > > +hardware | > > + | > > + | > > +............................................................................ > > +: remote processor : > > +............................................................................ > > htmldocs build errors out: > > Documentation/driver-api/mailbox/core.rst:57: WARNING: Block quote ends without a blank line; unexpected unindent. > Documentation/driver-api/mailbox/core.rst:57: CRITICAL: Missing matching underline for section title overline. > > ............................................................................ > : controller framework mailbox : > ....................................|....................................... > > reST markup error: > Documentation/driver-api/mailbox/core.rst:57: (SEVERE/4) Missing matching underline for section title overline. > > ............................................................................ > : controller framework mailbox : > ....................................|....................................... > > I have to fix up the design diagram and wrap it: > > ---- >8 ---- > diff --git a/Documentation/driver-api/mailbox/core.rst b/Documentation/driver-api/mailbox/core.rst > index d1220086da679f..8d56d81007c11c 100644 > --- a/Documentation/driver-api/mailbox/core.rst > +++ b/Documentation/driver-api/mailbox/core.rst > @@ -47,31 +47,32 @@ the mailbox client. > > Mailbox Client: This component handles the sending and receiving of messages. > > +:: > > -............................................................................ > -: client driver client_a client_b : > -............................................................................ > - ^-------------------^ > - | > - | > -............................................................................ > -: controller framework mailbox : > -....................................|....................................... > - | > - | > -............................................................................ > -: controller driver device specific : > -....................................|....................................... > - | > - | > -kernel | > -............................................................................ > -hardware | > - | > - | > -............................................................................ > -: remote processor : > -............................................................................ > + +---------------------------------------------------------------------------+ > + | client driver client_a client_b | > + +---------------------------------------------------------------------------+ > + ^-------------------^ > + | > + | > + +--------------------------------------------------------------------------+ > + | controller framework mailbox | > + +-----------------------------------|--------------------------------------+ > + | > + | > + +--------------------------------------------------------------------------+ > + | controller driver device specific | > + +-----------------------------------|--------------------------------------+ > + | > + | > + kernel | > + ---------------------------------------------------------------------------- > + hardware | > + | > + | > + +--------------------------------------------------------------------------+ > + | remote processor | > + +--------------------------------------------------------------------------+ > > > In the context of a mailbox framework, a channel refers to a dedicated > > > + > > + > > +In the context of a mailbox framework, a channel refers to a dedicated > > +communication pathway between two or more processors or components. By using > > +channels, the framework abstracts the complexity of interprocessor communication. > > + > > +Data Structures > > +================ > > + > > +- **struct mbox_client** > > + This structure represents a client that communicates over a mailbox > > + channel. It holds information such as: > > + - A pointer to the device associated with the client (`dev`). > > + - Callback functions for handling message transmission events, including: > > + - `rx_callback`: Called when a message is received. > > + - `tx_done`: Called when a message transmission is acknowledged. > > + - Flags that specify the client’s configuration, such as whether it operates > > + in blocking mode. > > + > > +- **struct mbox_chan** > > + This structure represents an individual mailbox channel. It maintains the > > + state required for message queuing and transmission. Key members include: > > + - `msg_data`: Array of messages queued for transmission. > > + - `msg_count`: Number of messages currently queued. > > + - `msg_free`: Index of the next free slot in the message queue. > > + - `active_req`: Pointer to the currently active message being transmitted. > > + - Synchronization primitives to manage access from multiple contexts. > > + > > +- **struct mbox_controller** > > + This structure represents a mailbox controller that manages multiple > > + channels. It includes: > > + - A pointer to the device managing the mailbox. > > + - Operations for sending and receiving messages, as well as initializing > > + and shutting down the mailbox. > > + - A list of associated channels and the total number of channels available. > > Shouldn't these structs be documented as kernel-doc comments? tl;dr: > see Documentation/doc-guide/kernel-doc.html > > > + > > +controller framework APIs > > +========================= > > + > > +``struct `mbox_controller` Initialization > > +----------------------------------------- > > Properly double-backquote the struct name to format it as inline code: > > ---- >8 ---- > diff --git a/Documentation/driver-api/mailbox/core.rst b/Documentation/driver-api/mailbox/core.rst > index 239538f497e41a..d83456164464aa 100644 > --- a/Documentation/driver-api/mailbox/core.rst > +++ b/Documentation/driver-api/mailbox/core.rst > @@ -117,7 +117,7 @@ Data Structures > controller framework APIs > ========================= > > -``struct `mbox_controller` Initialization > +``struct mbox_controller`` Initialization > ----------------------------------------- > > Just like any other kernel framework, the whole mailbox controller registration > > > + > > +Just like any other kernel framework, the whole mailbox controller registration > > +relies on the driver filling a structure and registering against the > > +framework. In our case, that structure is mbox_controller. > > + > > +The first thing you need to do in your driver is to allocate this > > +structure. Any of the usual memory allocators will do, but you'll also > > +need to initialize a few fields in there: > > + > > +- ``dev``: should hold the pointer to the ``struct device`` associated > > + to your current driver instance. > > + > > +- ``ops``: Operators that work on each communication channel. > > + > > +- ``chans``: Array of channels. > > + > > +- ``num_chans``: Number of channels in the `chans` array. > > + > > +- ``txdone_irq``: Indicates if the controller can report to the API > > + when the last transmitted data was read by the > > + remote (e.g., if it has a TX ACK interrupt). > > + > > +All the below fields are not mandatory. > > + > > +- ``txdone_poll``: Indicates if the controller can read but not report > > + the TX done. For example, some register may show > > + the TX status, but no interrupt is raised. This > > + field is ignored if `txdone_irq` is set. > > + > > +- ``txpoll_period``: If `txdone_poll` is in effect, the API polls for > > + the last TX status after this many milliseconds. > > + > > +- ``of_xlate``: Controller driver-specific mapping of channel via > > + Device Tree (DT). > > + > > + > > +Key Functions > > +------------- > > + > > +- **int devm_mbox_controller_register(struct mbox_controller *mbox)** > > + This function registers a mailbox controller with the kernel. It makes the > > + channels associated with the controller available for client requests. The > > + function performs sanity checks on the controller structure to ensure all > > + necessary fields are populated. > > + > > +- **struct mbox_chan *mbox_request_channel(struct mbox_client *cl, int index)** > > + This function requests a mailbox channel for a specified client, identified > > + by an index. It searches for the appropriate mailbox channel, and if found, > > + it returns a pointer to the channel. If the request fails (e.g., if the > > + index is invalid), it returns an error pointer. > > + > > +- **void mbox_free_channel(struct mbox_chan *chan)** > > + This function releases a mailbox channel that was previously allocated for a > > + client. It ensures that the channel can be reused by other clients. If any > > + messages are still in the queue, they are aborted, and no callbacks are made. > > + > > +- **int mbox_send_message(struct mbox_chan *chan, void *mssg)** > > + This function is used by clients to send a message through the specified > > + mailbox channel. The function can operate in either blocking or non-blocking > > + mode, depending on the client’s configuration. It will queue the message for > > + transmission and notify the client once the message is acknowledged. > > + > > +- **void mbox_chan_received_data(struct mbox_chan *chan, void *mssg)** > > + This function is called by the controller driver to notify the mailbox > > + framework that a message has been received on the specified channel. The > > + received message is then passed to the appropriate client's `rx_callback` > > + function for processing. > > Shouldn't these functions also be documented as kernel-doc comments? > > > diff --git a/Documentation/driver-api/mailbox/index.rst b/Documentation/driver-api/mailbox/index.rst > > new file mode 100644 > > index 000000000000..e254a8fdb66a > > --- /dev/null > > +++ b/Documentation/driver-api/mailbox/index.rst > > @@ -0,0 +1,45 @@ > > +======================= > > +Mailbox documentation > > +======================= > > + > > +Mailbox documentation provides documents for various aspects of mailbox > > +framework. > > + > > +Mailbox development documentation > > +--------------------------------- > > + > > +This book helps with mailbox internal APIs and guide for mailbox device > > +driver writers. > > + > > +.. toctree:: > > + :maxdepth: 1 > > + > > + core > > + > > +mailbox controller driver documentation > > +------------------------------ > > + > > +This book is a guide to device driver writers on how to register > > +mailbox controller to the mailbox framework. > > + > > +.. toctree:: > > + :maxdepth: 1 > > + > > + writing_mailbox_controller_drivers > > + > > +mailbox client driver documentation > > +------------------------------ > > Match up section underline length by its title: > > ---- >8 ---- > diff --git a/Documentation/driver-api/mailbox/index.rst b/Documentation/driver-api/mailbox/index.rst > index e254a8fdb66ac7..02d7d5e8660999 100644 > --- a/Documentation/driver-api/mailbox/index.rst > +++ b/Documentation/driver-api/mailbox/index.rst > @@ -1,6 +1,6 @@ > -======================= > +===================== > Mailbox documentation > -======================= > +===================== > > Mailbox documentation provides documents for various aspects of mailbox > framework. > @@ -17,7 +17,7 @@ driver writers. > core > > mailbox controller driver documentation > ------------------------------- > +--------------------------------------- > > This book is a guide to device driver writers on how to register > mailbox controller to the mailbox framework. > @@ -28,7 +28,7 @@ mailbox controller to the mailbox framework. > writing_mailbox_controller_drivers > > mailbox client driver documentation > ------------------------------- > +----------------------------------- > > This book is a guide to mailbox client driver writers. > > > > + > > +This book is a guide to mailbox client driver writers. > > + > > +.. toctree:: > > + :maxdepth: 1 > > + > > + client > > + > > +.. only:: subproject and html > > + > > + Indices > > + ======= > > + > > + * :ref:`genindex` > > Fix up also the reference link on parent toctree: > > ---- >8 ---- > diff --git a/Documentation/driver-api/index.rst b/Documentation/driver-api/index.rst > index 7f83e05769b4a4..b4d78b92fd921a 100644 > --- a/Documentation/driver-api/index.rst > +++ b/Documentation/driver-api/index.rst > @@ -102,7 +102,7 @@ Subsystem-specific APIs > ipmb > ipmi > libata > - mailbox > + mailbox/index > md/index > media/index > mei/index > > > diff --git a/Documentation/driver-api/mailbox/writing_mailbox_controller_drivers.rst b/Documentation/driver-api/mailbox/writing_mailbox_controller_drivers.rst > > new file mode 100644 > > index 000000000000..2a82645c1357 > > --- /dev/null > > +++ b/Documentation/driver-api/mailbox/writing_mailbox_controller_drivers.rst > > @@ -0,0 +1,179 @@ > > +.. SPDX-License-Identifier: GPL-2.0 > > + > > +.. _writing_mailbox_controller_drivers: > > + > > +================================== > > +Writing Mailbox Controller Drivers > > +================================== > > + > > +Introduction > > +============ > > + > > +This document serves as a basic guideline for driver programmers that need > > +to hack a new mailbox controller driver or understand the essentials of > > +the existing ones. > > + > > +Driver Boilerplate > > +================== > > + > > +As a bare minimum, a mailbox controller driver needs to call > > +``mbox_controller_register`` function to register with the framework. > > + > > +A basic driver skeleton could look like this for a mailbox hardware that > > +has the following characteristics: > > +a. It supports only a single channel, i.e., only the remote processor can > > + send interrupts. > > +b. Data transfer is over the registers associated with mailbox hardware. > > +c. Mailbox hardware is configured to receive interrupts. > > +d. When the remote processor is ready to send data, it triggers a mailbox > > + interrupt. > > +e. As part of interrupt handling by Linux, it copies data from the registers. > > + > > +.. code-block:: c > > + > > + #include <linux/device.h> > > + #include <linux/interrupt.h> > > + #include <linux/io.h> > > + #include <linux/kernel.h> > > + #include <linux/mailbox_controller.h> > > + #include <linux/module.h> > > + #include <linux/of.h> > > + #include <linux/platform_device.h> > > + #define DRIVER_NAME "dummy_controller" > > + > > + struct dummy_mbox { > > + struct device *dev; > > + struct mbox_controller controller; > > + int irq; > > + }; > > + > > + static void dummy_mbox_receive(struct mbox_chan *chan) > > + { > > + struct dummy_mbox *mbox = chan->con_priv; > > + int val; > > + > > + // Data copied from registers > > + val = read_register(); > > + mbox_chan_received_data(chan, &val); > > + } > > + > > + static irqreturn_t dummy_mbox_irq_handler(int irq, void *data) > > + { > > + struct mbox_chan *chan = data; > > + struct dummy_mbox *mbox = chan->con_priv; > > + u32 reg; > > + > > + // Read registers to see if data is received > > + dummy_mbox_receive(chan); > > + mbox_chan_txdone(chan, 0); > > + return reg ? IRQ_HANDLED : IRQ_NONE; > > + } > > + > > + static int dummy_mbox_send_data(struct mbox_chan *chan, void *data) > > + { > > + // Write data in registers to send it to the remote processor > > + return 0; > > + } > > + > > + static int dummy_mbox_startup(struct mbox_chan *chan) > > + { > > + struct dummy_mbox *mbox = chan->con_priv; > > + u32 reg; > > + int ret; > > + > > + ret = devm_request_irq(mbox->dev, mbox->irq, dummy_mbox_irq_handler, 0, > > + DRIVER_NAME, chan); > > + if (ret < 0) { > > + dev_err(mbox->dev, "Cannot request irq\n"); > > + return ret; > > + } > > + > > + /* Register write to enable IRQ generation */ > > + > > + return 0; > > + } > > + > > + static void dummy_mbox_shutdown(struct mbox_chan *chan) > > + { > > + struct dummy_mbox *mbox = chan->con_priv; > > + > > + /* Disable interrupt generation */ > > + devm_free_irq(mbox->dev, mbox->irq, chan); > > + } > > + > > + static const struct mbox_chan_ops dummy_mbox_ops = { > > + .send_data = dummy_mbox_send_data, > > + .startup = dummy_mbox_startup, > > + .shutdown = dummy_mbox_shutdown, > > + }; > > + > > + static int dummy_mbox_probe(struct platform_device *pdev) > > + { > > + struct dummy_mbox *mbox; > > + struct mbox_chan *chans; > > + int ret; > > + > > + mbox = devm_kzalloc(&pdev->dev, sizeof(*mbox), GFP_KERNEL); > > + if (!mbox) > > + return -ENOMEM; > > + > > + /* Allocate one channel */ > > + chans = devm_kzalloc(&pdev->dev, sizeof(*chans), GFP_KERNEL); > > + if (!chans) > > + return -ENOMEM; > > + > > + mbox->base = devm_platform_ioremap_resource(pdev, 0); > > + if (IS_ERR(mbox->base)) > > + return PTR_ERR(mbox->base); > > + > > + mbox->irq = platform_get_irq(pdev, 0); > > + if (mbox->irq < 0) > > + return mbox->irq; > > + > > + mbox->dev = &pdev->dev; > > + > > + /* Hardware supports only one channel. */ > > + mbox->controller.dev = mbox->dev; > > + mbox->controller.num_chans = 1; > > + mbox->controller.chans = chans; > > + mbox->controller.ops = &dummy_mbox_ops; > > + mbox->controller.txdone_irq = true; > > + > > + ret = devm_mbox_controller_register(mbox->dev, &mbox->controller); > > + if (ret) { > > + dev_err(&pdev->dev, "Could not register mailbox controller\n"); > > + return ret; > > + } > > + > > + return ret; > > + } > > + > > + static const struct of_device_id dummy_mbox_match[] = { > > + { .compatible = "dummy,dummy-mailbox" }, > > + { }, > > + }; > > + > > + MODULE_DEVICE_TABLE(of, dummy_mbox_match); > > + > > + static struct platform_driver dummy_mbox_driver = { > > + .probe = dummy_mbox_probe, > > + .driver = { > > + .name = DRIVER_NAME, > > + .of_match_table = dummy_mbox_match, > > + }, > > + }; > > + > > + module_platform_driver(dummy_mbox_driver); > > + MODULE_LICENSE("GPL v2"); > > + MODULE_DESCRIPTION("Dummy mailbox controller driver"); > > + > > +In the above code, a couple of things are done: > > +a. The controller is registered in the probe along with callbacks, which in > > + this case are the bare minimum: ``startup``, ``shutdown``, and > > + ``send_data``. > > +b. IRQ is registered to get notifications from the remote processor. > > +c. In the IRQ handler, registers are read to copy data, and > > + ``mbox_chan_received_data`` is called to hand over the data to the client. > > +d. ``mbox_chan_txdone`` is called to let the framework know that this data > > + is the last data and no more data is to be expected for the current transfer. > > + > > Sphinx warns out numerous indentation warnings on the lists, so I have to > fix them up: > > ---- >8 ---- > diff --git a/Documentation/driver-api/mailbox/client.rst b/Documentation/driver-api/mailbox/client.rst > index 9088f83734230d..17dafaca056777 100644 > --- a/Documentation/driver-api/mailbox/client.rst > +++ b/Documentation/driver-api/mailbox/client.rst > @@ -31,6 +31,7 @@ The mailbox structure is defined as follows: > Key Functions > ------------- > 1. Requesting a Mailbox Channel > + > - **Function**: `mbox_request_channel(struct mbox_client *client, > unsigned int channel)` > - **Description**: Requests a mailbox channel for sending messages. > @@ -41,15 +42,19 @@ Key Functions > code on failure. > > 2. Sending a Message > + > - **Function**: `mbox_send_message(struct mbox_chan *chan, void *msg)` > - **Description**: Sends a message through the mailbox channel. > - **Parameters**: > + > - `chan`: The mailbox channel used for communication. > - `msg`: Pointer to the message to be sent (usually NULL for dummy > messages). > + > - **Returns**: 0 on success, or a negative error code on failure. > > 3. Transmitting Completion > + > - **Function**: `mbox_client_txdone(struct mbox_chan *chan, unsigned int > msg_id)` > - **Description**: Notifies the mailbox framework that message > diff --git a/Documentation/driver-api/mailbox/core.rst b/Documentation/driver-api/mailbox/core.rst > index 8d56d81007c11c..239538f497e41a 100644 > --- a/Documentation/driver-api/mailbox/core.rst > +++ b/Documentation/driver-api/mailbox/core.rst > @@ -85,16 +85,20 @@ Data Structures > - **struct mbox_client** > This structure represents a client that communicates over a mailbox > channel. It holds information such as: > + > - A pointer to the device associated with the client (`dev`). > - Callback functions for handling message transmission events, including: > + > - `rx_callback`: Called when a message is received. > - `tx_done`: Called when a message transmission is acknowledged. > + > - Flags that specify the client’s configuration, such as whether it operates > in blocking mode. > > - **struct mbox_chan** > This structure represents an individual mailbox channel. It maintains the > state required for message queuing and transmission. Key members include: > + > - `msg_data`: Array of messages queued for transmission. > - `msg_count`: Number of messages currently queued. > - `msg_free`: Index of the next free slot in the message queue. > @@ -104,6 +108,7 @@ Data Structures > - **struct mbox_controller** > This structure represents a mailbox controller that manages multiple > channels. It includes: > + > - A pointer to the device managing the mailbox. > - Operations for sending and receiving messages, as well as initializing > and shutting down the mailbox. > @@ -133,21 +138,20 @@ need to initialize a few fields in there: > - ``num_chans``: Number of channels in the `chans` array. > > - ``txdone_irq``: Indicates if the controller can report to the API > - when the last transmitted data was read by the > - remote (e.g., if it has a TX ACK interrupt). > + when the last transmitted data was read by the remote (e.g., if it has a > + TX ACK interrupt). > > All the below fields are not mandatory. > > - ``txdone_poll``: Indicates if the controller can read but not report > - the TX done. For example, some register may show > - the TX status, but no interrupt is raised. This > - field is ignored if `txdone_irq` is set. > + the TX done. For example, some register may show the TX status, but no > + interrupt is raised. This field is ignored if `txdone_irq` is set. > > - ``txpoll_period``: If `txdone_poll` is in effect, the API polls for > - the last TX status after this many milliseconds. > + the last TX status after this many milliseconds. > > - ``of_xlate``: Controller driver-specific mapping of channel via > - Device Tree (DT). > + Device Tree (DT). > > > Key Functions > diff --git a/Documentation/driver-api/mailbox/writing_mailbox_controller_drivers.rst b/Documentation/driver-api/mailbox/writing_mailbox_controller_drivers.rst > index 2a82645c13573e..853adf6918173d 100644 > --- a/Documentation/driver-api/mailbox/writing_mailbox_controller_drivers.rst > +++ b/Documentation/driver-api/mailbox/writing_mailbox_controller_drivers.rst > @@ -21,6 +21,7 @@ As a bare minimum, a mailbox controller driver needs to call > > A basic driver skeleton could look like this for a mailbox hardware that > has the following characteristics: > + > a. It supports only a single channel, i.e., only the remote processor can > send interrupts. > b. Data transfer is over the registers associated with mailbox hardware. > @@ -168,6 +169,7 @@ e. As part of interrupt handling by Linux, it copies data from the registers. > MODULE_DESCRIPTION("Dummy mailbox controller driver"); > > In the above code, a couple of things are done: > + > a. The controller is registered in the probe along with callbacks, which in > this case are the bare minimum: ``startup``, ``shutdown``, and > ``send_data``. > > Thanks. > > -- > An old man doll... just what I always wanted! - Clara ^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH 2/2] mailbox: Documentation: add the latest documentation 2024-10-25 19:24 ` anish kumar @ 2024-10-29 18:06 ` anish kumar 2024-10-29 23:51 ` Bagas Sanjaya 2024-10-30 17:41 ` Jassi Brar 0 siblings, 2 replies; 12+ messages in thread From: anish kumar @ 2024-10-29 18:06 UTC (permalink / raw) To: jassisinghbrar, Jonathan Corbet; +Cc: linux-doc, linux-kernel, Bagas Sanjaya Hello Jassi, Gentle reminder for the review. On Fri, Oct 25, 2024 at 12:24 PM anish kumar <yesanishhere@gmail.com> wrote: > > Hello Jassi, > > I hope to get some more comments from you before > spinning up a new revision. > > On Thu, Oct 24, 2024 at 8:38 PM Bagas Sanjaya <bagasdotme@gmail.com> wrote: > > > > On Sat, Oct 19, 2024 at 12:55:34PM -0700, anish kumar wrote: > > > 1. added client documentation > > > 2. added controller documentation. > > > 3. added framework documentation > > > > One doc topic on each patch, please. > > > > > > > > Signed-off-by: anish kumar <yesanishhere@gmail.com> > > > --- > > > Documentation/driver-api/mailbox/client.rst | 192 ++++++++++++++++++ > > > Documentation/driver-api/mailbox/core.rst | 182 +++++++++++++++++ > > > Documentation/driver-api/mailbox/index.rst | 45 ++++ > > > .../writing_mailbox_controller_drivers.rst | 179 ++++++++++++++++ > > > 4 files changed, 598 insertions(+) > > > create mode 100644 Documentation/driver-api/mailbox/client.rst > > > create mode 100644 Documentation/driver-api/mailbox/core.rst > > > create mode 100644 Documentation/driver-api/mailbox/index.rst > > > create mode 100644 Documentation/driver-api/mailbox/writing_mailbox_controller_drivers.rst > > > > > > diff --git a/Documentation/driver-api/mailbox/client.rst b/Documentation/driver-api/mailbox/client.rst > > > new file mode 100644 > > > index 000000000000..9088f8373423 > > > --- /dev/null > > > +++ b/Documentation/driver-api/mailbox/client.rst > > > @@ -0,0 +1,192 @@ > > > +Mailbox Client Documentation > > > +============================ > > > + > > > +Overview > > > +-------- > > > +The mailbox client driver is responsible for sending and receiving messages > > > +to and from a remote processor. It uses mailbox APIs provided by the > > > +mailbox framework. > > > + > > > +Mailbox Structure > > > +----------------- > > > +The mailbox structure is defined as follows: > > > + > > > +.. code-block:: c > > > + > > > + struct mbox_client { > > > + //device associated with the mailbox > > > + struct device *dev; > > > + // callback for transmission completion > > > + void (*tx_done)(struct mbox_client *client); > > > + // callback to prepare for sending a message > > > + void (*tx_prepare)(struct mbox_client *client); > > > + // callback for received messages > > > + void (*rx_callback)(struct mbox_client *client, void *data); > > > + // flag to indicate if transmission should block > > > + bool tx_block; > > > + // indicates if the client knows when transmission is done > > > + bool knows_txdone; > > > + }; > > > + > > > +Key Functions > > > +------------- > > > +1. Requesting a Mailbox Channel > > > + - **Function**: `mbox_request_channel(struct mbox_client *client, > > > + unsigned int channel)` > > > + - **Description**: Requests a mailbox channel for sending messages. > > > + - **Parameters**: > > > + - `client`: Pointer to the mailbox client structure. > > > + - `channel`: The specific mailbox channel to request. > > > + - **Returns**: A pointer to the mailbox channel on success, or an error > > > + code on failure. > > > + > > > +2. Sending a Message > > > + - **Function**: `mbox_send_message(struct mbox_chan *chan, void *msg)` > > > + - **Description**: Sends a message through the mailbox channel. > > > + - **Parameters**: > > > + - `chan`: The mailbox channel used for communication. > > > + - `msg`: Pointer to the message to be sent (usually NULL for dummy > > > + messages). > > > + - **Returns**: 0 on success, or a negative error code on failure. > > > + > > > +3. Transmitting Completion > > > + - **Function**: `mbox_client_txdone(struct mbox_chan *chan, unsigned int > > > + msg_id)` > > > + - **Description**: Notifies the mailbox framework that message > > > + transmission is complete. > > > + - **Parameters**: > > > + - `chan`: The mailbox channel associated with the message. > > > + - `msg_id`: The identifier of the message that was transmitted. > > > > These functions should've been documented as kernel-doc comments, though. > > > > > + > > > +Usage Example > > > +------------- > > > +In a typical mailbox client driver, the following steps are typically > > > +performed: > > > + > > > +1. Initialize the Mailbox Client: > > > + > > > + .. code-block:: c > > > + > > > + struct mbox_client my_mbox_client = { > > > + .dev = &my_device, > > > + .tx_done = my_tx_done_callback, > > > + .rx_callback = my_rx_callback, > > > + .tx_block = false, > > > + .knows_txdone = true, > > > + }; > > > + > > > +2. Request a Mailbox Channel: > > > + > > > + .. code-block:: c > > > + > > > + mbox_chan = mbox_request_channel(&my_mbox_client, 0); > > > + if (IS_ERR(mbox_chan)) { > > > + // Handle error > > > + } > > > + > > > +3. Send a Message: > > > + > > > + .. code-block:: c > > > + > > > + int ret = mbox_send_message(mbox_chan, NULL); // Sending a dummy message > > > + if (ret < 0) { > > > + // Handle error > > > + } > > > + > > > +4. Complete Transmission: > > > + > > > + .. code-block:: c > > > + > > > + mbox_client_txdone(mbox_chan, 0); > > > + > > > +Interrupt Handling > > > +------------------ > > > +The mailbox interface can trigger interrupts upon message receipt. Handlers > > > +should be implemented in the `rx_callback` function defined in the mailbox > > > +client structure to process incoming messages. > > > + > > > +Example Mailbox Client Driver > > > +----------------------------- > > > +.. code-block:: c > > > + > > > + struct demo_client { > > > + struct mbox_client cl; > > > + struct mbox_chan *mbox; > > > + struct completion c; > > > + bool async; > > > + /* ... */ > > > + }; > > > + > > > + /* > > > + * This is the handler for data received from remote. The behaviour is purely > > > + * dependent upon the protocol. This is just an example. > > > + */ > > > + static void message_from_remote(struct mbox_client *cl, void *mssg) > > > + { > > > + struct demo_client *dc = container_of(cl, struct demo_client, cl); > > > + if (dc->async) { > > > + if (is_an_ack(mssg)) { > > > + /* An ACK to our last sample sent */ > > > + return; /* Or do something else here */ > > > + } else { /* A new message from remote */ > > > + queue_req(mssg); > > > + } > > > + } else { > > > + /* Remote f/w sends only ACK packets on this channel */ > > > + return; > > > + } > > > + } > > > + > > > + static void sample_sent(struct mbox_client *cl, void *mssg, int r) > > > + { > > > + struct demo_client *dc = container_of(cl, struct demo_client, cl); > > > + complete(&dc->c); > > > + } > > > + > > > + static void client_demo(struct platform_device *pdev) > > > + { > > > + struct demo_client *dc_sync, *dc_async; > > > + /* The controller already knows async_pkt and sync_pkt */ > > > + struct async_pkt ap; > > > + struct sync_pkt sp; > > > + > > > + dc_sync = kzalloc(sizeof(*dc_sync), GFP_KERNEL); > > > + dc_async = kzalloc(sizeof(*dc_async), GFP_KERNEL); > > > + > > > + /* Populate non-blocking mode client */ > > > + dc_async->cl.dev = &pdev->dev; > > > + dc_async->cl.rx_callback = message_from_remote; > > > + dc_async->cl.tx_done = sample_sent; > > > + dc_async->cl.tx_block = false; > > > + dc_async->cl.tx_tout = 0; /* doesn't matter here */ > > > + dc_async->cl.knows_txdone = false; /* depending upon protocol */ > > > + dc_async->async = true; > > > + init_completion(&dc_async->c); > > > + > > > + /* Populate blocking mode client */ > > > + dc_sync->cl.dev = &pdev->dev; > > > + dc_sync->cl.rx_callback = message_from_remote; > > > + dc_sync->cl.tx_done = NULL; /* operate in blocking mode */ > > > + dc_sync->cl.tx_block = true; > > > + dc_sync->cl.tx_tout = 500; /* by half a second */ > > > + dc_sync->cl.knows_txdone = false; /* depending upon protocol */ > > > + dc_sync->async = false; > > > + > > > + /* ASync mailbox is listed second in 'mboxes' property */ > > > + dc_async->mbox = mbox_request_channel(&dc_async->cl, 1); > > > + /* Populate data packet */ > > > + /* ap.xxx = 123; etc */ > > > + /* Send async message to remote */ > > > + mbox_send_message(dc_async->mbox, &ap); > > > + > > > + /* Sync mailbox is listed first in 'mboxes' property */ > > > + dc_sync->mbox = mbox_request_channel(&dc_sync->cl, 0); > > > + /* Populate data packet */ > > > + /* sp.abc = 123; etc */ > > > + /* Send message to remote in blocking mode */ > > > + mbox_send_message(dc_sync->mbox, &sp); > > > + /* At this point 'sp' has been sent */ > > > + > > > + /* Now wait for async chan to be done */ > > > + wait_for_completion(&dc_async->c); > > > + } > > > diff --git a/Documentation/driver-api/mailbox/core.rst b/Documentation/driver-api/mailbox/core.rst > > > new file mode 100644 > > > index 000000000000..d1220086da67 > > > --- /dev/null > > > +++ b/Documentation/driver-api/mailbox/core.rst > > > @@ -0,0 +1,182 @@ > > > +===================== > > > +mailbox documentation > > > +===================== > > > + > > > +Hardware Introduction > > > +===================== > > > + > > > +Mailbox hardware is a specialized component found in multi-core > > > +processors and embedded systems that facilitates inter-processor > > > +communication (IPC) or communication between different hardware > > > +components. It provides a structured mechanism for sending and > > > +receiving messages, allowing various processors or devices to > > > +exchange data efficiently. Here's an overview of its key > > > +characteristics and functions: > > > + > > > +Key Characteristics of Mailbox Hardware > > > +Interrupt Handling: Many mailbox implementations support > > > +interrupt-driven communication. This allows a receiving processor > > > +to be alerted when a new message arrives, facilitating immediate > > > +processing without polling the mailbox constantly. > > > + > > > +Hardware Registers: Mailbox hardware often includes registers for > > > +configuration and status monitoring. These registers can be used > > > +to control the mailbox's behavior, check for available messages, > > > +or acknowledge message receipt. > > > + > > > +Support for Multiple Protocols: Mailboxes can support various > > > +communication protocols, enabling interoperability between different > > > +hardware components and simplifying the integration of diverse systems. > > > + > > > +Synchronous and Asynchronous Modes: Mailbox hardware can operate in > > > +both synchronous and asynchronous modes. In synchronous mode, the > > > +sender may wait for the receiver to acknowledge receipt before > > > +proceeding, while in asynchronous mode, the sender can continue > > > +executing other tasks immediately after sending the message. > > > + > > > + > > > +Mailbox framework design > > > +======================== > > > + > > > +The mailbox facilitates interprocessor communication by allowing processors to > > > +exchange messages or signals. The mailbox framework consists of: > > > + > > > +Mailbox Controller: This is platform-specific and is responsible for configuring > > > +and managing interrupts from the remote processor. It offers a generic API for > > > +the mailbox client. > > > + > > > +Mailbox Client: This component handles the sending and receiving of messages. > > > + > > > + > > > +............................................................................ > > > +: client driver client_a client_b : > > > +............................................................................ > > > + ^-------------------^ > > > + | > > > + | > > > +............................................................................ > > > +: controller framework mailbox : > > > +....................................|....................................... > > > + | > > > + | > > > +............................................................................ > > > +: controller driver device specific : > > > +....................................|....................................... > > > + | > > > + | > > > +kernel | > > > +............................................................................ > > > +hardware | > > > + | > > > + | > > > +............................................................................ > > > +: remote processor : > > > +............................................................................ > > > > htmldocs build errors out: > > > > Documentation/driver-api/mailbox/core.rst:57: WARNING: Block quote ends without a blank line; unexpected unindent. > > Documentation/driver-api/mailbox/core.rst:57: CRITICAL: Missing matching underline for section title overline. > > > > ............................................................................ > > : controller framework mailbox : > > ....................................|....................................... > > > > reST markup error: > > Documentation/driver-api/mailbox/core.rst:57: (SEVERE/4) Missing matching underline for section title overline. > > > > ............................................................................ > > : controller framework mailbox : > > ....................................|....................................... > > > > I have to fix up the design diagram and wrap it: > > > > ---- >8 ---- > > diff --git a/Documentation/driver-api/mailbox/core.rst b/Documentation/driver-api/mailbox/core.rst > > index d1220086da679f..8d56d81007c11c 100644 > > --- a/Documentation/driver-api/mailbox/core.rst > > +++ b/Documentation/driver-api/mailbox/core.rst > > @@ -47,31 +47,32 @@ the mailbox client. > > > > Mailbox Client: This component handles the sending and receiving of messages. > > > > +:: > > > > -............................................................................ > > -: client driver client_a client_b : > > -............................................................................ > > - ^-------------------^ > > - | > > - | > > -............................................................................ > > -: controller framework mailbox : > > -....................................|....................................... > > - | > > - | > > -............................................................................ > > -: controller driver device specific : > > -....................................|....................................... > > - | > > - | > > -kernel | > > -............................................................................ > > -hardware | > > - | > > - | > > -............................................................................ > > -: remote processor : > > -............................................................................ > > + +---------------------------------------------------------------------------+ > > + | client driver client_a client_b | > > + +---------------------------------------------------------------------------+ > > + ^-------------------^ > > + | > > + | > > + +--------------------------------------------------------------------------+ > > + | controller framework mailbox | > > + +-----------------------------------|--------------------------------------+ > > + | > > + | > > + +--------------------------------------------------------------------------+ > > + | controller driver device specific | > > + +-----------------------------------|--------------------------------------+ > > + | > > + | > > + kernel | > > + ---------------------------------------------------------------------------- > > + hardware | > > + | > > + | > > + +--------------------------------------------------------------------------+ > > + | remote processor | > > + +--------------------------------------------------------------------------+ > > > > > > In the context of a mailbox framework, a channel refers to a dedicated > > > > > + > > > + > > > +In the context of a mailbox framework, a channel refers to a dedicated > > > +communication pathway between two or more processors or components. By using > > > +channels, the framework abstracts the complexity of interprocessor communication. > > > + > > > +Data Structures > > > +================ > > > + > > > +- **struct mbox_client** > > > + This structure represents a client that communicates over a mailbox > > > + channel. It holds information such as: > > > + - A pointer to the device associated with the client (`dev`). > > > + - Callback functions for handling message transmission events, including: > > > + - `rx_callback`: Called when a message is received. > > > + - `tx_done`: Called when a message transmission is acknowledged. > > > + - Flags that specify the client’s configuration, such as whether it operates > > > + in blocking mode. > > > + > > > +- **struct mbox_chan** > > > + This structure represents an individual mailbox channel. It maintains the > > > + state required for message queuing and transmission. Key members include: > > > + - `msg_data`: Array of messages queued for transmission. > > > + - `msg_count`: Number of messages currently queued. > > > + - `msg_free`: Index of the next free slot in the message queue. > > > + - `active_req`: Pointer to the currently active message being transmitted. > > > + - Synchronization primitives to manage access from multiple contexts. > > > + > > > +- **struct mbox_controller** > > > + This structure represents a mailbox controller that manages multiple > > > + channels. It includes: > > > + - A pointer to the device managing the mailbox. > > > + - Operations for sending and receiving messages, as well as initializing > > > + and shutting down the mailbox. > > > + - A list of associated channels and the total number of channels available. > > > > Shouldn't these structs be documented as kernel-doc comments? tl;dr: > > see Documentation/doc-guide/kernel-doc.html > > > > > + > > > +controller framework APIs > > > +========================= > > > + > > > +``struct `mbox_controller` Initialization > > > +----------------------------------------- > > > > Properly double-backquote the struct name to format it as inline code: > > > > ---- >8 ---- > > diff --git a/Documentation/driver-api/mailbox/core.rst b/Documentation/driver-api/mailbox/core.rst > > index 239538f497e41a..d83456164464aa 100644 > > --- a/Documentation/driver-api/mailbox/core.rst > > +++ b/Documentation/driver-api/mailbox/core.rst > > @@ -117,7 +117,7 @@ Data Structures > > controller framework APIs > > ========================= > > > > -``struct `mbox_controller` Initialization > > +``struct mbox_controller`` Initialization > > ----------------------------------------- > > > > Just like any other kernel framework, the whole mailbox controller registration > > > > > + > > > +Just like any other kernel framework, the whole mailbox controller registration > > > +relies on the driver filling a structure and registering against the > > > +framework. In our case, that structure is mbox_controller. > > > + > > > +The first thing you need to do in your driver is to allocate this > > > +structure. Any of the usual memory allocators will do, but you'll also > > > +need to initialize a few fields in there: > > > + > > > +- ``dev``: should hold the pointer to the ``struct device`` associated > > > + to your current driver instance. > > > + > > > +- ``ops``: Operators that work on each communication channel. > > > + > > > +- ``chans``: Array of channels. > > > + > > > +- ``num_chans``: Number of channels in the `chans` array. > > > + > > > +- ``txdone_irq``: Indicates if the controller can report to the API > > > + when the last transmitted data was read by the > > > + remote (e.g., if it has a TX ACK interrupt). > > > + > > > +All the below fields are not mandatory. > > > + > > > +- ``txdone_poll``: Indicates if the controller can read but not report > > > + the TX done. For example, some register may show > > > + the TX status, but no interrupt is raised. This > > > + field is ignored if `txdone_irq` is set. > > > + > > > +- ``txpoll_period``: If `txdone_poll` is in effect, the API polls for > > > + the last TX status after this many milliseconds. > > > + > > > +- ``of_xlate``: Controller driver-specific mapping of channel via > > > + Device Tree (DT). > > > + > > > + > > > +Key Functions > > > +------------- > > > + > > > +- **int devm_mbox_controller_register(struct mbox_controller *mbox)** > > > + This function registers a mailbox controller with the kernel. It makes the > > > + channels associated with the controller available for client requests. The > > > + function performs sanity checks on the controller structure to ensure all > > > + necessary fields are populated. > > > + > > > +- **struct mbox_chan *mbox_request_channel(struct mbox_client *cl, int index)** > > > + This function requests a mailbox channel for a specified client, identified > > > + by an index. It searches for the appropriate mailbox channel, and if found, > > > + it returns a pointer to the channel. If the request fails (e.g., if the > > > + index is invalid), it returns an error pointer. > > > + > > > +- **void mbox_free_channel(struct mbox_chan *chan)** > > > + This function releases a mailbox channel that was previously allocated for a > > > + client. It ensures that the channel can be reused by other clients. If any > > > + messages are still in the queue, they are aborted, and no callbacks are made. > > > + > > > +- **int mbox_send_message(struct mbox_chan *chan, void *mssg)** > > > + This function is used by clients to send a message through the specified > > > + mailbox channel. The function can operate in either blocking or non-blocking > > > + mode, depending on the client’s configuration. It will queue the message for > > > + transmission and notify the client once the message is acknowledged. > > > + > > > +- **void mbox_chan_received_data(struct mbox_chan *chan, void *mssg)** > > > + This function is called by the controller driver to notify the mailbox > > > + framework that a message has been received on the specified channel. The > > > + received message is then passed to the appropriate client's `rx_callback` > > > + function for processing. > > > > Shouldn't these functions also be documented as kernel-doc comments? > > > > > diff --git a/Documentation/driver-api/mailbox/index.rst b/Documentation/driver-api/mailbox/index.rst > > > new file mode 100644 > > > index 000000000000..e254a8fdb66a > > > --- /dev/null > > > +++ b/Documentation/driver-api/mailbox/index.rst > > > @@ -0,0 +1,45 @@ > > > +======================= > > > +Mailbox documentation > > > +======================= > > > + > > > +Mailbox documentation provides documents for various aspects of mailbox > > > +framework. > > > + > > > +Mailbox development documentation > > > +--------------------------------- > > > + > > > +This book helps with mailbox internal APIs and guide for mailbox device > > > +driver writers. > > > + > > > +.. toctree:: > > > + :maxdepth: 1 > > > + > > > + core > > > + > > > +mailbox controller driver documentation > > > +------------------------------ > > > + > > > +This book is a guide to device driver writers on how to register > > > +mailbox controller to the mailbox framework. > > > + > > > +.. toctree:: > > > + :maxdepth: 1 > > > + > > > + writing_mailbox_controller_drivers > > > + > > > +mailbox client driver documentation > > > +------------------------------ > > > > Match up section underline length by its title: > > > > ---- >8 ---- > > diff --git a/Documentation/driver-api/mailbox/index.rst b/Documentation/driver-api/mailbox/index.rst > > index e254a8fdb66ac7..02d7d5e8660999 100644 > > --- a/Documentation/driver-api/mailbox/index.rst > > +++ b/Documentation/driver-api/mailbox/index.rst > > @@ -1,6 +1,6 @@ > > -======================= > > +===================== > > Mailbox documentation > > -======================= > > +===================== > > > > Mailbox documentation provides documents for various aspects of mailbox > > framework. > > @@ -17,7 +17,7 @@ driver writers. > > core > > > > mailbox controller driver documentation > > ------------------------------- > > +--------------------------------------- > > > > This book is a guide to device driver writers on how to register > > mailbox controller to the mailbox framework. > > @@ -28,7 +28,7 @@ mailbox controller to the mailbox framework. > > writing_mailbox_controller_drivers > > > > mailbox client driver documentation > > ------------------------------- > > +----------------------------------- > > > > This book is a guide to mailbox client driver writers. > > > > > > > + > > > +This book is a guide to mailbox client driver writers. > > > + > > > +.. toctree:: > > > + :maxdepth: 1 > > > + > > > + client > > > + > > > +.. only:: subproject and html > > > + > > > + Indices > > > + ======= > > > + > > > + * :ref:`genindex` > > > > Fix up also the reference link on parent toctree: > > > > ---- >8 ---- > > diff --git a/Documentation/driver-api/index.rst b/Documentation/driver-api/index.rst > > index 7f83e05769b4a4..b4d78b92fd921a 100644 > > --- a/Documentation/driver-api/index.rst > > +++ b/Documentation/driver-api/index.rst > > @@ -102,7 +102,7 @@ Subsystem-specific APIs > > ipmb > > ipmi > > libata > > - mailbox > > + mailbox/index > > md/index > > media/index > > mei/index > > > > > diff --git a/Documentation/driver-api/mailbox/writing_mailbox_controller_drivers.rst b/Documentation/driver-api/mailbox/writing_mailbox_controller_drivers.rst > > > new file mode 100644 > > > index 000000000000..2a82645c1357 > > > --- /dev/null > > > +++ b/Documentation/driver-api/mailbox/writing_mailbox_controller_drivers.rst > > > @@ -0,0 +1,179 @@ > > > +.. SPDX-License-Identifier: GPL-2.0 > > > + > > > +.. _writing_mailbox_controller_drivers: > > > + > > > +================================== > > > +Writing Mailbox Controller Drivers > > > +================================== > > > + > > > +Introduction > > > +============ > > > + > > > +This document serves as a basic guideline for driver programmers that need > > > +to hack a new mailbox controller driver or understand the essentials of > > > +the existing ones. > > > + > > > +Driver Boilerplate > > > +================== > > > + > > > +As a bare minimum, a mailbox controller driver needs to call > > > +``mbox_controller_register`` function to register with the framework. > > > + > > > +A basic driver skeleton could look like this for a mailbox hardware that > > > +has the following characteristics: > > > +a. It supports only a single channel, i.e., only the remote processor can > > > + send interrupts. > > > +b. Data transfer is over the registers associated with mailbox hardware. > > > +c. Mailbox hardware is configured to receive interrupts. > > > +d. When the remote processor is ready to send data, it triggers a mailbox > > > + interrupt. > > > +e. As part of interrupt handling by Linux, it copies data from the registers. > > > + > > > +.. code-block:: c > > > + > > > + #include <linux/device.h> > > > + #include <linux/interrupt.h> > > > + #include <linux/io.h> > > > + #include <linux/kernel.h> > > > + #include <linux/mailbox_controller.h> > > > + #include <linux/module.h> > > > + #include <linux/of.h> > > > + #include <linux/platform_device.h> > > > + #define DRIVER_NAME "dummy_controller" > > > + > > > + struct dummy_mbox { > > > + struct device *dev; > > > + struct mbox_controller controller; > > > + int irq; > > > + }; > > > + > > > + static void dummy_mbox_receive(struct mbox_chan *chan) > > > + { > > > + struct dummy_mbox *mbox = chan->con_priv; > > > + int val; > > > + > > > + // Data copied from registers > > > + val = read_register(); > > > + mbox_chan_received_data(chan, &val); > > > + } > > > + > > > + static irqreturn_t dummy_mbox_irq_handler(int irq, void *data) > > > + { > > > + struct mbox_chan *chan = data; > > > + struct dummy_mbox *mbox = chan->con_priv; > > > + u32 reg; > > > + > > > + // Read registers to see if data is received > > > + dummy_mbox_receive(chan); > > > + mbox_chan_txdone(chan, 0); > > > + return reg ? IRQ_HANDLED : IRQ_NONE; > > > + } > > > + > > > + static int dummy_mbox_send_data(struct mbox_chan *chan, void *data) > > > + { > > > + // Write data in registers to send it to the remote processor > > > + return 0; > > > + } > > > + > > > + static int dummy_mbox_startup(struct mbox_chan *chan) > > > + { > > > + struct dummy_mbox *mbox = chan->con_priv; > > > + u32 reg; > > > + int ret; > > > + > > > + ret = devm_request_irq(mbox->dev, mbox->irq, dummy_mbox_irq_handler, 0, > > > + DRIVER_NAME, chan); > > > + if (ret < 0) { > > > + dev_err(mbox->dev, "Cannot request irq\n"); > > > + return ret; > > > + } > > > + > > > + /* Register write to enable IRQ generation */ > > > + > > > + return 0; > > > + } > > > + > > > + static void dummy_mbox_shutdown(struct mbox_chan *chan) > > > + { > > > + struct dummy_mbox *mbox = chan->con_priv; > > > + > > > + /* Disable interrupt generation */ > > > + devm_free_irq(mbox->dev, mbox->irq, chan); > > > + } > > > + > > > + static const struct mbox_chan_ops dummy_mbox_ops = { > > > + .send_data = dummy_mbox_send_data, > > > + .startup = dummy_mbox_startup, > > > + .shutdown = dummy_mbox_shutdown, > > > + }; > > > + > > > + static int dummy_mbox_probe(struct platform_device *pdev) > > > + { > > > + struct dummy_mbox *mbox; > > > + struct mbox_chan *chans; > > > + int ret; > > > + > > > + mbox = devm_kzalloc(&pdev->dev, sizeof(*mbox), GFP_KERNEL); > > > + if (!mbox) > > > + return -ENOMEM; > > > + > > > + /* Allocate one channel */ > > > + chans = devm_kzalloc(&pdev->dev, sizeof(*chans), GFP_KERNEL); > > > + if (!chans) > > > + return -ENOMEM; > > > + > > > + mbox->base = devm_platform_ioremap_resource(pdev, 0); > > > + if (IS_ERR(mbox->base)) > > > + return PTR_ERR(mbox->base); > > > + > > > + mbox->irq = platform_get_irq(pdev, 0); > > > + if (mbox->irq < 0) > > > + return mbox->irq; > > > + > > > + mbox->dev = &pdev->dev; > > > + > > > + /* Hardware supports only one channel. */ > > > + mbox->controller.dev = mbox->dev; > > > + mbox->controller.num_chans = 1; > > > + mbox->controller.chans = chans; > > > + mbox->controller.ops = &dummy_mbox_ops; > > > + mbox->controller.txdone_irq = true; > > > + > > > + ret = devm_mbox_controller_register(mbox->dev, &mbox->controller); > > > + if (ret) { > > > + dev_err(&pdev->dev, "Could not register mailbox controller\n"); > > > + return ret; > > > + } > > > + > > > + return ret; > > > + } > > > + > > > + static const struct of_device_id dummy_mbox_match[] = { > > > + { .compatible = "dummy,dummy-mailbox" }, > > > + { }, > > > + }; > > > + > > > + MODULE_DEVICE_TABLE(of, dummy_mbox_match); > > > + > > > + static struct platform_driver dummy_mbox_driver = { > > > + .probe = dummy_mbox_probe, > > > + .driver = { > > > + .name = DRIVER_NAME, > > > + .of_match_table = dummy_mbox_match, > > > + }, > > > + }; > > > + > > > + module_platform_driver(dummy_mbox_driver); > > > + MODULE_LICENSE("GPL v2"); > > > + MODULE_DESCRIPTION("Dummy mailbox controller driver"); > > > + > > > +In the above code, a couple of things are done: > > > +a. The controller is registered in the probe along with callbacks, which in > > > + this case are the bare minimum: ``startup``, ``shutdown``, and > > > + ``send_data``. > > > +b. IRQ is registered to get notifications from the remote processor. > > > +c. In the IRQ handler, registers are read to copy data, and > > > + ``mbox_chan_received_data`` is called to hand over the data to the client. > > > +d. ``mbox_chan_txdone`` is called to let the framework know that this data > > > + is the last data and no more data is to be expected for the current transfer. > > > + > > > > Sphinx warns out numerous indentation warnings on the lists, so I have to > > fix them up: > > > > ---- >8 ---- > > diff --git a/Documentation/driver-api/mailbox/client.rst b/Documentation/driver-api/mailbox/client.rst > > index 9088f83734230d..17dafaca056777 100644 > > --- a/Documentation/driver-api/mailbox/client.rst > > +++ b/Documentation/driver-api/mailbox/client.rst > > @@ -31,6 +31,7 @@ The mailbox structure is defined as follows: > > Key Functions > > ------------- > > 1. Requesting a Mailbox Channel > > + > > - **Function**: `mbox_request_channel(struct mbox_client *client, > > unsigned int channel)` > > - **Description**: Requests a mailbox channel for sending messages. > > @@ -41,15 +42,19 @@ Key Functions > > code on failure. > > > > 2. Sending a Message > > + > > - **Function**: `mbox_send_message(struct mbox_chan *chan, void *msg)` > > - **Description**: Sends a message through the mailbox channel. > > - **Parameters**: > > + > > - `chan`: The mailbox channel used for communication. > > - `msg`: Pointer to the message to be sent (usually NULL for dummy > > messages). > > + > > - **Returns**: 0 on success, or a negative error code on failure. > > > > 3. Transmitting Completion > > + > > - **Function**: `mbox_client_txdone(struct mbox_chan *chan, unsigned int > > msg_id)` > > - **Description**: Notifies the mailbox framework that message > > diff --git a/Documentation/driver-api/mailbox/core.rst b/Documentation/driver-api/mailbox/core.rst > > index 8d56d81007c11c..239538f497e41a 100644 > > --- a/Documentation/driver-api/mailbox/core.rst > > +++ b/Documentation/driver-api/mailbox/core.rst > > @@ -85,16 +85,20 @@ Data Structures > > - **struct mbox_client** > > This structure represents a client that communicates over a mailbox > > channel. It holds information such as: > > + > > - A pointer to the device associated with the client (`dev`). > > - Callback functions for handling message transmission events, including: > > + > > - `rx_callback`: Called when a message is received. > > - `tx_done`: Called when a message transmission is acknowledged. > > + > > - Flags that specify the client’s configuration, such as whether it operates > > in blocking mode. > > > > - **struct mbox_chan** > > This structure represents an individual mailbox channel. It maintains the > > state required for message queuing and transmission. Key members include: > > + > > - `msg_data`: Array of messages queued for transmission. > > - `msg_count`: Number of messages currently queued. > > - `msg_free`: Index of the next free slot in the message queue. > > @@ -104,6 +108,7 @@ Data Structures > > - **struct mbox_controller** > > This structure represents a mailbox controller that manages multiple > > channels. It includes: > > + > > - A pointer to the device managing the mailbox. > > - Operations for sending and receiving messages, as well as initializing > > and shutting down the mailbox. > > @@ -133,21 +138,20 @@ need to initialize a few fields in there: > > - ``num_chans``: Number of channels in the `chans` array. > > > > - ``txdone_irq``: Indicates if the controller can report to the API > > - when the last transmitted data was read by the > > - remote (e.g., if it has a TX ACK interrupt). > > + when the last transmitted data was read by the remote (e.g., if it has a > > + TX ACK interrupt). > > > > All the below fields are not mandatory. > > > > - ``txdone_poll``: Indicates if the controller can read but not report > > - the TX done. For example, some register may show > > - the TX status, but no interrupt is raised. This > > - field is ignored if `txdone_irq` is set. > > + the TX done. For example, some register may show the TX status, but no > > + interrupt is raised. This field is ignored if `txdone_irq` is set. > > > > - ``txpoll_period``: If `txdone_poll` is in effect, the API polls for > > - the last TX status after this many milliseconds. > > + the last TX status after this many milliseconds. > > > > - ``of_xlate``: Controller driver-specific mapping of channel via > > - Device Tree (DT). > > + Device Tree (DT). > > > > > > Key Functions > > diff --git a/Documentation/driver-api/mailbox/writing_mailbox_controller_drivers.rst b/Documentation/driver-api/mailbox/writing_mailbox_controller_drivers.rst > > index 2a82645c13573e..853adf6918173d 100644 > > --- a/Documentation/driver-api/mailbox/writing_mailbox_controller_drivers.rst > > +++ b/Documentation/driver-api/mailbox/writing_mailbox_controller_drivers.rst > > @@ -21,6 +21,7 @@ As a bare minimum, a mailbox controller driver needs to call > > > > A basic driver skeleton could look like this for a mailbox hardware that > > has the following characteristics: > > + > > a. It supports only a single channel, i.e., only the remote processor can > > send interrupts. > > b. Data transfer is over the registers associated with mailbox hardware. > > @@ -168,6 +169,7 @@ e. As part of interrupt handling by Linux, it copies data from the registers. > > MODULE_DESCRIPTION("Dummy mailbox controller driver"); > > > > In the above code, a couple of things are done: > > + > > a. The controller is registered in the probe along with callbacks, which in > > this case are the bare minimum: ``startup``, ``shutdown``, and > > ``send_data``. > > > > Thanks. > > > > -- > > An old man doll... just what I always wanted! - Clara ^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH 2/2] mailbox: Documentation: add the latest documentation 2024-10-29 18:06 ` anish kumar @ 2024-10-29 23:51 ` Bagas Sanjaya 2024-10-30 0:42 ` anish kumar 2024-10-30 17:41 ` Jassi Brar 1 sibling, 1 reply; 12+ messages in thread From: Bagas Sanjaya @ 2024-10-29 23:51 UTC (permalink / raw) To: anish kumar, jassisinghbrar, Jonathan Corbet; +Cc: linux-doc, linux-kernel On 10/30/24 01:06, anish kumar wrote: > Hello Jassi, > > Gentle reminder for the review. > Reroll. ^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH 2/2] mailbox: Documentation: add the latest documentation 2024-10-29 23:51 ` Bagas Sanjaya @ 2024-10-30 0:42 ` anish kumar 2024-10-30 1:17 ` Bagas Sanjaya 0 siblings, 1 reply; 12+ messages in thread From: anish kumar @ 2024-10-30 0:42 UTC (permalink / raw) To: Bagas Sanjaya; +Cc: jassisinghbrar, Jonathan Corbet, linux-doc, linux-kernel On Tue, Oct 29, 2024 at 4:51 PM Bagas Sanjaya <bagasdotme@gmail.com> wrote: > > On 10/30/24 01:06, anish kumar wrote: > > Hello Jassi, > > > > Gentle reminder for the review. > > > > Reroll. Waiting for him to provide any additional comments otherwise I will have to upload a new rev after that. > ^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH 2/2] mailbox: Documentation: add the latest documentation 2024-10-30 0:42 ` anish kumar @ 2024-10-30 1:17 ` Bagas Sanjaya 0 siblings, 0 replies; 12+ messages in thread From: Bagas Sanjaya @ 2024-10-30 1:17 UTC (permalink / raw) To: anish kumar; +Cc: jassisinghbrar, Jonathan Corbet, linux-doc, linux-kernel [-- Attachment #1: Type: text/plain, Size: 540 bytes --] On Tue, Oct 29, 2024 at 05:42:32PM -0700, anish kumar wrote: > On Tue, Oct 29, 2024 at 4:51 PM Bagas Sanjaya <bagasdotme@gmail.com> wrote: > > > > On 10/30/24 01:06, anish kumar wrote: > > > Hello Jassi, > > > > > > Gentle reminder for the review. > > > > > > > Reroll. > > Waiting for him to provide any additional comments otherwise > I will have to upload a new rev after that. > > IMO you can reroll anyway with my review suggestions applied. Thanks. -- An old man doll... just what I always wanted! - Clara [-- Attachment #2: signature.asc --] [-- Type: application/pgp-signature, Size: 228 bytes --] ^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH 2/2] mailbox: Documentation: add the latest documentation 2024-10-29 18:06 ` anish kumar 2024-10-29 23:51 ` Bagas Sanjaya @ 2024-10-30 17:41 ` Jassi Brar 2024-10-30 18:13 ` anish kumar 1 sibling, 1 reply; 12+ messages in thread From: Jassi Brar @ 2024-10-30 17:41 UTC (permalink / raw) To: anish kumar; +Cc: Jonathan Corbet, linux-doc, linux-kernel, Bagas Sanjaya Hi Anish, It is the third ping within 10 days, please avoid. Documentation is not a high priority, esp when it is mostly copying info from header files. I haven't looked closely and you haven't mentioned in the log what new info are you adding or clearer? From a quick look it seems just api explanation copied into doc format. Will look closer later. Thanks On Tue, Oct 29, 2024 at 1:06 PM anish kumar <yesanishhere@gmail.com> wrote: > > Hello Jassi, > > Gentle reminder for the review. > > On Fri, Oct 25, 2024 at 12:24 PM anish kumar <yesanishhere@gmail.com> wrote: > > > > Hello Jassi, > > > > I hope to get some more comments from you before > > spinning up a new revision. > > > > On Thu, Oct 24, 2024 at 8:38 PM Bagas Sanjaya <bagasdotme@gmail.com> wrote: > > > > > > On Sat, Oct 19, 2024 at 12:55:34PM -0700, anish kumar wrote: > > > > 1. added client documentation > > > > 2. added controller documentation. > > > > 3. added framework documentation > > > > > > One doc topic on each patch, please. > > > > > > > > > > > Signed-off-by: anish kumar <yesanishhere@gmail.com> > > > > --- > > > > Documentation/driver-api/mailbox/client.rst | 192 ++++++++++++++++++ > > > > Documentation/driver-api/mailbox/core.rst | 182 +++++++++++++++++ > > > > Documentation/driver-api/mailbox/index.rst | 45 ++++ > > > > .../writing_mailbox_controller_drivers.rst | 179 ++++++++++++++++ > > > > 4 files changed, 598 insertions(+) > > > > create mode 100644 Documentation/driver-api/mailbox/client.rst > > > > create mode 100644 Documentation/driver-api/mailbox/core.rst > > > > create mode 100644 Documentation/driver-api/mailbox/index.rst > > > > create mode 100644 Documentation/driver-api/mailbox/writing_mailbox_controller_drivers.rst > > > > > > > > diff --git a/Documentation/driver-api/mailbox/client.rst b/Documentation/driver-api/mailbox/client.rst > > > > new file mode 100644 > > > > index 000000000000..9088f8373423 > > > > --- /dev/null > > > > +++ b/Documentation/driver-api/mailbox/client.rst > > > > @@ -0,0 +1,192 @@ > > > > +Mailbox Client Documentation > > > > +============================ > > > > + > > > > +Overview > > > > +-------- > > > > +The mailbox client driver is responsible for sending and receiving messages > > > > +to and from a remote processor. It uses mailbox APIs provided by the > > > > +mailbox framework. > > > > + > > > > +Mailbox Structure > > > > +----------------- > > > > +The mailbox structure is defined as follows: > > > > + > > > > +.. code-block:: c > > > > + > > > > + struct mbox_client { > > > > + //device associated with the mailbox > > > > + struct device *dev; > > > > + // callback for transmission completion > > > > + void (*tx_done)(struct mbox_client *client); > > > > + // callback to prepare for sending a message > > > > + void (*tx_prepare)(struct mbox_client *client); > > > > + // callback for received messages > > > > + void (*rx_callback)(struct mbox_client *client, void *data); > > > > + // flag to indicate if transmission should block > > > > + bool tx_block; > > > > + // indicates if the client knows when transmission is done > > > > + bool knows_txdone; > > > > + }; > > > > + > > > > +Key Functions > > > > +------------- > > > > +1. Requesting a Mailbox Channel > > > > + - **Function**: `mbox_request_channel(struct mbox_client *client, > > > > + unsigned int channel)` > > > > + - **Description**: Requests a mailbox channel for sending messages. > > > > + - **Parameters**: > > > > + - `client`: Pointer to the mailbox client structure. > > > > + - `channel`: The specific mailbox channel to request. > > > > + - **Returns**: A pointer to the mailbox channel on success, or an error > > > > + code on failure. > > > > + > > > > +2. Sending a Message > > > > + - **Function**: `mbox_send_message(struct mbox_chan *chan, void *msg)` > > > > + - **Description**: Sends a message through the mailbox channel. > > > > + - **Parameters**: > > > > + - `chan`: The mailbox channel used for communication. > > > > + - `msg`: Pointer to the message to be sent (usually NULL for dummy > > > > + messages). > > > > + - **Returns**: 0 on success, or a negative error code on failure. > > > > + > > > > +3. Transmitting Completion > > > > + - **Function**: `mbox_client_txdone(struct mbox_chan *chan, unsigned int > > > > + msg_id)` > > > > + - **Description**: Notifies the mailbox framework that message > > > > + transmission is complete. > > > > + - **Parameters**: > > > > + - `chan`: The mailbox channel associated with the message. > > > > + - `msg_id`: The identifier of the message that was transmitted. > > > > > > These functions should've been documented as kernel-doc comments, though. > > > > > > > + > > > > +Usage Example > > > > +------------- > > > > +In a typical mailbox client driver, the following steps are typically > > > > +performed: > > > > + > > > > +1. Initialize the Mailbox Client: > > > > + > > > > + .. code-block:: c > > > > + > > > > + struct mbox_client my_mbox_client = { > > > > + .dev = &my_device, > > > > + .tx_done = my_tx_done_callback, > > > > + .rx_callback = my_rx_callback, > > > > + .tx_block = false, > > > > + .knows_txdone = true, > > > > + }; > > > > + > > > > +2. Request a Mailbox Channel: > > > > + > > > > + .. code-block:: c > > > > + > > > > + mbox_chan = mbox_request_channel(&my_mbox_client, 0); > > > > + if (IS_ERR(mbox_chan)) { > > > > + // Handle error > > > > + } > > > > + > > > > +3. Send a Message: > > > > + > > > > + .. code-block:: c > > > > + > > > > + int ret = mbox_send_message(mbox_chan, NULL); // Sending a dummy message > > > > + if (ret < 0) { > > > > + // Handle error > > > > + } > > > > + > > > > +4. Complete Transmission: > > > > + > > > > + .. code-block:: c > > > > + > > > > + mbox_client_txdone(mbox_chan, 0); > > > > + > > > > +Interrupt Handling > > > > +------------------ > > > > +The mailbox interface can trigger interrupts upon message receipt. Handlers > > > > +should be implemented in the `rx_callback` function defined in the mailbox > > > > +client structure to process incoming messages. > > > > + > > > > +Example Mailbox Client Driver > > > > +----------------------------- > > > > +.. code-block:: c > > > > + > > > > + struct demo_client { > > > > + struct mbox_client cl; > > > > + struct mbox_chan *mbox; > > > > + struct completion c; > > > > + bool async; > > > > + /* ... */ > > > > + }; > > > > + > > > > + /* > > > > + * This is the handler for data received from remote. The behaviour is purely > > > > + * dependent upon the protocol. This is just an example. > > > > + */ > > > > + static void message_from_remote(struct mbox_client *cl, void *mssg) > > > > + { > > > > + struct demo_client *dc = container_of(cl, struct demo_client, cl); > > > > + if (dc->async) { > > > > + if (is_an_ack(mssg)) { > > > > + /* An ACK to our last sample sent */ > > > > + return; /* Or do something else here */ > > > > + } else { /* A new message from remote */ > > > > + queue_req(mssg); > > > > + } > > > > + } else { > > > > + /* Remote f/w sends only ACK packets on this channel */ > > > > + return; > > > > + } > > > > + } > > > > + > > > > + static void sample_sent(struct mbox_client *cl, void *mssg, int r) > > > > + { > > > > + struct demo_client *dc = container_of(cl, struct demo_client, cl); > > > > + complete(&dc->c); > > > > + } > > > > + > > > > + static void client_demo(struct platform_device *pdev) > > > > + { > > > > + struct demo_client *dc_sync, *dc_async; > > > > + /* The controller already knows async_pkt and sync_pkt */ > > > > + struct async_pkt ap; > > > > + struct sync_pkt sp; > > > > + > > > > + dc_sync = kzalloc(sizeof(*dc_sync), GFP_KERNEL); > > > > + dc_async = kzalloc(sizeof(*dc_async), GFP_KERNEL); > > > > + > > > > + /* Populate non-blocking mode client */ > > > > + dc_async->cl.dev = &pdev->dev; > > > > + dc_async->cl.rx_callback = message_from_remote; > > > > + dc_async->cl.tx_done = sample_sent; > > > > + dc_async->cl.tx_block = false; > > > > + dc_async->cl.tx_tout = 0; /* doesn't matter here */ > > > > + dc_async->cl.knows_txdone = false; /* depending upon protocol */ > > > > + dc_async->async = true; > > > > + init_completion(&dc_async->c); > > > > + > > > > + /* Populate blocking mode client */ > > > > + dc_sync->cl.dev = &pdev->dev; > > > > + dc_sync->cl.rx_callback = message_from_remote; > > > > + dc_sync->cl.tx_done = NULL; /* operate in blocking mode */ > > > > + dc_sync->cl.tx_block = true; > > > > + dc_sync->cl.tx_tout = 500; /* by half a second */ > > > > + dc_sync->cl.knows_txdone = false; /* depending upon protocol */ > > > > + dc_sync->async = false; > > > > + > > > > + /* ASync mailbox is listed second in 'mboxes' property */ > > > > + dc_async->mbox = mbox_request_channel(&dc_async->cl, 1); > > > > + /* Populate data packet */ > > > > + /* ap.xxx = 123; etc */ > > > > + /* Send async message to remote */ > > > > + mbox_send_message(dc_async->mbox, &ap); > > > > + > > > > + /* Sync mailbox is listed first in 'mboxes' property */ > > > > + dc_sync->mbox = mbox_request_channel(&dc_sync->cl, 0); > > > > + /* Populate data packet */ > > > > + /* sp.abc = 123; etc */ > > > > + /* Send message to remote in blocking mode */ > > > > + mbox_send_message(dc_sync->mbox, &sp); > > > > + /* At this point 'sp' has been sent */ > > > > + > > > > + /* Now wait for async chan to be done */ > > > > + wait_for_completion(&dc_async->c); > > > > + } > > > > diff --git a/Documentation/driver-api/mailbox/core.rst b/Documentation/driver-api/mailbox/core.rst > > > > new file mode 100644 > > > > index 000000000000..d1220086da67 > > > > --- /dev/null > > > > +++ b/Documentation/driver-api/mailbox/core.rst > > > > @@ -0,0 +1,182 @@ > > > > +===================== > > > > +mailbox documentation > > > > +===================== > > > > + > > > > +Hardware Introduction > > > > +===================== > > > > + > > > > +Mailbox hardware is a specialized component found in multi-core > > > > +processors and embedded systems that facilitates inter-processor > > > > +communication (IPC) or communication between different hardware > > > > +components. It provides a structured mechanism for sending and > > > > +receiving messages, allowing various processors or devices to > > > > +exchange data efficiently. Here's an overview of its key > > > > +characteristics and functions: > > > > + > > > > +Key Characteristics of Mailbox Hardware > > > > +Interrupt Handling: Many mailbox implementations support > > > > +interrupt-driven communication. This allows a receiving processor > > > > +to be alerted when a new message arrives, facilitating immediate > > > > +processing without polling the mailbox constantly. > > > > + > > > > +Hardware Registers: Mailbox hardware often includes registers for > > > > +configuration and status monitoring. These registers can be used > > > > +to control the mailbox's behavior, check for available messages, > > > > +or acknowledge message receipt. > > > > + > > > > +Support for Multiple Protocols: Mailboxes can support various > > > > +communication protocols, enabling interoperability between different > > > > +hardware components and simplifying the integration of diverse systems. > > > > + > > > > +Synchronous and Asynchronous Modes: Mailbox hardware can operate in > > > > +both synchronous and asynchronous modes. In synchronous mode, the > > > > +sender may wait for the receiver to acknowledge receipt before > > > > +proceeding, while in asynchronous mode, the sender can continue > > > > +executing other tasks immediately after sending the message. > > > > + > > > > + > > > > +Mailbox framework design > > > > +======================== > > > > + > > > > +The mailbox facilitates interprocessor communication by allowing processors to > > > > +exchange messages or signals. The mailbox framework consists of: > > > > + > > > > +Mailbox Controller: This is platform-specific and is responsible for configuring > > > > +and managing interrupts from the remote processor. It offers a generic API for > > > > +the mailbox client. > > > > + > > > > +Mailbox Client: This component handles the sending and receiving of messages. > > > > + > > > > + > > > > +............................................................................ > > > > +: client driver client_a client_b : > > > > +............................................................................ > > > > + ^-------------------^ > > > > + | > > > > + | > > > > +............................................................................ > > > > +: controller framework mailbox : > > > > +....................................|....................................... > > > > + | > > > > + | > > > > +............................................................................ > > > > +: controller driver device specific : > > > > +....................................|....................................... > > > > + | > > > > + | > > > > +kernel | > > > > +............................................................................ > > > > +hardware | > > > > + | > > > > + | > > > > +............................................................................ > > > > +: remote processor : > > > > +............................................................................ > > > > > > htmldocs build errors out: > > > > > > Documentation/driver-api/mailbox/core.rst:57: WARNING: Block quote ends without a blank line; unexpected unindent. > > > Documentation/driver-api/mailbox/core.rst:57: CRITICAL: Missing matching underline for section title overline. > > > > > > ............................................................................ > > > : controller framework mailbox : > > > ....................................|....................................... > > > > > > reST markup error: > > > Documentation/driver-api/mailbox/core.rst:57: (SEVERE/4) Missing matching underline for section title overline. > > > > > > ............................................................................ > > > : controller framework mailbox : > > > ....................................|....................................... > > > > > > I have to fix up the design diagram and wrap it: > > > > > > ---- >8 ---- > > > diff --git a/Documentation/driver-api/mailbox/core.rst b/Documentation/driver-api/mailbox/core.rst > > > index d1220086da679f..8d56d81007c11c 100644 > > > --- a/Documentation/driver-api/mailbox/core.rst > > > +++ b/Documentation/driver-api/mailbox/core.rst > > > @@ -47,31 +47,32 @@ the mailbox client. > > > > > > Mailbox Client: This component handles the sending and receiving of messages. > > > > > > +:: > > > > > > -............................................................................ > > > -: client driver client_a client_b : > > > -............................................................................ > > > - ^-------------------^ > > > - | > > > - | > > > -............................................................................ > > > -: controller framework mailbox : > > > -....................................|....................................... > > > - | > > > - | > > > -............................................................................ > > > -: controller driver device specific : > > > -....................................|....................................... > > > - | > > > - | > > > -kernel | > > > -............................................................................ > > > -hardware | > > > - | > > > - | > > > -............................................................................ > > > -: remote processor : > > > -............................................................................ > > > + +---------------------------------------------------------------------------+ > > > + | client driver client_a client_b | > > > + +---------------------------------------------------------------------------+ > > > + ^-------------------^ > > > + | > > > + | > > > + +--------------------------------------------------------------------------+ > > > + | controller framework mailbox | > > > + +-----------------------------------|--------------------------------------+ > > > + | > > > + | > > > + +--------------------------------------------------------------------------+ > > > + | controller driver device specific | > > > + +-----------------------------------|--------------------------------------+ > > > + | > > > + | > > > + kernel | > > > + ---------------------------------------------------------------------------- > > > + hardware | > > > + | > > > + | > > > + +--------------------------------------------------------------------------+ > > > + | remote processor | > > > + +--------------------------------------------------------------------------+ > > > > > > > > > In the context of a mailbox framework, a channel refers to a dedicated > > > > > > > + > > > > + > > > > +In the context of a mailbox framework, a channel refers to a dedicated > > > > +communication pathway between two or more processors or components. By using > > > > +channels, the framework abstracts the complexity of interprocessor communication. > > > > + > > > > +Data Structures > > > > +================ > > > > + > > > > +- **struct mbox_client** > > > > + This structure represents a client that communicates over a mailbox > > > > + channel. It holds information such as: > > > > + - A pointer to the device associated with the client (`dev`). > > > > + - Callback functions for handling message transmission events, including: > > > > + - `rx_callback`: Called when a message is received. > > > > + - `tx_done`: Called when a message transmission is acknowledged. > > > > + - Flags that specify the client’s configuration, such as whether it operates > > > > + in blocking mode. > > > > + > > > > +- **struct mbox_chan** > > > > + This structure represents an individual mailbox channel. It maintains the > > > > + state required for message queuing and transmission. Key members include: > > > > + - `msg_data`: Array of messages queued for transmission. > > > > + - `msg_count`: Number of messages currently queued. > > > > + - `msg_free`: Index of the next free slot in the message queue. > > > > + - `active_req`: Pointer to the currently active message being transmitted. > > > > + - Synchronization primitives to manage access from multiple contexts. > > > > + > > > > +- **struct mbox_controller** > > > > + This structure represents a mailbox controller that manages multiple > > > > + channels. It includes: > > > > + - A pointer to the device managing the mailbox. > > > > + - Operations for sending and receiving messages, as well as initializing > > > > + and shutting down the mailbox. > > > > + - A list of associated channels and the total number of channels available. > > > > > > Shouldn't these structs be documented as kernel-doc comments? tl;dr: > > > see Documentation/doc-guide/kernel-doc.html > > > > > > > + > > > > +controller framework APIs > > > > +========================= > > > > + > > > > +``struct `mbox_controller` Initialization > > > > +----------------------------------------- > > > > > > Properly double-backquote the struct name to format it as inline code: > > > > > > ---- >8 ---- > > > diff --git a/Documentation/driver-api/mailbox/core.rst b/Documentation/driver-api/mailbox/core.rst > > > index 239538f497e41a..d83456164464aa 100644 > > > --- a/Documentation/driver-api/mailbox/core.rst > > > +++ b/Documentation/driver-api/mailbox/core.rst > > > @@ -117,7 +117,7 @@ Data Structures > > > controller framework APIs > > > ========================= > > > > > > -``struct `mbox_controller` Initialization > > > +``struct mbox_controller`` Initialization > > > ----------------------------------------- > > > > > > Just like any other kernel framework, the whole mailbox controller registration > > > > > > > + > > > > +Just like any other kernel framework, the whole mailbox controller registration > > > > +relies on the driver filling a structure and registering against the > > > > +framework. In our case, that structure is mbox_controller. > > > > + > > > > +The first thing you need to do in your driver is to allocate this > > > > +structure. Any of the usual memory allocators will do, but you'll also > > > > +need to initialize a few fields in there: > > > > + > > > > +- ``dev``: should hold the pointer to the ``struct device`` associated > > > > + to your current driver instance. > > > > + > > > > +- ``ops``: Operators that work on each communication channel. > > > > + > > > > +- ``chans``: Array of channels. > > > > + > > > > +- ``num_chans``: Number of channels in the `chans` array. > > > > + > > > > +- ``txdone_irq``: Indicates if the controller can report to the API > > > > + when the last transmitted data was read by the > > > > + remote (e.g., if it has a TX ACK interrupt). > > > > + > > > > +All the below fields are not mandatory. > > > > + > > > > +- ``txdone_poll``: Indicates if the controller can read but not report > > > > + the TX done. For example, some register may show > > > > + the TX status, but no interrupt is raised. This > > > > + field is ignored if `txdone_irq` is set. > > > > + > > > > +- ``txpoll_period``: If `txdone_poll` is in effect, the API polls for > > > > + the last TX status after this many milliseconds. > > > > + > > > > +- ``of_xlate``: Controller driver-specific mapping of channel via > > > > + Device Tree (DT). > > > > + > > > > + > > > > +Key Functions > > > > +------------- > > > > + > > > > +- **int devm_mbox_controller_register(struct mbox_controller *mbox)** > > > > + This function registers a mailbox controller with the kernel. It makes the > > > > + channels associated with the controller available for client requests. The > > > > + function performs sanity checks on the controller structure to ensure all > > > > + necessary fields are populated. > > > > + > > > > +- **struct mbox_chan *mbox_request_channel(struct mbox_client *cl, int index)** > > > > + This function requests a mailbox channel for a specified client, identified > > > > + by an index. It searches for the appropriate mailbox channel, and if found, > > > > + it returns a pointer to the channel. If the request fails (e.g., if the > > > > + index is invalid), it returns an error pointer. > > > > + > > > > +- **void mbox_free_channel(struct mbox_chan *chan)** > > > > + This function releases a mailbox channel that was previously allocated for a > > > > + client. It ensures that the channel can be reused by other clients. If any > > > > + messages are still in the queue, they are aborted, and no callbacks are made. > > > > + > > > > +- **int mbox_send_message(struct mbox_chan *chan, void *mssg)** > > > > + This function is used by clients to send a message through the specified > > > > + mailbox channel. The function can operate in either blocking or non-blocking > > > > + mode, depending on the client’s configuration. It will queue the message for > > > > + transmission and notify the client once the message is acknowledged. > > > > + > > > > +- **void mbox_chan_received_data(struct mbox_chan *chan, void *mssg)** > > > > + This function is called by the controller driver to notify the mailbox > > > > + framework that a message has been received on the specified channel. The > > > > + received message is then passed to the appropriate client's `rx_callback` > > > > + function for processing. > > > > > > Shouldn't these functions also be documented as kernel-doc comments? > > > > > > > diff --git a/Documentation/driver-api/mailbox/index.rst b/Documentation/driver-api/mailbox/index.rst > > > > new file mode 100644 > > > > index 000000000000..e254a8fdb66a > > > > --- /dev/null > > > > +++ b/Documentation/driver-api/mailbox/index.rst > > > > @@ -0,0 +1,45 @@ > > > > +======================= > > > > +Mailbox documentation > > > > +======================= > > > > + > > > > +Mailbox documentation provides documents for various aspects of mailbox > > > > +framework. > > > > + > > > > +Mailbox development documentation > > > > +--------------------------------- > > > > + > > > > +This book helps with mailbox internal APIs and guide for mailbox device > > > > +driver writers. > > > > + > > > > +.. toctree:: > > > > + :maxdepth: 1 > > > > + > > > > + core > > > > + > > > > +mailbox controller driver documentation > > > > +------------------------------ > > > > + > > > > +This book is a guide to device driver writers on how to register > > > > +mailbox controller to the mailbox framework. > > > > + > > > > +.. toctree:: > > > > + :maxdepth: 1 > > > > + > > > > + writing_mailbox_controller_drivers > > > > + > > > > +mailbox client driver documentation > > > > +------------------------------ > > > > > > Match up section underline length by its title: > > > > > > ---- >8 ---- > > > diff --git a/Documentation/driver-api/mailbox/index.rst b/Documentation/driver-api/mailbox/index.rst > > > index e254a8fdb66ac7..02d7d5e8660999 100644 > > > --- a/Documentation/driver-api/mailbox/index.rst > > > +++ b/Documentation/driver-api/mailbox/index.rst > > > @@ -1,6 +1,6 @@ > > > -======================= > > > +===================== > > > Mailbox documentation > > > -======================= > > > +===================== > > > > > > Mailbox documentation provides documents for various aspects of mailbox > > > framework. > > > @@ -17,7 +17,7 @@ driver writers. > > > core > > > > > > mailbox controller driver documentation > > > ------------------------------- > > > +--------------------------------------- > > > > > > This book is a guide to device driver writers on how to register > > > mailbox controller to the mailbox framework. > > > @@ -28,7 +28,7 @@ mailbox controller to the mailbox framework. > > > writing_mailbox_controller_drivers > > > > > > mailbox client driver documentation > > > ------------------------------- > > > +----------------------------------- > > > > > > This book is a guide to mailbox client driver writers. > > > > > > > > > > + > > > > +This book is a guide to mailbox client driver writers. > > > > + > > > > +.. toctree:: > > > > + :maxdepth: 1 > > > > + > > > > + client > > > > + > > > > +.. only:: subproject and html > > > > + > > > > + Indices > > > > + ======= > > > > + > > > > + * :ref:`genindex` > > > > > > Fix up also the reference link on parent toctree: > > > > > > ---- >8 ---- > > > diff --git a/Documentation/driver-api/index.rst b/Documentation/driver-api/index.rst > > > index 7f83e05769b4a4..b4d78b92fd921a 100644 > > > --- a/Documentation/driver-api/index.rst > > > +++ b/Documentation/driver-api/index.rst > > > @@ -102,7 +102,7 @@ Subsystem-specific APIs > > > ipmb > > > ipmi > > > libata > > > - mailbox > > > + mailbox/index > > > md/index > > > media/index > > > mei/index > > > > > > > diff --git a/Documentation/driver-api/mailbox/writing_mailbox_controller_drivers.rst b/Documentation/driver-api/mailbox/writing_mailbox_controller_drivers.rst > > > > new file mode 100644 > > > > index 000000000000..2a82645c1357 > > > > --- /dev/null > > > > +++ b/Documentation/driver-api/mailbox/writing_mailbox_controller_drivers.rst > > > > @@ -0,0 +1,179 @@ > > > > +.. SPDX-License-Identifier: GPL-2.0 > > > > + > > > > +.. _writing_mailbox_controller_drivers: > > > > + > > > > +================================== > > > > +Writing Mailbox Controller Drivers > > > > +================================== > > > > + > > > > +Introduction > > > > +============ > > > > + > > > > +This document serves as a basic guideline for driver programmers that need > > > > +to hack a new mailbox controller driver or understand the essentials of > > > > +the existing ones. > > > > + > > > > +Driver Boilerplate > > > > +================== > > > > + > > > > +As a bare minimum, a mailbox controller driver needs to call > > > > +``mbox_controller_register`` function to register with the framework. > > > > + > > > > +A basic driver skeleton could look like this for a mailbox hardware that > > > > +has the following characteristics: > > > > +a. It supports only a single channel, i.e., only the remote processor can > > > > + send interrupts. > > > > +b. Data transfer is over the registers associated with mailbox hardware. > > > > +c. Mailbox hardware is configured to receive interrupts. > > > > +d. When the remote processor is ready to send data, it triggers a mailbox > > > > + interrupt. > > > > +e. As part of interrupt handling by Linux, it copies data from the registers. > > > > + > > > > +.. code-block:: c > > > > + > > > > + #include <linux/device.h> > > > > + #include <linux/interrupt.h> > > > > + #include <linux/io.h> > > > > + #include <linux/kernel.h> > > > > + #include <linux/mailbox_controller.h> > > > > + #include <linux/module.h> > > > > + #include <linux/of.h> > > > > + #include <linux/platform_device.h> > > > > + #define DRIVER_NAME "dummy_controller" > > > > + > > > > + struct dummy_mbox { > > > > + struct device *dev; > > > > + struct mbox_controller controller; > > > > + int irq; > > > > + }; > > > > + > > > > + static void dummy_mbox_receive(struct mbox_chan *chan) > > > > + { > > > > + struct dummy_mbox *mbox = chan->con_priv; > > > > + int val; > > > > + > > > > + // Data copied from registers > > > > + val = read_register(); > > > > + mbox_chan_received_data(chan, &val); > > > > + } > > > > + > > > > + static irqreturn_t dummy_mbox_irq_handler(int irq, void *data) > > > > + { > > > > + struct mbox_chan *chan = data; > > > > + struct dummy_mbox *mbox = chan->con_priv; > > > > + u32 reg; > > > > + > > > > + // Read registers to see if data is received > > > > + dummy_mbox_receive(chan); > > > > + mbox_chan_txdone(chan, 0); > > > > + return reg ? IRQ_HANDLED : IRQ_NONE; > > > > + } > > > > + > > > > + static int dummy_mbox_send_data(struct mbox_chan *chan, void *data) > > > > + { > > > > + // Write data in registers to send it to the remote processor > > > > + return 0; > > > > + } > > > > + > > > > + static int dummy_mbox_startup(struct mbox_chan *chan) > > > > + { > > > > + struct dummy_mbox *mbox = chan->con_priv; > > > > + u32 reg; > > > > + int ret; > > > > + > > > > + ret = devm_request_irq(mbox->dev, mbox->irq, dummy_mbox_irq_handler, 0, > > > > + DRIVER_NAME, chan); > > > > + if (ret < 0) { > > > > + dev_err(mbox->dev, "Cannot request irq\n"); > > > > + return ret; > > > > + } > > > > + > > > > + /* Register write to enable IRQ generation */ > > > > + > > > > + return 0; > > > > + } > > > > + > > > > + static void dummy_mbox_shutdown(struct mbox_chan *chan) > > > > + { > > > > + struct dummy_mbox *mbox = chan->con_priv; > > > > + > > > > + /* Disable interrupt generation */ > > > > + devm_free_irq(mbox->dev, mbox->irq, chan); > > > > + } > > > > + > > > > + static const struct mbox_chan_ops dummy_mbox_ops = { > > > > + .send_data = dummy_mbox_send_data, > > > > + .startup = dummy_mbox_startup, > > > > + .shutdown = dummy_mbox_shutdown, > > > > + }; > > > > + > > > > + static int dummy_mbox_probe(struct platform_device *pdev) > > > > + { > > > > + struct dummy_mbox *mbox; > > > > + struct mbox_chan *chans; > > > > + int ret; > > > > + > > > > + mbox = devm_kzalloc(&pdev->dev, sizeof(*mbox), GFP_KERNEL); > > > > + if (!mbox) > > > > + return -ENOMEM; > > > > + > > > > + /* Allocate one channel */ > > > > + chans = devm_kzalloc(&pdev->dev, sizeof(*chans), GFP_KERNEL); > > > > + if (!chans) > > > > + return -ENOMEM; > > > > + > > > > + mbox->base = devm_platform_ioremap_resource(pdev, 0); > > > > + if (IS_ERR(mbox->base)) > > > > + return PTR_ERR(mbox->base); > > > > + > > > > + mbox->irq = platform_get_irq(pdev, 0); > > > > + if (mbox->irq < 0) > > > > + return mbox->irq; > > > > + > > > > + mbox->dev = &pdev->dev; > > > > + > > > > + /* Hardware supports only one channel. */ > > > > + mbox->controller.dev = mbox->dev; > > > > + mbox->controller.num_chans = 1; > > > > + mbox->controller.chans = chans; > > > > + mbox->controller.ops = &dummy_mbox_ops; > > > > + mbox->controller.txdone_irq = true; > > > > + > > > > + ret = devm_mbox_controller_register(mbox->dev, &mbox->controller); > > > > + if (ret) { > > > > + dev_err(&pdev->dev, "Could not register mailbox controller\n"); > > > > + return ret; > > > > + } > > > > + > > > > + return ret; > > > > + } > > > > + > > > > + static const struct of_device_id dummy_mbox_match[] = { > > > > + { .compatible = "dummy,dummy-mailbox" }, > > > > + { }, > > > > + }; > > > > + > > > > + MODULE_DEVICE_TABLE(of, dummy_mbox_match); > > > > + > > > > + static struct platform_driver dummy_mbox_driver = { > > > > + .probe = dummy_mbox_probe, > > > > + .driver = { > > > > + .name = DRIVER_NAME, > > > > + .of_match_table = dummy_mbox_match, > > > > + }, > > > > + }; > > > > + > > > > + module_platform_driver(dummy_mbox_driver); > > > > + MODULE_LICENSE("GPL v2"); > > > > + MODULE_DESCRIPTION("Dummy mailbox controller driver"); > > > > + > > > > +In the above code, a couple of things are done: > > > > +a. The controller is registered in the probe along with callbacks, which in > > > > + this case are the bare minimum: ``startup``, ``shutdown``, and > > > > + ``send_data``. > > > > +b. IRQ is registered to get notifications from the remote processor. > > > > +c. In the IRQ handler, registers are read to copy data, and > > > > + ``mbox_chan_received_data`` is called to hand over the data to the client. > > > > +d. ``mbox_chan_txdone`` is called to let the framework know that this data > > > > + is the last data and no more data is to be expected for the current transfer. > > > > + > > > > > > Sphinx warns out numerous indentation warnings on the lists, so I have to > > > fix them up: > > > > > > ---- >8 ---- > > > diff --git a/Documentation/driver-api/mailbox/client.rst b/Documentation/driver-api/mailbox/client.rst > > > index 9088f83734230d..17dafaca056777 100644 > > > --- a/Documentation/driver-api/mailbox/client.rst > > > +++ b/Documentation/driver-api/mailbox/client.rst > > > @@ -31,6 +31,7 @@ The mailbox structure is defined as follows: > > > Key Functions > > > ------------- > > > 1. Requesting a Mailbox Channel > > > + > > > - **Function**: `mbox_request_channel(struct mbox_client *client, > > > unsigned int channel)` > > > - **Description**: Requests a mailbox channel for sending messages. > > > @@ -41,15 +42,19 @@ Key Functions > > > code on failure. > > > > > > 2. Sending a Message > > > + > > > - **Function**: `mbox_send_message(struct mbox_chan *chan, void *msg)` > > > - **Description**: Sends a message through the mailbox channel. > > > - **Parameters**: > > > + > > > - `chan`: The mailbox channel used for communication. > > > - `msg`: Pointer to the message to be sent (usually NULL for dummy > > > messages). > > > + > > > - **Returns**: 0 on success, or a negative error code on failure. > > > > > > 3. Transmitting Completion > > > + > > > - **Function**: `mbox_client_txdone(struct mbox_chan *chan, unsigned int > > > msg_id)` > > > - **Description**: Notifies the mailbox framework that message > > > diff --git a/Documentation/driver-api/mailbox/core.rst b/Documentation/driver-api/mailbox/core.rst > > > index 8d56d81007c11c..239538f497e41a 100644 > > > --- a/Documentation/driver-api/mailbox/core.rst > > > +++ b/Documentation/driver-api/mailbox/core.rst > > > @@ -85,16 +85,20 @@ Data Structures > > > - **struct mbox_client** > > > This structure represents a client that communicates over a mailbox > > > channel. It holds information such as: > > > + > > > - A pointer to the device associated with the client (`dev`). > > > - Callback functions for handling message transmission events, including: > > > + > > > - `rx_callback`: Called when a message is received. > > > - `tx_done`: Called when a message transmission is acknowledged. > > > + > > > - Flags that specify the client’s configuration, such as whether it operates > > > in blocking mode. > > > > > > - **struct mbox_chan** > > > This structure represents an individual mailbox channel. It maintains the > > > state required for message queuing and transmission. Key members include: > > > + > > > - `msg_data`: Array of messages queued for transmission. > > > - `msg_count`: Number of messages currently queued. > > > - `msg_free`: Index of the next free slot in the message queue. > > > @@ -104,6 +108,7 @@ Data Structures > > > - **struct mbox_controller** > > > This structure represents a mailbox controller that manages multiple > > > channels. It includes: > > > + > > > - A pointer to the device managing the mailbox. > > > - Operations for sending and receiving messages, as well as initializing > > > and shutting down the mailbox. > > > @@ -133,21 +138,20 @@ need to initialize a few fields in there: > > > - ``num_chans``: Number of channels in the `chans` array. > > > > > > - ``txdone_irq``: Indicates if the controller can report to the API > > > - when the last transmitted data was read by the > > > - remote (e.g., if it has a TX ACK interrupt). > > > + when the last transmitted data was read by the remote (e.g., if it has a > > > + TX ACK interrupt). > > > > > > All the below fields are not mandatory. > > > > > > - ``txdone_poll``: Indicates if the controller can read but not report > > > - the TX done. For example, some register may show > > > - the TX status, but no interrupt is raised. This > > > - field is ignored if `txdone_irq` is set. > > > + the TX done. For example, some register may show the TX status, but no > > > + interrupt is raised. This field is ignored if `txdone_irq` is set. > > > > > > - ``txpoll_period``: If `txdone_poll` is in effect, the API polls for > > > - the last TX status after this many milliseconds. > > > + the last TX status after this many milliseconds. > > > > > > - ``of_xlate``: Controller driver-specific mapping of channel via > > > - Device Tree (DT). > > > + Device Tree (DT). > > > > > > > > > Key Functions > > > diff --git a/Documentation/driver-api/mailbox/writing_mailbox_controller_drivers.rst b/Documentation/driver-api/mailbox/writing_mailbox_controller_drivers.rst > > > index 2a82645c13573e..853adf6918173d 100644 > > > --- a/Documentation/driver-api/mailbox/writing_mailbox_controller_drivers.rst > > > +++ b/Documentation/driver-api/mailbox/writing_mailbox_controller_drivers.rst > > > @@ -21,6 +21,7 @@ As a bare minimum, a mailbox controller driver needs to call > > > > > > A basic driver skeleton could look like this for a mailbox hardware that > > > has the following characteristics: > > > + > > > a. It supports only a single channel, i.e., only the remote processor can > > > send interrupts. > > > b. Data transfer is over the registers associated with mailbox hardware. > > > @@ -168,6 +169,7 @@ e. As part of interrupt handling by Linux, it copies data from the registers. > > > MODULE_DESCRIPTION("Dummy mailbox controller driver"); > > > > > > In the above code, a couple of things are done: > > > + > > > a. The controller is registered in the probe along with callbacks, which in > > > this case are the bare minimum: ``startup``, ``shutdown``, and > > > ``send_data``. > > > > > > Thanks. > > > > > > -- > > > An old man doll... just what I always wanted! - Clara ^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH 2/2] mailbox: Documentation: add the latest documentation 2024-10-30 17:41 ` Jassi Brar @ 2024-10-30 18:13 ` anish kumar 2024-12-05 20:32 ` anish kumar 0 siblings, 1 reply; 12+ messages in thread From: anish kumar @ 2024-10-30 18:13 UTC (permalink / raw) To: Jassi Brar; +Cc: Jonathan Corbet, linux-doc, linux-kernel, Bagas Sanjaya On Wed, Oct 30, 2024 at 10:42 AM Jassi Brar <jassisinghbrar@gmail.com> wrote: > > Hi Anish, > It is the third ping within 10 days, please avoid. Documentation is apologies for this. > not a high priority, esp when it is mostly copying info from header > files. It is true for the api but not true for overall documentation. Reason for writing this document was that I had to read the code to understand how the mailbox driver works. Couple of things this document does is: 1. Explain how the controller, client and hardware are connected 2. Separated out documentation of client, controller and mailbox framework. So, if someone needs to only do a client then they just read that document. 3. Provided example code for controller. 4. In general a better explanation of the framework. > I haven't looked closely and you haven't mentioned in the log what new > info are you adding or clearer? Yes, I should have done that but I added index.rst so thought it is not needed but will do for V2. > From a quick look it seems just api explanation copied into doc > format. Will look closer later. Not completely true. > > Thanks > > On Tue, Oct 29, 2024 at 1:06 PM anish kumar <yesanishhere@gmail.com> wrote: > > > > Hello Jassi, > > > > Gentle reminder for the review. > > > > On Fri, Oct 25, 2024 at 12:24 PM anish kumar <yesanishhere@gmail.com> wrote: > > > > > > Hello Jassi, > > > > > > I hope to get some more comments from you before > > > spinning up a new revision. > > > > > > On Thu, Oct 24, 2024 at 8:38 PM Bagas Sanjaya <bagasdotme@gmail.com> wrote: > > > > > > > > On Sat, Oct 19, 2024 at 12:55:34PM -0700, anish kumar wrote: > > > > > 1. added client documentation > > > > > 2. added controller documentation. > > > > > 3. added framework documentation > > > > > > > > One doc topic on each patch, please. > > > > > > > > > > > > > > Signed-off-by: anish kumar <yesanishhere@gmail.com> > > > > > --- > > > > > Documentation/driver-api/mailbox/client.rst | 192 ++++++++++++++++++ > > > > > Documentation/driver-api/mailbox/core.rst | 182 +++++++++++++++++ > > > > > Documentation/driver-api/mailbox/index.rst | 45 ++++ > > > > > .../writing_mailbox_controller_drivers.rst | 179 ++++++++++++++++ > > > > > 4 files changed, 598 insertions(+) > > > > > create mode 100644 Documentation/driver-api/mailbox/client.rst > > > > > create mode 100644 Documentation/driver-api/mailbox/core.rst > > > > > create mode 100644 Documentation/driver-api/mailbox/index.rst > > > > > create mode 100644 Documentation/driver-api/mailbox/writing_mailbox_controller_drivers.rst > > > > > > > > > > diff --git a/Documentation/driver-api/mailbox/client.rst b/Documentation/driver-api/mailbox/client.rst > > > > > new file mode 100644 > > > > > index 000000000000..9088f8373423 > > > > > --- /dev/null > > > > > +++ b/Documentation/driver-api/mailbox/client.rst > > > > > @@ -0,0 +1,192 @@ > > > > > +Mailbox Client Documentation > > > > > +============================ > > > > > + > > > > > +Overview > > > > > +-------- > > > > > +The mailbox client driver is responsible for sending and receiving messages > > > > > +to and from a remote processor. It uses mailbox APIs provided by the > > > > > +mailbox framework. > > > > > + > > > > > +Mailbox Structure > > > > > +----------------- > > > > > +The mailbox structure is defined as follows: > > > > > + > > > > > +.. code-block:: c > > > > > + > > > > > + struct mbox_client { > > > > > + //device associated with the mailbox > > > > > + struct device *dev; > > > > > + // callback for transmission completion > > > > > + void (*tx_done)(struct mbox_client *client); > > > > > + // callback to prepare for sending a message > > > > > + void (*tx_prepare)(struct mbox_client *client); > > > > > + // callback for received messages > > > > > + void (*rx_callback)(struct mbox_client *client, void *data); > > > > > + // flag to indicate if transmission should block > > > > > + bool tx_block; > > > > > + // indicates if the client knows when transmission is done > > > > > + bool knows_txdone; > > > > > + }; > > > > > + > > > > > +Key Functions > > > > > +------------- > > > > > +1. Requesting a Mailbox Channel > > > > > + - **Function**: `mbox_request_channel(struct mbox_client *client, > > > > > + unsigned int channel)` > > > > > + - **Description**: Requests a mailbox channel for sending messages. > > > > > + - **Parameters**: > > > > > + - `client`: Pointer to the mailbox client structure. > > > > > + - `channel`: The specific mailbox channel to request. > > > > > + - **Returns**: A pointer to the mailbox channel on success, or an error > > > > > + code on failure. > > > > > + > > > > > +2. Sending a Message > > > > > + - **Function**: `mbox_send_message(struct mbox_chan *chan, void *msg)` > > > > > + - **Description**: Sends a message through the mailbox channel. > > > > > + - **Parameters**: > > > > > + - `chan`: The mailbox channel used for communication. > > > > > + - `msg`: Pointer to the message to be sent (usually NULL for dummy > > > > > + messages). > > > > > + - **Returns**: 0 on success, or a negative error code on failure. > > > > > + > > > > > +3. Transmitting Completion > > > > > + - **Function**: `mbox_client_txdone(struct mbox_chan *chan, unsigned int > > > > > + msg_id)` > > > > > + - **Description**: Notifies the mailbox framework that message > > > > > + transmission is complete. > > > > > + - **Parameters**: > > > > > + - `chan`: The mailbox channel associated with the message. > > > > > + - `msg_id`: The identifier of the message that was transmitted. > > > > > > > > These functions should've been documented as kernel-doc comments, though. > > > > > > > > > + > > > > > +Usage Example > > > > > +------------- > > > > > +In a typical mailbox client driver, the following steps are typically > > > > > +performed: > > > > > + > > > > > +1. Initialize the Mailbox Client: > > > > > + > > > > > + .. code-block:: c > > > > > + > > > > > + struct mbox_client my_mbox_client = { > > > > > + .dev = &my_device, > > > > > + .tx_done = my_tx_done_callback, > > > > > + .rx_callback = my_rx_callback, > > > > > + .tx_block = false, > > > > > + .knows_txdone = true, > > > > > + }; > > > > > + > > > > > +2. Request a Mailbox Channel: > > > > > + > > > > > + .. code-block:: c > > > > > + > > > > > + mbox_chan = mbox_request_channel(&my_mbox_client, 0); > > > > > + if (IS_ERR(mbox_chan)) { > > > > > + // Handle error > > > > > + } > > > > > + > > > > > +3. Send a Message: > > > > > + > > > > > + .. code-block:: c > > > > > + > > > > > + int ret = mbox_send_message(mbox_chan, NULL); // Sending a dummy message > > > > > + if (ret < 0) { > > > > > + // Handle error > > > > > + } > > > > > + > > > > > +4. Complete Transmission: > > > > > + > > > > > + .. code-block:: c > > > > > + > > > > > + mbox_client_txdone(mbox_chan, 0); > > > > > + > > > > > +Interrupt Handling > > > > > +------------------ > > > > > +The mailbox interface can trigger interrupts upon message receipt. Handlers > > > > > +should be implemented in the `rx_callback` function defined in the mailbox > > > > > +client structure to process incoming messages. > > > > > + > > > > > +Example Mailbox Client Driver > > > > > +----------------------------- > > > > > +.. code-block:: c > > > > > + > > > > > + struct demo_client { > > > > > + struct mbox_client cl; > > > > > + struct mbox_chan *mbox; > > > > > + struct completion c; > > > > > + bool async; > > > > > + /* ... */ > > > > > + }; > > > > > + > > > > > + /* > > > > > + * This is the handler for data received from remote. The behaviour is purely > > > > > + * dependent upon the protocol. This is just an example. > > > > > + */ > > > > > + static void message_from_remote(struct mbox_client *cl, void *mssg) > > > > > + { > > > > > + struct demo_client *dc = container_of(cl, struct demo_client, cl); > > > > > + if (dc->async) { > > > > > + if (is_an_ack(mssg)) { > > > > > + /* An ACK to our last sample sent */ > > > > > + return; /* Or do something else here */ > > > > > + } else { /* A new message from remote */ > > > > > + queue_req(mssg); > > > > > + } > > > > > + } else { > > > > > + /* Remote f/w sends only ACK packets on this channel */ > > > > > + return; > > > > > + } > > > > > + } > > > > > + > > > > > + static void sample_sent(struct mbox_client *cl, void *mssg, int r) > > > > > + { > > > > > + struct demo_client *dc = container_of(cl, struct demo_client, cl); > > > > > + complete(&dc->c); > > > > > + } > > > > > + > > > > > + static void client_demo(struct platform_device *pdev) > > > > > + { > > > > > + struct demo_client *dc_sync, *dc_async; > > > > > + /* The controller already knows async_pkt and sync_pkt */ > > > > > + struct async_pkt ap; > > > > > + struct sync_pkt sp; > > > > > + > > > > > + dc_sync = kzalloc(sizeof(*dc_sync), GFP_KERNEL); > > > > > + dc_async = kzalloc(sizeof(*dc_async), GFP_KERNEL); > > > > > + > > > > > + /* Populate non-blocking mode client */ > > > > > + dc_async->cl.dev = &pdev->dev; > > > > > + dc_async->cl.rx_callback = message_from_remote; > > > > > + dc_async->cl.tx_done = sample_sent; > > > > > + dc_async->cl.tx_block = false; > > > > > + dc_async->cl.tx_tout = 0; /* doesn't matter here */ > > > > > + dc_async->cl.knows_txdone = false; /* depending upon protocol */ > > > > > + dc_async->async = true; > > > > > + init_completion(&dc_async->c); > > > > > + > > > > > + /* Populate blocking mode client */ > > > > > + dc_sync->cl.dev = &pdev->dev; > > > > > + dc_sync->cl.rx_callback = message_from_remote; > > > > > + dc_sync->cl.tx_done = NULL; /* operate in blocking mode */ > > > > > + dc_sync->cl.tx_block = true; > > > > > + dc_sync->cl.tx_tout = 500; /* by half a second */ > > > > > + dc_sync->cl.knows_txdone = false; /* depending upon protocol */ > > > > > + dc_sync->async = false; > > > > > + > > > > > + /* ASync mailbox is listed second in 'mboxes' property */ > > > > > + dc_async->mbox = mbox_request_channel(&dc_async->cl, 1); > > > > > + /* Populate data packet */ > > > > > + /* ap.xxx = 123; etc */ > > > > > + /* Send async message to remote */ > > > > > + mbox_send_message(dc_async->mbox, &ap); > > > > > + > > > > > + /* Sync mailbox is listed first in 'mboxes' property */ > > > > > + dc_sync->mbox = mbox_request_channel(&dc_sync->cl, 0); > > > > > + /* Populate data packet */ > > > > > + /* sp.abc = 123; etc */ > > > > > + /* Send message to remote in blocking mode */ > > > > > + mbox_send_message(dc_sync->mbox, &sp); > > > > > + /* At this point 'sp' has been sent */ > > > > > + > > > > > + /* Now wait for async chan to be done */ > > > > > + wait_for_completion(&dc_async->c); > > > > > + } > > > > > diff --git a/Documentation/driver-api/mailbox/core.rst b/Documentation/driver-api/mailbox/core.rst > > > > > new file mode 100644 > > > > > index 000000000000..d1220086da67 > > > > > --- /dev/null > > > > > +++ b/Documentation/driver-api/mailbox/core.rst > > > > > @@ -0,0 +1,182 @@ > > > > > +===================== > > > > > +mailbox documentation > > > > > +===================== > > > > > + > > > > > +Hardware Introduction > > > > > +===================== > > > > > + > > > > > +Mailbox hardware is a specialized component found in multi-core > > > > > +processors and embedded systems that facilitates inter-processor > > > > > +communication (IPC) or communication between different hardware > > > > > +components. It provides a structured mechanism for sending and > > > > > +receiving messages, allowing various processors or devices to > > > > > +exchange data efficiently. Here's an overview of its key > > > > > +characteristics and functions: > > > > > + > > > > > +Key Characteristics of Mailbox Hardware > > > > > +Interrupt Handling: Many mailbox implementations support > > > > > +interrupt-driven communication. This allows a receiving processor > > > > > +to be alerted when a new message arrives, facilitating immediate > > > > > +processing without polling the mailbox constantly. > > > > > + > > > > > +Hardware Registers: Mailbox hardware often includes registers for > > > > > +configuration and status monitoring. These registers can be used > > > > > +to control the mailbox's behavior, check for available messages, > > > > > +or acknowledge message receipt. > > > > > + > > > > > +Support for Multiple Protocols: Mailboxes can support various > > > > > +communication protocols, enabling interoperability between different > > > > > +hardware components and simplifying the integration of diverse systems. > > > > > + > > > > > +Synchronous and Asynchronous Modes: Mailbox hardware can operate in > > > > > +both synchronous and asynchronous modes. In synchronous mode, the > > > > > +sender may wait for the receiver to acknowledge receipt before > > > > > +proceeding, while in asynchronous mode, the sender can continue > > > > > +executing other tasks immediately after sending the message. > > > > > + > > > > > + > > > > > +Mailbox framework design > > > > > +======================== > > > > > + > > > > > +The mailbox facilitates interprocessor communication by allowing processors to > > > > > +exchange messages or signals. The mailbox framework consists of: > > > > > + > > > > > +Mailbox Controller: This is platform-specific and is responsible for configuring > > > > > +and managing interrupts from the remote processor. It offers a generic API for > > > > > +the mailbox client. > > > > > + > > > > > +Mailbox Client: This component handles the sending and receiving of messages. > > > > > + > > > > > + > > > > > +............................................................................ > > > > > +: client driver client_a client_b : > > > > > +............................................................................ > > > > > + ^-------------------^ > > > > > + | > > > > > + | > > > > > +............................................................................ > > > > > +: controller framework mailbox : > > > > > +....................................|....................................... > > > > > + | > > > > > + | > > > > > +............................................................................ > > > > > +: controller driver device specific : > > > > > +....................................|....................................... > > > > > + | > > > > > + | > > > > > +kernel | > > > > > +............................................................................ > > > > > +hardware | > > > > > + | > > > > > + | > > > > > +............................................................................ > > > > > +: remote processor : > > > > > +............................................................................ > > > > > > > > htmldocs build errors out: > > > > > > > > Documentation/driver-api/mailbox/core.rst:57: WARNING: Block quote ends without a blank line; unexpected unindent. > > > > Documentation/driver-api/mailbox/core.rst:57: CRITICAL: Missing matching underline for section title overline. > > > > > > > > ............................................................................ > > > > : controller framework mailbox : > > > > ....................................|....................................... > > > > > > > > reST markup error: > > > > Documentation/driver-api/mailbox/core.rst:57: (SEVERE/4) Missing matching underline for section title overline. > > > > > > > > ............................................................................ > > > > : controller framework mailbox : > > > > ....................................|....................................... > > > > > > > > I have to fix up the design diagram and wrap it: > > > > > > > > ---- >8 ---- > > > > diff --git a/Documentation/driver-api/mailbox/core.rst b/Documentation/driver-api/mailbox/core.rst > > > > index d1220086da679f..8d56d81007c11c 100644 > > > > --- a/Documentation/driver-api/mailbox/core.rst > > > > +++ b/Documentation/driver-api/mailbox/core.rst > > > > @@ -47,31 +47,32 @@ the mailbox client. > > > > > > > > Mailbox Client: This component handles the sending and receiving of messages. > > > > > > > > +:: > > > > > > > > -............................................................................ > > > > -: client driver client_a client_b : > > > > -............................................................................ > > > > - ^-------------------^ > > > > - | > > > > - | > > > > -............................................................................ > > > > -: controller framework mailbox : > > > > -....................................|....................................... > > > > - | > > > > - | > > > > -............................................................................ > > > > -: controller driver device specific : > > > > -....................................|....................................... > > > > - | > > > > - | > > > > -kernel | > > > > -............................................................................ > > > > -hardware | > > > > - | > > > > - | > > > > -............................................................................ > > > > -: remote processor : > > > > -............................................................................ > > > > + +---------------------------------------------------------------------------+ > > > > + | client driver client_a client_b | > > > > + +---------------------------------------------------------------------------+ > > > > + ^-------------------^ > > > > + | > > > > + | > > > > + +--------------------------------------------------------------------------+ > > > > + | controller framework mailbox | > > > > + +-----------------------------------|--------------------------------------+ > > > > + | > > > > + | > > > > + +--------------------------------------------------------------------------+ > > > > + | controller driver device specific | > > > > + +-----------------------------------|--------------------------------------+ > > > > + | > > > > + | > > > > + kernel | > > > > + ---------------------------------------------------------------------------- > > > > + hardware | > > > > + | > > > > + | > > > > + +--------------------------------------------------------------------------+ > > > > + | remote processor | > > > > + +--------------------------------------------------------------------------+ > > > > > > > > > > > > In the context of a mailbox framework, a channel refers to a dedicated > > > > > > > > > + > > > > > + > > > > > +In the context of a mailbox framework, a channel refers to a dedicated > > > > > +communication pathway between two or more processors or components. By using > > > > > +channels, the framework abstracts the complexity of interprocessor communication. > > > > > + > > > > > +Data Structures > > > > > +================ > > > > > + > > > > > +- **struct mbox_client** > > > > > + This structure represents a client that communicates over a mailbox > > > > > + channel. It holds information such as: > > > > > + - A pointer to the device associated with the client (`dev`). > > > > > + - Callback functions for handling message transmission events, including: > > > > > + - `rx_callback`: Called when a message is received. > > > > > + - `tx_done`: Called when a message transmission is acknowledged. > > > > > + - Flags that specify the client’s configuration, such as whether it operates > > > > > + in blocking mode. > > > > > + > > > > > +- **struct mbox_chan** > > > > > + This structure represents an individual mailbox channel. It maintains the > > > > > + state required for message queuing and transmission. Key members include: > > > > > + - `msg_data`: Array of messages queued for transmission. > > > > > + - `msg_count`: Number of messages currently queued. > > > > > + - `msg_free`: Index of the next free slot in the message queue. > > > > > + - `active_req`: Pointer to the currently active message being transmitted. > > > > > + - Synchronization primitives to manage access from multiple contexts. > > > > > + > > > > > +- **struct mbox_controller** > > > > > + This structure represents a mailbox controller that manages multiple > > > > > + channels. It includes: > > > > > + - A pointer to the device managing the mailbox. > > > > > + - Operations for sending and receiving messages, as well as initializing > > > > > + and shutting down the mailbox. > > > > > + - A list of associated channels and the total number of channels available. > > > > > > > > Shouldn't these structs be documented as kernel-doc comments? tl;dr: > > > > see Documentation/doc-guide/kernel-doc.html > > > > > > > > > + > > > > > +controller framework APIs > > > > > +========================= > > > > > + > > > > > +``struct `mbox_controller` Initialization > > > > > +----------------------------------------- > > > > > > > > Properly double-backquote the struct name to format it as inline code: > > > > > > > > ---- >8 ---- > > > > diff --git a/Documentation/driver-api/mailbox/core.rst b/Documentation/driver-api/mailbox/core.rst > > > > index 239538f497e41a..d83456164464aa 100644 > > > > --- a/Documentation/driver-api/mailbox/core.rst > > > > +++ b/Documentation/driver-api/mailbox/core.rst > > > > @@ -117,7 +117,7 @@ Data Structures > > > > controller framework APIs > > > > ========================= > > > > > > > > -``struct `mbox_controller` Initialization > > > > +``struct mbox_controller`` Initialization > > > > ----------------------------------------- > > > > > > > > Just like any other kernel framework, the whole mailbox controller registration > > > > > > > > > + > > > > > +Just like any other kernel framework, the whole mailbox controller registration > > > > > +relies on the driver filling a structure and registering against the > > > > > +framework. In our case, that structure is mbox_controller. > > > > > + > > > > > +The first thing you need to do in your driver is to allocate this > > > > > +structure. Any of the usual memory allocators will do, but you'll also > > > > > +need to initialize a few fields in there: > > > > > + > > > > > +- ``dev``: should hold the pointer to the ``struct device`` associated > > > > > + to your current driver instance. > > > > > + > > > > > +- ``ops``: Operators that work on each communication channel. > > > > > + > > > > > +- ``chans``: Array of channels. > > > > > + > > > > > +- ``num_chans``: Number of channels in the `chans` array. > > > > > + > > > > > +- ``txdone_irq``: Indicates if the controller can report to the API > > > > > + when the last transmitted data was read by the > > > > > + remote (e.g., if it has a TX ACK interrupt). > > > > > + > > > > > +All the below fields are not mandatory. > > > > > + > > > > > +- ``txdone_poll``: Indicates if the controller can read but not report > > > > > + the TX done. For example, some register may show > > > > > + the TX status, but no interrupt is raised. This > > > > > + field is ignored if `txdone_irq` is set. > > > > > + > > > > > +- ``txpoll_period``: If `txdone_poll` is in effect, the API polls for > > > > > + the last TX status after this many milliseconds. > > > > > + > > > > > +- ``of_xlate``: Controller driver-specific mapping of channel via > > > > > + Device Tree (DT). > > > > > + > > > > > + > > > > > +Key Functions > > > > > +------------- > > > > > + > > > > > +- **int devm_mbox_controller_register(struct mbox_controller *mbox)** > > > > > + This function registers a mailbox controller with the kernel. It makes the > > > > > + channels associated with the controller available for client requests. The > > > > > + function performs sanity checks on the controller structure to ensure all > > > > > + necessary fields are populated. > > > > > + > > > > > +- **struct mbox_chan *mbox_request_channel(struct mbox_client *cl, int index)** > > > > > + This function requests a mailbox channel for a specified client, identified > > > > > + by an index. It searches for the appropriate mailbox channel, and if found, > > > > > + it returns a pointer to the channel. If the request fails (e.g., if the > > > > > + index is invalid), it returns an error pointer. > > > > > + > > > > > +- **void mbox_free_channel(struct mbox_chan *chan)** > > > > > + This function releases a mailbox channel that was previously allocated for a > > > > > + client. It ensures that the channel can be reused by other clients. If any > > > > > + messages are still in the queue, they are aborted, and no callbacks are made. > > > > > + > > > > > +- **int mbox_send_message(struct mbox_chan *chan, void *mssg)** > > > > > + This function is used by clients to send a message through the specified > > > > > + mailbox channel. The function can operate in either blocking or non-blocking > > > > > + mode, depending on the client’s configuration. It will queue the message for > > > > > + transmission and notify the client once the message is acknowledged. > > > > > + > > > > > +- **void mbox_chan_received_data(struct mbox_chan *chan, void *mssg)** > > > > > + This function is called by the controller driver to notify the mailbox > > > > > + framework that a message has been received on the specified channel. The > > > > > + received message is then passed to the appropriate client's `rx_callback` > > > > > + function for processing. > > > > > > > > Shouldn't these functions also be documented as kernel-doc comments? > > > > > > > > > diff --git a/Documentation/driver-api/mailbox/index.rst b/Documentation/driver-api/mailbox/index.rst > > > > > new file mode 100644 > > > > > index 000000000000..e254a8fdb66a > > > > > --- /dev/null > > > > > +++ b/Documentation/driver-api/mailbox/index.rst > > > > > @@ -0,0 +1,45 @@ > > > > > +======================= > > > > > +Mailbox documentation > > > > > +======================= > > > > > + > > > > > +Mailbox documentation provides documents for various aspects of mailbox > > > > > +framework. > > > > > + > > > > > +Mailbox development documentation > > > > > +--------------------------------- > > > > > + > > > > > +This book helps with mailbox internal APIs and guide for mailbox device > > > > > +driver writers. > > > > > + > > > > > +.. toctree:: > > > > > + :maxdepth: 1 > > > > > + > > > > > + core > > > > > + > > > > > +mailbox controller driver documentation > > > > > +------------------------------ > > > > > + > > > > > +This book is a guide to device driver writers on how to register > > > > > +mailbox controller to the mailbox framework. > > > > > + > > > > > +.. toctree:: > > > > > + :maxdepth: 1 > > > > > + > > > > > + writing_mailbox_controller_drivers > > > > > + > > > > > +mailbox client driver documentation > > > > > +------------------------------ > > > > > > > > Match up section underline length by its title: > > > > > > > > ---- >8 ---- > > > > diff --git a/Documentation/driver-api/mailbox/index.rst b/Documentation/driver-api/mailbox/index.rst > > > > index e254a8fdb66ac7..02d7d5e8660999 100644 > > > > --- a/Documentation/driver-api/mailbox/index.rst > > > > +++ b/Documentation/driver-api/mailbox/index.rst > > > > @@ -1,6 +1,6 @@ > > > > -======================= > > > > +===================== > > > > Mailbox documentation > > > > -======================= > > > > +===================== > > > > > > > > Mailbox documentation provides documents for various aspects of mailbox > > > > framework. > > > > @@ -17,7 +17,7 @@ driver writers. > > > > core > > > > > > > > mailbox controller driver documentation > > > > ------------------------------- > > > > +--------------------------------------- > > > > > > > > This book is a guide to device driver writers on how to register > > > > mailbox controller to the mailbox framework. > > > > @@ -28,7 +28,7 @@ mailbox controller to the mailbox framework. > > > > writing_mailbox_controller_drivers > > > > > > > > mailbox client driver documentation > > > > ------------------------------- > > > > +----------------------------------- > > > > > > > > This book is a guide to mailbox client driver writers. > > > > > > > > > > > > > + > > > > > +This book is a guide to mailbox client driver writers. > > > > > + > > > > > +.. toctree:: > > > > > + :maxdepth: 1 > > > > > + > > > > > + client > > > > > + > > > > > +.. only:: subproject and html > > > > > + > > > > > + Indices > > > > > + ======= > > > > > + > > > > > + * :ref:`genindex` > > > > > > > > Fix up also the reference link on parent toctree: > > > > > > > > ---- >8 ---- > > > > diff --git a/Documentation/driver-api/index.rst b/Documentation/driver-api/index.rst > > > > index 7f83e05769b4a4..b4d78b92fd921a 100644 > > > > --- a/Documentation/driver-api/index.rst > > > > +++ b/Documentation/driver-api/index.rst > > > > @@ -102,7 +102,7 @@ Subsystem-specific APIs > > > > ipmb > > > > ipmi > > > > libata > > > > - mailbox > > > > + mailbox/index > > > > md/index > > > > media/index > > > > mei/index > > > > > > > > > diff --git a/Documentation/driver-api/mailbox/writing_mailbox_controller_drivers.rst b/Documentation/driver-api/mailbox/writing_mailbox_controller_drivers.rst > > > > > new file mode 100644 > > > > > index 000000000000..2a82645c1357 > > > > > --- /dev/null > > > > > +++ b/Documentation/driver-api/mailbox/writing_mailbox_controller_drivers.rst > > > > > @@ -0,0 +1,179 @@ > > > > > +.. SPDX-License-Identifier: GPL-2.0 > > > > > + > > > > > +.. _writing_mailbox_controller_drivers: > > > > > + > > > > > +================================== > > > > > +Writing Mailbox Controller Drivers > > > > > +================================== > > > > > + > > > > > +Introduction > > > > > +============ > > > > > + > > > > > +This document serves as a basic guideline for driver programmers that need > > > > > +to hack a new mailbox controller driver or understand the essentials of > > > > > +the existing ones. > > > > > + > > > > > +Driver Boilerplate > > > > > +================== > > > > > + > > > > > +As a bare minimum, a mailbox controller driver needs to call > > > > > +``mbox_controller_register`` function to register with the framework. > > > > > + > > > > > +A basic driver skeleton could look like this for a mailbox hardware that > > > > > +has the following characteristics: > > > > > +a. It supports only a single channel, i.e., only the remote processor can > > > > > + send interrupts. > > > > > +b. Data transfer is over the registers associated with mailbox hardware. > > > > > +c. Mailbox hardware is configured to receive interrupts. > > > > > +d. When the remote processor is ready to send data, it triggers a mailbox > > > > > + interrupt. > > > > > +e. As part of interrupt handling by Linux, it copies data from the registers. > > > > > + > > > > > +.. code-block:: c > > > > > + > > > > > + #include <linux/device.h> > > > > > + #include <linux/interrupt.h> > > > > > + #include <linux/io.h> > > > > > + #include <linux/kernel.h> > > > > > + #include <linux/mailbox_controller.h> > > > > > + #include <linux/module.h> > > > > > + #include <linux/of.h> > > > > > + #include <linux/platform_device.h> > > > > > + #define DRIVER_NAME "dummy_controller" > > > > > + > > > > > + struct dummy_mbox { > > > > > + struct device *dev; > > > > > + struct mbox_controller controller; > > > > > + int irq; > > > > > + }; > > > > > + > > > > > + static void dummy_mbox_receive(struct mbox_chan *chan) > > > > > + { > > > > > + struct dummy_mbox *mbox = chan->con_priv; > > > > > + int val; > > > > > + > > > > > + // Data copied from registers > > > > > + val = read_register(); > > > > > + mbox_chan_received_data(chan, &val); > > > > > + } > > > > > + > > > > > + static irqreturn_t dummy_mbox_irq_handler(int irq, void *data) > > > > > + { > > > > > + struct mbox_chan *chan = data; > > > > > + struct dummy_mbox *mbox = chan->con_priv; > > > > > + u32 reg; > > > > > + > > > > > + // Read registers to see if data is received > > > > > + dummy_mbox_receive(chan); > > > > > + mbox_chan_txdone(chan, 0); > > > > > + return reg ? IRQ_HANDLED : IRQ_NONE; > > > > > + } > > > > > + > > > > > + static int dummy_mbox_send_data(struct mbox_chan *chan, void *data) > > > > > + { > > > > > + // Write data in registers to send it to the remote processor > > > > > + return 0; > > > > > + } > > > > > + > > > > > + static int dummy_mbox_startup(struct mbox_chan *chan) > > > > > + { > > > > > + struct dummy_mbox *mbox = chan->con_priv; > > > > > + u32 reg; > > > > > + int ret; > > > > > + > > > > > + ret = devm_request_irq(mbox->dev, mbox->irq, dummy_mbox_irq_handler, 0, > > > > > + DRIVER_NAME, chan); > > > > > + if (ret < 0) { > > > > > + dev_err(mbox->dev, "Cannot request irq\n"); > > > > > + return ret; > > > > > + } > > > > > + > > > > > + /* Register write to enable IRQ generation */ > > > > > + > > > > > + return 0; > > > > > + } > > > > > + > > > > > + static void dummy_mbox_shutdown(struct mbox_chan *chan) > > > > > + { > > > > > + struct dummy_mbox *mbox = chan->con_priv; > > > > > + > > > > > + /* Disable interrupt generation */ > > > > > + devm_free_irq(mbox->dev, mbox->irq, chan); > > > > > + } > > > > > + > > > > > + static const struct mbox_chan_ops dummy_mbox_ops = { > > > > > + .send_data = dummy_mbox_send_data, > > > > > + .startup = dummy_mbox_startup, > > > > > + .shutdown = dummy_mbox_shutdown, > > > > > + }; > > > > > + > > > > > + static int dummy_mbox_probe(struct platform_device *pdev) > > > > > + { > > > > > + struct dummy_mbox *mbox; > > > > > + struct mbox_chan *chans; > > > > > + int ret; > > > > > + > > > > > + mbox = devm_kzalloc(&pdev->dev, sizeof(*mbox), GFP_KERNEL); > > > > > + if (!mbox) > > > > > + return -ENOMEM; > > > > > + > > > > > + /* Allocate one channel */ > > > > > + chans = devm_kzalloc(&pdev->dev, sizeof(*chans), GFP_KERNEL); > > > > > + if (!chans) > > > > > + return -ENOMEM; > > > > > + > > > > > + mbox->base = devm_platform_ioremap_resource(pdev, 0); > > > > > + if (IS_ERR(mbox->base)) > > > > > + return PTR_ERR(mbox->base); > > > > > + > > > > > + mbox->irq = platform_get_irq(pdev, 0); > > > > > + if (mbox->irq < 0) > > > > > + return mbox->irq; > > > > > + > > > > > + mbox->dev = &pdev->dev; > > > > > + > > > > > + /* Hardware supports only one channel. */ > > > > > + mbox->controller.dev = mbox->dev; > > > > > + mbox->controller.num_chans = 1; > > > > > + mbox->controller.chans = chans; > > > > > + mbox->controller.ops = &dummy_mbox_ops; > > > > > + mbox->controller.txdone_irq = true; > > > > > + > > > > > + ret = devm_mbox_controller_register(mbox->dev, &mbox->controller); > > > > > + if (ret) { > > > > > + dev_err(&pdev->dev, "Could not register mailbox controller\n"); > > > > > + return ret; > > > > > + } > > > > > + > > > > > + return ret; > > > > > + } > > > > > + > > > > > + static const struct of_device_id dummy_mbox_match[] = { > > > > > + { .compatible = "dummy,dummy-mailbox" }, > > > > > + { }, > > > > > + }; > > > > > + > > > > > + MODULE_DEVICE_TABLE(of, dummy_mbox_match); > > > > > + > > > > > + static struct platform_driver dummy_mbox_driver = { > > > > > + .probe = dummy_mbox_probe, > > > > > + .driver = { > > > > > + .name = DRIVER_NAME, > > > > > + .of_match_table = dummy_mbox_match, > > > > > + }, > > > > > + }; > > > > > + > > > > > + module_platform_driver(dummy_mbox_driver); > > > > > + MODULE_LICENSE("GPL v2"); > > > > > + MODULE_DESCRIPTION("Dummy mailbox controller driver"); > > > > > + > > > > > +In the above code, a couple of things are done: > > > > > +a. The controller is registered in the probe along with callbacks, which in > > > > > + this case are the bare minimum: ``startup``, ``shutdown``, and > > > > > + ``send_data``. > > > > > +b. IRQ is registered to get notifications from the remote processor. > > > > > +c. In the IRQ handler, registers are read to copy data, and > > > > > + ``mbox_chan_received_data`` is called to hand over the data to the client. > > > > > +d. ``mbox_chan_txdone`` is called to let the framework know that this data > > > > > + is the last data and no more data is to be expected for the current transfer. > > > > > + > > > > > > > > Sphinx warns out numerous indentation warnings on the lists, so I have to > > > > fix them up: > > > > > > > > ---- >8 ---- > > > > diff --git a/Documentation/driver-api/mailbox/client.rst b/Documentation/driver-api/mailbox/client.rst > > > > index 9088f83734230d..17dafaca056777 100644 > > > > --- a/Documentation/driver-api/mailbox/client.rst > > > > +++ b/Documentation/driver-api/mailbox/client.rst > > > > @@ -31,6 +31,7 @@ The mailbox structure is defined as follows: > > > > Key Functions > > > > ------------- > > > > 1. Requesting a Mailbox Channel > > > > + > > > > - **Function**: `mbox_request_channel(struct mbox_client *client, > > > > unsigned int channel)` > > > > - **Description**: Requests a mailbox channel for sending messages. > > > > @@ -41,15 +42,19 @@ Key Functions > > > > code on failure. > > > > > > > > 2. Sending a Message > > > > + > > > > - **Function**: `mbox_send_message(struct mbox_chan *chan, void *msg)` > > > > - **Description**: Sends a message through the mailbox channel. > > > > - **Parameters**: > > > > + > > > > - `chan`: The mailbox channel used for communication. > > > > - `msg`: Pointer to the message to be sent (usually NULL for dummy > > > > messages). > > > > + > > > > - **Returns**: 0 on success, or a negative error code on failure. > > > > > > > > 3. Transmitting Completion > > > > + > > > > - **Function**: `mbox_client_txdone(struct mbox_chan *chan, unsigned int > > > > msg_id)` > > > > - **Description**: Notifies the mailbox framework that message > > > > diff --git a/Documentation/driver-api/mailbox/core.rst b/Documentation/driver-api/mailbox/core.rst > > > > index 8d56d81007c11c..239538f497e41a 100644 > > > > --- a/Documentation/driver-api/mailbox/core.rst > > > > +++ b/Documentation/driver-api/mailbox/core.rst > > > > @@ -85,16 +85,20 @@ Data Structures > > > > - **struct mbox_client** > > > > This structure represents a client that communicates over a mailbox > > > > channel. It holds information such as: > > > > + > > > > - A pointer to the device associated with the client (`dev`). > > > > - Callback functions for handling message transmission events, including: > > > > + > > > > - `rx_callback`: Called when a message is received. > > > > - `tx_done`: Called when a message transmission is acknowledged. > > > > + > > > > - Flags that specify the client’s configuration, such as whether it operates > > > > in blocking mode. > > > > > > > > - **struct mbox_chan** > > > > This structure represents an individual mailbox channel. It maintains the > > > > state required for message queuing and transmission. Key members include: > > > > + > > > > - `msg_data`: Array of messages queued for transmission. > > > > - `msg_count`: Number of messages currently queued. > > > > - `msg_free`: Index of the next free slot in the message queue. > > > > @@ -104,6 +108,7 @@ Data Structures > > > > - **struct mbox_controller** > > > > This structure represents a mailbox controller that manages multiple > > > > channels. It includes: > > > > + > > > > - A pointer to the device managing the mailbox. > > > > - Operations for sending and receiving messages, as well as initializing > > > > and shutting down the mailbox. > > > > @@ -133,21 +138,20 @@ need to initialize a few fields in there: > > > > - ``num_chans``: Number of channels in the `chans` array. > > > > > > > > - ``txdone_irq``: Indicates if the controller can report to the API > > > > - when the last transmitted data was read by the > > > > - remote (e.g., if it has a TX ACK interrupt). > > > > + when the last transmitted data was read by the remote (e.g., if it has a > > > > + TX ACK interrupt). > > > > > > > > All the below fields are not mandatory. > > > > > > > > - ``txdone_poll``: Indicates if the controller can read but not report > > > > - the TX done. For example, some register may show > > > > - the TX status, but no interrupt is raised. This > > > > - field is ignored if `txdone_irq` is set. > > > > + the TX done. For example, some register may show the TX status, but no > > > > + interrupt is raised. This field is ignored if `txdone_irq` is set. > > > > > > > > - ``txpoll_period``: If `txdone_poll` is in effect, the API polls for > > > > - the last TX status after this many milliseconds. > > > > + the last TX status after this many milliseconds. > > > > > > > > - ``of_xlate``: Controller driver-specific mapping of channel via > > > > - Device Tree (DT). > > > > + Device Tree (DT). > > > > > > > > > > > > Key Functions > > > > diff --git a/Documentation/driver-api/mailbox/writing_mailbox_controller_drivers.rst b/Documentation/driver-api/mailbox/writing_mailbox_controller_drivers.rst > > > > index 2a82645c13573e..853adf6918173d 100644 > > > > --- a/Documentation/driver-api/mailbox/writing_mailbox_controller_drivers.rst > > > > +++ b/Documentation/driver-api/mailbox/writing_mailbox_controller_drivers.rst > > > > @@ -21,6 +21,7 @@ As a bare minimum, a mailbox controller driver needs to call > > > > > > > > A basic driver skeleton could look like this for a mailbox hardware that > > > > has the following characteristics: > > > > + > > > > a. It supports only a single channel, i.e., only the remote processor can > > > > send interrupts. > > > > b. Data transfer is over the registers associated with mailbox hardware. > > > > @@ -168,6 +169,7 @@ e. As part of interrupt handling by Linux, it copies data from the registers. > > > > MODULE_DESCRIPTION("Dummy mailbox controller driver"); > > > > > > > > In the above code, a couple of things are done: > > > > + > > > > a. The controller is registered in the probe along with callbacks, which in > > > > this case are the bare minimum: ``startup``, ``shutdown``, and > > > > ``send_data``. > > > > > > > > Thanks. > > > > > > > > -- > > > > An old man doll... just what I always wanted! - Clara ^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH 2/2] mailbox: Documentation: add the latest documentation 2024-10-30 18:13 ` anish kumar @ 2024-12-05 20:32 ` anish kumar 0 siblings, 0 replies; 12+ messages in thread From: anish kumar @ 2024-12-05 20:32 UTC (permalink / raw) To: Jassi Brar; +Cc: Jonathan Corbet, linux-doc, linux-kernel, Bagas Sanjaya Hello Jassi, Wondering if I can remind you now for reviewing? On Wed, Oct 30, 2024 at 11:13 AM anish kumar <yesanishhere@gmail.com> wrote: > > On Wed, Oct 30, 2024 at 10:42 AM Jassi Brar <jassisinghbrar@gmail.com> wrote: > > > > Hi Anish, > > It is the third ping within 10 days, please avoid. Documentation is > > apologies for this. > > > not a high priority, esp when it is mostly copying info from header > > files. > > It is true for the api but not true for overall documentation. > Reason for writing this document was that I had to read the code > to understand how the mailbox driver works. Couple of things > this document does is: > 1. Explain how the controller, client and hardware are connected > 2. Separated out documentation of client, controller and mailbox > framework. So, if someone needs to only do a client then they just > read that document. > 3. Provided example code for controller. > 4. In general a better explanation of the framework. > > > I haven't looked closely and you haven't mentioned in the log what new > > info are you adding or clearer? > > Yes, I should have done that but I added index.rst so thought > it is not needed but will do for V2. > > > From a quick look it seems just api explanation copied into doc > > format. Will look closer later. > > Not completely true. > > > > Thanks > > > > On Tue, Oct 29, 2024 at 1:06 PM anish kumar <yesanishhere@gmail.com> wrote: > > > > > > Hello Jassi, > > > > > > Gentle reminder for the review. > > > > > > On Fri, Oct 25, 2024 at 12:24 PM anish kumar <yesanishhere@gmail.com> wrote: > > > > > > > > Hello Jassi, > > > > > > > > I hope to get some more comments from you before > > > > spinning up a new revision. > > > > > > > > On Thu, Oct 24, 2024 at 8:38 PM Bagas Sanjaya <bagasdotme@gmail.com> wrote: > > > > > > > > > > On Sat, Oct 19, 2024 at 12:55:34PM -0700, anish kumar wrote: > > > > > > 1. added client documentation > > > > > > 2. added controller documentation. > > > > > > 3. added framework documentation > > > > > > > > > > One doc topic on each patch, please. > > > > > > > > > > > > > > > > > Signed-off-by: anish kumar <yesanishhere@gmail.com> > > > > > > --- > > > > > > Documentation/driver-api/mailbox/client.rst | 192 ++++++++++++++++++ > > > > > > Documentation/driver-api/mailbox/core.rst | 182 +++++++++++++++++ > > > > > > Documentation/driver-api/mailbox/index.rst | 45 ++++ > > > > > > .../writing_mailbox_controller_drivers.rst | 179 ++++++++++++++++ > > > > > > 4 files changed, 598 insertions(+) > > > > > > create mode 100644 Documentation/driver-api/mailbox/client.rst > > > > > > create mode 100644 Documentation/driver-api/mailbox/core.rst > > > > > > create mode 100644 Documentation/driver-api/mailbox/index.rst > > > > > > create mode 100644 Documentation/driver-api/mailbox/writing_mailbox_controller_drivers.rst > > > > > > > > > > > > diff --git a/Documentation/driver-api/mailbox/client.rst b/Documentation/driver-api/mailbox/client.rst > > > > > > new file mode 100644 > > > > > > index 000000000000..9088f8373423 > > > > > > --- /dev/null > > > > > > +++ b/Documentation/driver-api/mailbox/client.rst > > > > > > @@ -0,0 +1,192 @@ > > > > > > +Mailbox Client Documentation > > > > > > +============================ > > > > > > + > > > > > > +Overview > > > > > > +-------- > > > > > > +The mailbox client driver is responsible for sending and receiving messages > > > > > > +to and from a remote processor. It uses mailbox APIs provided by the > > > > > > +mailbox framework. > > > > > > + > > > > > > +Mailbox Structure > > > > > > +----------------- > > > > > > +The mailbox structure is defined as follows: > > > > > > + > > > > > > +.. code-block:: c > > > > > > + > > > > > > + struct mbox_client { > > > > > > + //device associated with the mailbox > > > > > > + struct device *dev; > > > > > > + // callback for transmission completion > > > > > > + void (*tx_done)(struct mbox_client *client); > > > > > > + // callback to prepare for sending a message > > > > > > + void (*tx_prepare)(struct mbox_client *client); > > > > > > + // callback for received messages > > > > > > + void (*rx_callback)(struct mbox_client *client, void *data); > > > > > > + // flag to indicate if transmission should block > > > > > > + bool tx_block; > > > > > > + // indicates if the client knows when transmission is done > > > > > > + bool knows_txdone; > > > > > > + }; > > > > > > + > > > > > > +Key Functions > > > > > > +------------- > > > > > > +1. Requesting a Mailbox Channel > > > > > > + - **Function**: `mbox_request_channel(struct mbox_client *client, > > > > > > + unsigned int channel)` > > > > > > + - **Description**: Requests a mailbox channel for sending messages. > > > > > > + - **Parameters**: > > > > > > + - `client`: Pointer to the mailbox client structure. > > > > > > + - `channel`: The specific mailbox channel to request. > > > > > > + - **Returns**: A pointer to the mailbox channel on success, or an error > > > > > > + code on failure. > > > > > > + > > > > > > +2. Sending a Message > > > > > > + - **Function**: `mbox_send_message(struct mbox_chan *chan, void *msg)` > > > > > > + - **Description**: Sends a message through the mailbox channel. > > > > > > + - **Parameters**: > > > > > > + - `chan`: The mailbox channel used for communication. > > > > > > + - `msg`: Pointer to the message to be sent (usually NULL for dummy > > > > > > + messages). > > > > > > + - **Returns**: 0 on success, or a negative error code on failure. > > > > > > + > > > > > > +3. Transmitting Completion > > > > > > + - **Function**: `mbox_client_txdone(struct mbox_chan *chan, unsigned int > > > > > > + msg_id)` > > > > > > + - **Description**: Notifies the mailbox framework that message > > > > > > + transmission is complete. > > > > > > + - **Parameters**: > > > > > > + - `chan`: The mailbox channel associated with the message. > > > > > > + - `msg_id`: The identifier of the message that was transmitted. > > > > > > > > > > These functions should've been documented as kernel-doc comments, though. > > > > > > > > > > > + > > > > > > +Usage Example > > > > > > +------------- > > > > > > +In a typical mailbox client driver, the following steps are typically > > > > > > +performed: > > > > > > + > > > > > > +1. Initialize the Mailbox Client: > > > > > > + > > > > > > + .. code-block:: c > > > > > > + > > > > > > + struct mbox_client my_mbox_client = { > > > > > > + .dev = &my_device, > > > > > > + .tx_done = my_tx_done_callback, > > > > > > + .rx_callback = my_rx_callback, > > > > > > + .tx_block = false, > > > > > > + .knows_txdone = true, > > > > > > + }; > > > > > > + > > > > > > +2. Request a Mailbox Channel: > > > > > > + > > > > > > + .. code-block:: c > > > > > > + > > > > > > + mbox_chan = mbox_request_channel(&my_mbox_client, 0); > > > > > > + if (IS_ERR(mbox_chan)) { > > > > > > + // Handle error > > > > > > + } > > > > > > + > > > > > > +3. Send a Message: > > > > > > + > > > > > > + .. code-block:: c > > > > > > + > > > > > > + int ret = mbox_send_message(mbox_chan, NULL); // Sending a dummy message > > > > > > + if (ret < 0) { > > > > > > + // Handle error > > > > > > + } > > > > > > + > > > > > > +4. Complete Transmission: > > > > > > + > > > > > > + .. code-block:: c > > > > > > + > > > > > > + mbox_client_txdone(mbox_chan, 0); > > > > > > + > > > > > > +Interrupt Handling > > > > > > +------------------ > > > > > > +The mailbox interface can trigger interrupts upon message receipt. Handlers > > > > > > +should be implemented in the `rx_callback` function defined in the mailbox > > > > > > +client structure to process incoming messages. > > > > > > + > > > > > > +Example Mailbox Client Driver > > > > > > +----------------------------- > > > > > > +.. code-block:: c > > > > > > + > > > > > > + struct demo_client { > > > > > > + struct mbox_client cl; > > > > > > + struct mbox_chan *mbox; > > > > > > + struct completion c; > > > > > > + bool async; > > > > > > + /* ... */ > > > > > > + }; > > > > > > + > > > > > > + /* > > > > > > + * This is the handler for data received from remote. The behaviour is purely > > > > > > + * dependent upon the protocol. This is just an example. > > > > > > + */ > > > > > > + static void message_from_remote(struct mbox_client *cl, void *mssg) > > > > > > + { > > > > > > + struct demo_client *dc = container_of(cl, struct demo_client, cl); > > > > > > + if (dc->async) { > > > > > > + if (is_an_ack(mssg)) { > > > > > > + /* An ACK to our last sample sent */ > > > > > > + return; /* Or do something else here */ > > > > > > + } else { /* A new message from remote */ > > > > > > + queue_req(mssg); > > > > > > + } > > > > > > + } else { > > > > > > + /* Remote f/w sends only ACK packets on this channel */ > > > > > > + return; > > > > > > + } > > > > > > + } > > > > > > + > > > > > > + static void sample_sent(struct mbox_client *cl, void *mssg, int r) > > > > > > + { > > > > > > + struct demo_client *dc = container_of(cl, struct demo_client, cl); > > > > > > + complete(&dc->c); > > > > > > + } > > > > > > + > > > > > > + static void client_demo(struct platform_device *pdev) > > > > > > + { > > > > > > + struct demo_client *dc_sync, *dc_async; > > > > > > + /* The controller already knows async_pkt and sync_pkt */ > > > > > > + struct async_pkt ap; > > > > > > + struct sync_pkt sp; > > > > > > + > > > > > > + dc_sync = kzalloc(sizeof(*dc_sync), GFP_KERNEL); > > > > > > + dc_async = kzalloc(sizeof(*dc_async), GFP_KERNEL); > > > > > > + > > > > > > + /* Populate non-blocking mode client */ > > > > > > + dc_async->cl.dev = &pdev->dev; > > > > > > + dc_async->cl.rx_callback = message_from_remote; > > > > > > + dc_async->cl.tx_done = sample_sent; > > > > > > + dc_async->cl.tx_block = false; > > > > > > + dc_async->cl.tx_tout = 0; /* doesn't matter here */ > > > > > > + dc_async->cl.knows_txdone = false; /* depending upon protocol */ > > > > > > + dc_async->async = true; > > > > > > + init_completion(&dc_async->c); > > > > > > + > > > > > > + /* Populate blocking mode client */ > > > > > > + dc_sync->cl.dev = &pdev->dev; > > > > > > + dc_sync->cl.rx_callback = message_from_remote; > > > > > > + dc_sync->cl.tx_done = NULL; /* operate in blocking mode */ > > > > > > + dc_sync->cl.tx_block = true; > > > > > > + dc_sync->cl.tx_tout = 500; /* by half a second */ > > > > > > + dc_sync->cl.knows_txdone = false; /* depending upon protocol */ > > > > > > + dc_sync->async = false; > > > > > > + > > > > > > + /* ASync mailbox is listed second in 'mboxes' property */ > > > > > > + dc_async->mbox = mbox_request_channel(&dc_async->cl, 1); > > > > > > + /* Populate data packet */ > > > > > > + /* ap.xxx = 123; etc */ > > > > > > + /* Send async message to remote */ > > > > > > + mbox_send_message(dc_async->mbox, &ap); > > > > > > + > > > > > > + /* Sync mailbox is listed first in 'mboxes' property */ > > > > > > + dc_sync->mbox = mbox_request_channel(&dc_sync->cl, 0); > > > > > > + /* Populate data packet */ > > > > > > + /* sp.abc = 123; etc */ > > > > > > + /* Send message to remote in blocking mode */ > > > > > > + mbox_send_message(dc_sync->mbox, &sp); > > > > > > + /* At this point 'sp' has been sent */ > > > > > > + > > > > > > + /* Now wait for async chan to be done */ > > > > > > + wait_for_completion(&dc_async->c); > > > > > > + } > > > > > > diff --git a/Documentation/driver-api/mailbox/core.rst b/Documentation/driver-api/mailbox/core.rst > > > > > > new file mode 100644 > > > > > > index 000000000000..d1220086da67 > > > > > > --- /dev/null > > > > > > +++ b/Documentation/driver-api/mailbox/core.rst > > > > > > @@ -0,0 +1,182 @@ > > > > > > +===================== > > > > > > +mailbox documentation > > > > > > +===================== > > > > > > + > > > > > > +Hardware Introduction > > > > > > +===================== > > > > > > + > > > > > > +Mailbox hardware is a specialized component found in multi-core > > > > > > +processors and embedded systems that facilitates inter-processor > > > > > > +communication (IPC) or communication between different hardware > > > > > > +components. It provides a structured mechanism for sending and > > > > > > +receiving messages, allowing various processors or devices to > > > > > > +exchange data efficiently. Here's an overview of its key > > > > > > +characteristics and functions: > > > > > > + > > > > > > +Key Characteristics of Mailbox Hardware > > > > > > +Interrupt Handling: Many mailbox implementations support > > > > > > +interrupt-driven communication. This allows a receiving processor > > > > > > +to be alerted when a new message arrives, facilitating immediate > > > > > > +processing without polling the mailbox constantly. > > > > > > + > > > > > > +Hardware Registers: Mailbox hardware often includes registers for > > > > > > +configuration and status monitoring. These registers can be used > > > > > > +to control the mailbox's behavior, check for available messages, > > > > > > +or acknowledge message receipt. > > > > > > + > > > > > > +Support for Multiple Protocols: Mailboxes can support various > > > > > > +communication protocols, enabling interoperability between different > > > > > > +hardware components and simplifying the integration of diverse systems. > > > > > > + > > > > > > +Synchronous and Asynchronous Modes: Mailbox hardware can operate in > > > > > > +both synchronous and asynchronous modes. In synchronous mode, the > > > > > > +sender may wait for the receiver to acknowledge receipt before > > > > > > +proceeding, while in asynchronous mode, the sender can continue > > > > > > +executing other tasks immediately after sending the message. > > > > > > + > > > > > > + > > > > > > +Mailbox framework design > > > > > > +======================== > > > > > > + > > > > > > +The mailbox facilitates interprocessor communication by allowing processors to > > > > > > +exchange messages or signals. The mailbox framework consists of: > > > > > > + > > > > > > +Mailbox Controller: This is platform-specific and is responsible for configuring > > > > > > +and managing interrupts from the remote processor. It offers a generic API for > > > > > > +the mailbox client. > > > > > > + > > > > > > +Mailbox Client: This component handles the sending and receiving of messages. > > > > > > + > > > > > > + > > > > > > +............................................................................ > > > > > > +: client driver client_a client_b : > > > > > > +............................................................................ > > > > > > + ^-------------------^ > > > > > > + | > > > > > > + | > > > > > > +............................................................................ > > > > > > +: controller framework mailbox : > > > > > > +....................................|....................................... > > > > > > + | > > > > > > + | > > > > > > +............................................................................ > > > > > > +: controller driver device specific : > > > > > > +....................................|....................................... > > > > > > + | > > > > > > + | > > > > > > +kernel | > > > > > > +............................................................................ > > > > > > +hardware | > > > > > > + | > > > > > > + | > > > > > > +............................................................................ > > > > > > +: remote processor : > > > > > > +............................................................................ > > > > > > > > > > htmldocs build errors out: > > > > > > > > > > Documentation/driver-api/mailbox/core.rst:57: WARNING: Block quote ends without a blank line; unexpected unindent. > > > > > Documentation/driver-api/mailbox/core.rst:57: CRITICAL: Missing matching underline for section title overline. > > > > > > > > > > ............................................................................ > > > > > : controller framework mailbox : > > > > > ....................................|....................................... > > > > > > > > > > reST markup error: > > > > > Documentation/driver-api/mailbox/core.rst:57: (SEVERE/4) Missing matching underline for section title overline. > > > > > > > > > > ............................................................................ > > > > > : controller framework mailbox : > > > > > ....................................|....................................... > > > > > > > > > > I have to fix up the design diagram and wrap it: > > > > > > > > > > ---- >8 ---- > > > > > diff --git a/Documentation/driver-api/mailbox/core.rst b/Documentation/driver-api/mailbox/core.rst > > > > > index d1220086da679f..8d56d81007c11c 100644 > > > > > --- a/Documentation/driver-api/mailbox/core.rst > > > > > +++ b/Documentation/driver-api/mailbox/core.rst > > > > > @@ -47,31 +47,32 @@ the mailbox client. > > > > > > > > > > Mailbox Client: This component handles the sending and receiving of messages. > > > > > > > > > > +:: > > > > > > > > > > -............................................................................ > > > > > -: client driver client_a client_b : > > > > > -............................................................................ > > > > > - ^-------------------^ > > > > > - | > > > > > - | > > > > > -............................................................................ > > > > > -: controller framework mailbox : > > > > > -....................................|....................................... > > > > > - | > > > > > - | > > > > > -............................................................................ > > > > > -: controller driver device specific : > > > > > -....................................|....................................... > > > > > - | > > > > > - | > > > > > -kernel | > > > > > -............................................................................ > > > > > -hardware | > > > > > - | > > > > > - | > > > > > -............................................................................ > > > > > -: remote processor : > > > > > -............................................................................ > > > > > + +---------------------------------------------------------------------------+ > > > > > + | client driver client_a client_b | > > > > > + +---------------------------------------------------------------------------+ > > > > > + ^-------------------^ > > > > > + | > > > > > + | > > > > > + +--------------------------------------------------------------------------+ > > > > > + | controller framework mailbox | > > > > > + +-----------------------------------|--------------------------------------+ > > > > > + | > > > > > + | > > > > > + +--------------------------------------------------------------------------+ > > > > > + | controller driver device specific | > > > > > + +-----------------------------------|--------------------------------------+ > > > > > + | > > > > > + | > > > > > + kernel | > > > > > + ---------------------------------------------------------------------------- > > > > > + hardware | > > > > > + | > > > > > + | > > > > > + +--------------------------------------------------------------------------+ > > > > > + | remote processor | > > > > > + +--------------------------------------------------------------------------+ > > > > > > > > > > > > > > > In the context of a mailbox framework, a channel refers to a dedicated > > > > > > > > > > > + > > > > > > + > > > > > > +In the context of a mailbox framework, a channel refers to a dedicated > > > > > > +communication pathway between two or more processors or components. By using > > > > > > +channels, the framework abstracts the complexity of interprocessor communication. > > > > > > + > > > > > > +Data Structures > > > > > > +================ > > > > > > + > > > > > > +- **struct mbox_client** > > > > > > + This structure represents a client that communicates over a mailbox > > > > > > + channel. It holds information such as: > > > > > > + - A pointer to the device associated with the client (`dev`). > > > > > > + - Callback functions for handling message transmission events, including: > > > > > > + - `rx_callback`: Called when a message is received. > > > > > > + - `tx_done`: Called when a message transmission is acknowledged. > > > > > > + - Flags that specify the client’s configuration, such as whether it operates > > > > > > + in blocking mode. > > > > > > + > > > > > > +- **struct mbox_chan** > > > > > > + This structure represents an individual mailbox channel. It maintains the > > > > > > + state required for message queuing and transmission. Key members include: > > > > > > + - `msg_data`: Array of messages queued for transmission. > > > > > > + - `msg_count`: Number of messages currently queued. > > > > > > + - `msg_free`: Index of the next free slot in the message queue. > > > > > > + - `active_req`: Pointer to the currently active message being transmitted. > > > > > > + - Synchronization primitives to manage access from multiple contexts. > > > > > > + > > > > > > +- **struct mbox_controller** > > > > > > + This structure represents a mailbox controller that manages multiple > > > > > > + channels. It includes: > > > > > > + - A pointer to the device managing the mailbox. > > > > > > + - Operations for sending and receiving messages, as well as initializing > > > > > > + and shutting down the mailbox. > > > > > > + - A list of associated channels and the total number of channels available. > > > > > > > > > > Shouldn't these structs be documented as kernel-doc comments? tl;dr: > > > > > see Documentation/doc-guide/kernel-doc.html > > > > > > > > > > > + > > > > > > +controller framework APIs > > > > > > +========================= > > > > > > + > > > > > > +``struct `mbox_controller` Initialization > > > > > > +----------------------------------------- > > > > > > > > > > Properly double-backquote the struct name to format it as inline code: > > > > > > > > > > ---- >8 ---- > > > > > diff --git a/Documentation/driver-api/mailbox/core.rst b/Documentation/driver-api/mailbox/core.rst > > > > > index 239538f497e41a..d83456164464aa 100644 > > > > > --- a/Documentation/driver-api/mailbox/core.rst > > > > > +++ b/Documentation/driver-api/mailbox/core.rst > > > > > @@ -117,7 +117,7 @@ Data Structures > > > > > controller framework APIs > > > > > ========================= > > > > > > > > > > -``struct `mbox_controller` Initialization > > > > > +``struct mbox_controller`` Initialization > > > > > ----------------------------------------- > > > > > > > > > > Just like any other kernel framework, the whole mailbox controller registration > > > > > > > > > > > + > > > > > > +Just like any other kernel framework, the whole mailbox controller registration > > > > > > +relies on the driver filling a structure and registering against the > > > > > > +framework. In our case, that structure is mbox_controller. > > > > > > + > > > > > > +The first thing you need to do in your driver is to allocate this > > > > > > +structure. Any of the usual memory allocators will do, but you'll also > > > > > > +need to initialize a few fields in there: > > > > > > + > > > > > > +- ``dev``: should hold the pointer to the ``struct device`` associated > > > > > > + to your current driver instance. > > > > > > + > > > > > > +- ``ops``: Operators that work on each communication channel. > > > > > > + > > > > > > +- ``chans``: Array of channels. > > > > > > + > > > > > > +- ``num_chans``: Number of channels in the `chans` array. > > > > > > + > > > > > > +- ``txdone_irq``: Indicates if the controller can report to the API > > > > > > + when the last transmitted data was read by the > > > > > > + remote (e.g., if it has a TX ACK interrupt). > > > > > > + > > > > > > +All the below fields are not mandatory. > > > > > > + > > > > > > +- ``txdone_poll``: Indicates if the controller can read but not report > > > > > > + the TX done. For example, some register may show > > > > > > + the TX status, but no interrupt is raised. This > > > > > > + field is ignored if `txdone_irq` is set. > > > > > > + > > > > > > +- ``txpoll_period``: If `txdone_poll` is in effect, the API polls for > > > > > > + the last TX status after this many milliseconds. > > > > > > + > > > > > > +- ``of_xlate``: Controller driver-specific mapping of channel via > > > > > > + Device Tree (DT). > > > > > > + > > > > > > + > > > > > > +Key Functions > > > > > > +------------- > > > > > > + > > > > > > +- **int devm_mbox_controller_register(struct mbox_controller *mbox)** > > > > > > + This function registers a mailbox controller with the kernel. It makes the > > > > > > + channels associated with the controller available for client requests. The > > > > > > + function performs sanity checks on the controller structure to ensure all > > > > > > + necessary fields are populated. > > > > > > + > > > > > > +- **struct mbox_chan *mbox_request_channel(struct mbox_client *cl, int index)** > > > > > > + This function requests a mailbox channel for a specified client, identified > > > > > > + by an index. It searches for the appropriate mailbox channel, and if found, > > > > > > + it returns a pointer to the channel. If the request fails (e.g., if the > > > > > > + index is invalid), it returns an error pointer. > > > > > > + > > > > > > +- **void mbox_free_channel(struct mbox_chan *chan)** > > > > > > + This function releases a mailbox channel that was previously allocated for a > > > > > > + client. It ensures that the channel can be reused by other clients. If any > > > > > > + messages are still in the queue, they are aborted, and no callbacks are made. > > > > > > + > > > > > > +- **int mbox_send_message(struct mbox_chan *chan, void *mssg)** > > > > > > + This function is used by clients to send a message through the specified > > > > > > + mailbox channel. The function can operate in either blocking or non-blocking > > > > > > + mode, depending on the client’s configuration. It will queue the message for > > > > > > + transmission and notify the client once the message is acknowledged. > > > > > > + > > > > > > +- **void mbox_chan_received_data(struct mbox_chan *chan, void *mssg)** > > > > > > + This function is called by the controller driver to notify the mailbox > > > > > > + framework that a message has been received on the specified channel. The > > > > > > + received message is then passed to the appropriate client's `rx_callback` > > > > > > + function for processing. > > > > > > > > > > Shouldn't these functions also be documented as kernel-doc comments? > > > > > > > > > > > diff --git a/Documentation/driver-api/mailbox/index.rst b/Documentation/driver-api/mailbox/index.rst > > > > > > new file mode 100644 > > > > > > index 000000000000..e254a8fdb66a > > > > > > --- /dev/null > > > > > > +++ b/Documentation/driver-api/mailbox/index.rst > > > > > > @@ -0,0 +1,45 @@ > > > > > > +======================= > > > > > > +Mailbox documentation > > > > > > +======================= > > > > > > + > > > > > > +Mailbox documentation provides documents for various aspects of mailbox > > > > > > +framework. > > > > > > + > > > > > > +Mailbox development documentation > > > > > > +--------------------------------- > > > > > > + > > > > > > +This book helps with mailbox internal APIs and guide for mailbox device > > > > > > +driver writers. > > > > > > + > > > > > > +.. toctree:: > > > > > > + :maxdepth: 1 > > > > > > + > > > > > > + core > > > > > > + > > > > > > +mailbox controller driver documentation > > > > > > +------------------------------ > > > > > > + > > > > > > +This book is a guide to device driver writers on how to register > > > > > > +mailbox controller to the mailbox framework. > > > > > > + > > > > > > +.. toctree:: > > > > > > + :maxdepth: 1 > > > > > > + > > > > > > + writing_mailbox_controller_drivers > > > > > > + > > > > > > +mailbox client driver documentation > > > > > > +------------------------------ > > > > > > > > > > Match up section underline length by its title: > > > > > > > > > > ---- >8 ---- > > > > > diff --git a/Documentation/driver-api/mailbox/index.rst b/Documentation/driver-api/mailbox/index.rst > > > > > index e254a8fdb66ac7..02d7d5e8660999 100644 > > > > > --- a/Documentation/driver-api/mailbox/index.rst > > > > > +++ b/Documentation/driver-api/mailbox/index.rst > > > > > @@ -1,6 +1,6 @@ > > > > > -======================= > > > > > +===================== > > > > > Mailbox documentation > > > > > -======================= > > > > > +===================== > > > > > > > > > > Mailbox documentation provides documents for various aspects of mailbox > > > > > framework. > > > > > @@ -17,7 +17,7 @@ driver writers. > > > > > core > > > > > > > > > > mailbox controller driver documentation > > > > > ------------------------------- > > > > > +--------------------------------------- > > > > > > > > > > This book is a guide to device driver writers on how to register > > > > > mailbox controller to the mailbox framework. > > > > > @@ -28,7 +28,7 @@ mailbox controller to the mailbox framework. > > > > > writing_mailbox_controller_drivers > > > > > > > > > > mailbox client driver documentation > > > > > ------------------------------- > > > > > +----------------------------------- > > > > > > > > > > This book is a guide to mailbox client driver writers. > > > > > > > > > > > > > > > > + > > > > > > +This book is a guide to mailbox client driver writers. > > > > > > + > > > > > > +.. toctree:: > > > > > > + :maxdepth: 1 > > > > > > + > > > > > > + client > > > > > > + > > > > > > +.. only:: subproject and html > > > > > > + > > > > > > + Indices > > > > > > + ======= > > > > > > + > > > > > > + * :ref:`genindex` > > > > > > > > > > Fix up also the reference link on parent toctree: > > > > > > > > > > ---- >8 ---- > > > > > diff --git a/Documentation/driver-api/index.rst b/Documentation/driver-api/index.rst > > > > > index 7f83e05769b4a4..b4d78b92fd921a 100644 > > > > > --- a/Documentation/driver-api/index.rst > > > > > +++ b/Documentation/driver-api/index.rst > > > > > @@ -102,7 +102,7 @@ Subsystem-specific APIs > > > > > ipmb > > > > > ipmi > > > > > libata > > > > > - mailbox > > > > > + mailbox/index > > > > > md/index > > > > > media/index > > > > > mei/index > > > > > > > > > > > diff --git a/Documentation/driver-api/mailbox/writing_mailbox_controller_drivers.rst b/Documentation/driver-api/mailbox/writing_mailbox_controller_drivers.rst > > > > > > new file mode 100644 > > > > > > index 000000000000..2a82645c1357 > > > > > > --- /dev/null > > > > > > +++ b/Documentation/driver-api/mailbox/writing_mailbox_controller_drivers.rst > > > > > > @@ -0,0 +1,179 @@ > > > > > > +.. SPDX-License-Identifier: GPL-2.0 > > > > > > + > > > > > > +.. _writing_mailbox_controller_drivers: > > > > > > + > > > > > > +================================== > > > > > > +Writing Mailbox Controller Drivers > > > > > > +================================== > > > > > > + > > > > > > +Introduction > > > > > > +============ > > > > > > + > > > > > > +This document serves as a basic guideline for driver programmers that need > > > > > > +to hack a new mailbox controller driver or understand the essentials of > > > > > > +the existing ones. > > > > > > + > > > > > > +Driver Boilerplate > > > > > > +================== > > > > > > + > > > > > > +As a bare minimum, a mailbox controller driver needs to call > > > > > > +``mbox_controller_register`` function to register with the framework. > > > > > > + > > > > > > +A basic driver skeleton could look like this for a mailbox hardware that > > > > > > +has the following characteristics: > > > > > > +a. It supports only a single channel, i.e., only the remote processor can > > > > > > + send interrupts. > > > > > > +b. Data transfer is over the registers associated with mailbox hardware. > > > > > > +c. Mailbox hardware is configured to receive interrupts. > > > > > > +d. When the remote processor is ready to send data, it triggers a mailbox > > > > > > + interrupt. > > > > > > +e. As part of interrupt handling by Linux, it copies data from the registers. > > > > > > + > > > > > > +.. code-block:: c > > > > > > + > > > > > > + #include <linux/device.h> > > > > > > + #include <linux/interrupt.h> > > > > > > + #include <linux/io.h> > > > > > > + #include <linux/kernel.h> > > > > > > + #include <linux/mailbox_controller.h> > > > > > > + #include <linux/module.h> > > > > > > + #include <linux/of.h> > > > > > > + #include <linux/platform_device.h> > > > > > > + #define DRIVER_NAME "dummy_controller" > > > > > > + > > > > > > + struct dummy_mbox { > > > > > > + struct device *dev; > > > > > > + struct mbox_controller controller; > > > > > > + int irq; > > > > > > + }; > > > > > > + > > > > > > + static void dummy_mbox_receive(struct mbox_chan *chan) > > > > > > + { > > > > > > + struct dummy_mbox *mbox = chan->con_priv; > > > > > > + int val; > > > > > > + > > > > > > + // Data copied from registers > > > > > > + val = read_register(); > > > > > > + mbox_chan_received_data(chan, &val); > > > > > > + } > > > > > > + > > > > > > + static irqreturn_t dummy_mbox_irq_handler(int irq, void *data) > > > > > > + { > > > > > > + struct mbox_chan *chan = data; > > > > > > + struct dummy_mbox *mbox = chan->con_priv; > > > > > > + u32 reg; > > > > > > + > > > > > > + // Read registers to see if data is received > > > > > > + dummy_mbox_receive(chan); > > > > > > + mbox_chan_txdone(chan, 0); > > > > > > + return reg ? IRQ_HANDLED : IRQ_NONE; > > > > > > + } > > > > > > + > > > > > > + static int dummy_mbox_send_data(struct mbox_chan *chan, void *data) > > > > > > + { > > > > > > + // Write data in registers to send it to the remote processor > > > > > > + return 0; > > > > > > + } > > > > > > + > > > > > > + static int dummy_mbox_startup(struct mbox_chan *chan) > > > > > > + { > > > > > > + struct dummy_mbox *mbox = chan->con_priv; > > > > > > + u32 reg; > > > > > > + int ret; > > > > > > + > > > > > > + ret = devm_request_irq(mbox->dev, mbox->irq, dummy_mbox_irq_handler, 0, > > > > > > + DRIVER_NAME, chan); > > > > > > + if (ret < 0) { > > > > > > + dev_err(mbox->dev, "Cannot request irq\n"); > > > > > > + return ret; > > > > > > + } > > > > > > + > > > > > > + /* Register write to enable IRQ generation */ > > > > > > + > > > > > > + return 0; > > > > > > + } > > > > > > + > > > > > > + static void dummy_mbox_shutdown(struct mbox_chan *chan) > > > > > > + { > > > > > > + struct dummy_mbox *mbox = chan->con_priv; > > > > > > + > > > > > > + /* Disable interrupt generation */ > > > > > > + devm_free_irq(mbox->dev, mbox->irq, chan); > > > > > > + } > > > > > > + > > > > > > + static const struct mbox_chan_ops dummy_mbox_ops = { > > > > > > + .send_data = dummy_mbox_send_data, > > > > > > + .startup = dummy_mbox_startup, > > > > > > + .shutdown = dummy_mbox_shutdown, > > > > > > + }; > > > > > > + > > > > > > + static int dummy_mbox_probe(struct platform_device *pdev) > > > > > > + { > > > > > > + struct dummy_mbox *mbox; > > > > > > + struct mbox_chan *chans; > > > > > > + int ret; > > > > > > + > > > > > > + mbox = devm_kzalloc(&pdev->dev, sizeof(*mbox), GFP_KERNEL); > > > > > > + if (!mbox) > > > > > > + return -ENOMEM; > > > > > > + > > > > > > + /* Allocate one channel */ > > > > > > + chans = devm_kzalloc(&pdev->dev, sizeof(*chans), GFP_KERNEL); > > > > > > + if (!chans) > > > > > > + return -ENOMEM; > > > > > > + > > > > > > + mbox->base = devm_platform_ioremap_resource(pdev, 0); > > > > > > + if (IS_ERR(mbox->base)) > > > > > > + return PTR_ERR(mbox->base); > > > > > > + > > > > > > + mbox->irq = platform_get_irq(pdev, 0); > > > > > > + if (mbox->irq < 0) > > > > > > + return mbox->irq; > > > > > > + > > > > > > + mbox->dev = &pdev->dev; > > > > > > + > > > > > > + /* Hardware supports only one channel. */ > > > > > > + mbox->controller.dev = mbox->dev; > > > > > > + mbox->controller.num_chans = 1; > > > > > > + mbox->controller.chans = chans; > > > > > > + mbox->controller.ops = &dummy_mbox_ops; > > > > > > + mbox->controller.txdone_irq = true; > > > > > > + > > > > > > + ret = devm_mbox_controller_register(mbox->dev, &mbox->controller); > > > > > > + if (ret) { > > > > > > + dev_err(&pdev->dev, "Could not register mailbox controller\n"); > > > > > > + return ret; > > > > > > + } > > > > > > + > > > > > > + return ret; > > > > > > + } > > > > > > + > > > > > > + static const struct of_device_id dummy_mbox_match[] = { > > > > > > + { .compatible = "dummy,dummy-mailbox" }, > > > > > > + { }, > > > > > > + }; > > > > > > + > > > > > > + MODULE_DEVICE_TABLE(of, dummy_mbox_match); > > > > > > + > > > > > > + static struct platform_driver dummy_mbox_driver = { > > > > > > + .probe = dummy_mbox_probe, > > > > > > + .driver = { > > > > > > + .name = DRIVER_NAME, > > > > > > + .of_match_table = dummy_mbox_match, > > > > > > + }, > > > > > > + }; > > > > > > + > > > > > > + module_platform_driver(dummy_mbox_driver); > > > > > > + MODULE_LICENSE("GPL v2"); > > > > > > + MODULE_DESCRIPTION("Dummy mailbox controller driver"); > > > > > > + > > > > > > +In the above code, a couple of things are done: > > > > > > +a. The controller is registered in the probe along with callbacks, which in > > > > > > + this case are the bare minimum: ``startup``, ``shutdown``, and > > > > > > + ``send_data``. > > > > > > +b. IRQ is registered to get notifications from the remote processor. > > > > > > +c. In the IRQ handler, registers are read to copy data, and > > > > > > + ``mbox_chan_received_data`` is called to hand over the data to the client. > > > > > > +d. ``mbox_chan_txdone`` is called to let the framework know that this data > > > > > > + is the last data and no more data is to be expected for the current transfer. > > > > > > + > > > > > > > > > > Sphinx warns out numerous indentation warnings on the lists, so I have to > > > > > fix them up: > > > > > > > > > > ---- >8 ---- > > > > > diff --git a/Documentation/driver-api/mailbox/client.rst b/Documentation/driver-api/mailbox/client.rst > > > > > index 9088f83734230d..17dafaca056777 100644 > > > > > --- a/Documentation/driver-api/mailbox/client.rst > > > > > +++ b/Documentation/driver-api/mailbox/client.rst > > > > > @@ -31,6 +31,7 @@ The mailbox structure is defined as follows: > > > > > Key Functions > > > > > ------------- > > > > > 1. Requesting a Mailbox Channel > > > > > + > > > > > - **Function**: `mbox_request_channel(struct mbox_client *client, > > > > > unsigned int channel)` > > > > > - **Description**: Requests a mailbox channel for sending messages. > > > > > @@ -41,15 +42,19 @@ Key Functions > > > > > code on failure. > > > > > > > > > > 2. Sending a Message > > > > > + > > > > > - **Function**: `mbox_send_message(struct mbox_chan *chan, void *msg)` > > > > > - **Description**: Sends a message through the mailbox channel. > > > > > - **Parameters**: > > > > > + > > > > > - `chan`: The mailbox channel used for communication. > > > > > - `msg`: Pointer to the message to be sent (usually NULL for dummy > > > > > messages). > > > > > + > > > > > - **Returns**: 0 on success, or a negative error code on failure. > > > > > > > > > > 3. Transmitting Completion > > > > > + > > > > > - **Function**: `mbox_client_txdone(struct mbox_chan *chan, unsigned int > > > > > msg_id)` > > > > > - **Description**: Notifies the mailbox framework that message > > > > > diff --git a/Documentation/driver-api/mailbox/core.rst b/Documentation/driver-api/mailbox/core.rst > > > > > index 8d56d81007c11c..239538f497e41a 100644 > > > > > --- a/Documentation/driver-api/mailbox/core.rst > > > > > +++ b/Documentation/driver-api/mailbox/core.rst > > > > > @@ -85,16 +85,20 @@ Data Structures > > > > > - **struct mbox_client** > > > > > This structure represents a client that communicates over a mailbox > > > > > channel. It holds information such as: > > > > > + > > > > > - A pointer to the device associated with the client (`dev`). > > > > > - Callback functions for handling message transmission events, including: > > > > > + > > > > > - `rx_callback`: Called when a message is received. > > > > > - `tx_done`: Called when a message transmission is acknowledged. > > > > > + > > > > > - Flags that specify the client’s configuration, such as whether it operates > > > > > in blocking mode. > > > > > > > > > > - **struct mbox_chan** > > > > > This structure represents an individual mailbox channel. It maintains the > > > > > state required for message queuing and transmission. Key members include: > > > > > + > > > > > - `msg_data`: Array of messages queued for transmission. > > > > > - `msg_count`: Number of messages currently queued. > > > > > - `msg_free`: Index of the next free slot in the message queue. > > > > > @@ -104,6 +108,7 @@ Data Structures > > > > > - **struct mbox_controller** > > > > > This structure represents a mailbox controller that manages multiple > > > > > channels. It includes: > > > > > + > > > > > - A pointer to the device managing the mailbox. > > > > > - Operations for sending and receiving messages, as well as initializing > > > > > and shutting down the mailbox. > > > > > @@ -133,21 +138,20 @@ need to initialize a few fields in there: > > > > > - ``num_chans``: Number of channels in the `chans` array. > > > > > > > > > > - ``txdone_irq``: Indicates if the controller can report to the API > > > > > - when the last transmitted data was read by the > > > > > - remote (e.g., if it has a TX ACK interrupt). > > > > > + when the last transmitted data was read by the remote (e.g., if it has a > > > > > + TX ACK interrupt). > > > > > > > > > > All the below fields are not mandatory. > > > > > > > > > > - ``txdone_poll``: Indicates if the controller can read but not report > > > > > - the TX done. For example, some register may show > > > > > - the TX status, but no interrupt is raised. This > > > > > - field is ignored if `txdone_irq` is set. > > > > > + the TX done. For example, some register may show the TX status, but no > > > > > + interrupt is raised. This field is ignored if `txdone_irq` is set. > > > > > > > > > > - ``txpoll_period``: If `txdone_poll` is in effect, the API polls for > > > > > - the last TX status after this many milliseconds. > > > > > + the last TX status after this many milliseconds. > > > > > > > > > > - ``of_xlate``: Controller driver-specific mapping of channel via > > > > > - Device Tree (DT). > > > > > + Device Tree (DT). > > > > > > > > > > > > > > > Key Functions > > > > > diff --git a/Documentation/driver-api/mailbox/writing_mailbox_controller_drivers.rst b/Documentation/driver-api/mailbox/writing_mailbox_controller_drivers.rst > > > > > index 2a82645c13573e..853adf6918173d 100644 > > > > > --- a/Documentation/driver-api/mailbox/writing_mailbox_controller_drivers.rst > > > > > +++ b/Documentation/driver-api/mailbox/writing_mailbox_controller_drivers.rst > > > > > @@ -21,6 +21,7 @@ As a bare minimum, a mailbox controller driver needs to call > > > > > > > > > > A basic driver skeleton could look like this for a mailbox hardware that > > > > > has the following characteristics: > > > > > + > > > > > a. It supports only a single channel, i.e., only the remote processor can > > > > > send interrupts. > > > > > b. Data transfer is over the registers associated with mailbox hardware. > > > > > @@ -168,6 +169,7 @@ e. As part of interrupt handling by Linux, it copies data from the registers. > > > > > MODULE_DESCRIPTION("Dummy mailbox controller driver"); > > > > > > > > > > In the above code, a couple of things are done: > > > > > + > > > > > a. The controller is registered in the probe along with callbacks, which in > > > > > this case are the bare minimum: ``startup``, ``shutdown``, and > > > > > ``send_data``. > > > > > > > > > > Thanks. > > > > > > > > > > -- > > > > > An old man doll... just what I always wanted! - Clara ^ permalink raw reply [flat|nested] 12+ messages in thread
end of thread, other threads:[~2024-12-05 20:32 UTC | newest] Thread overview: 12+ messages (download: mbox.gz / follow: Atom feed) -- links below jump to the message on this page -- 2024-10-19 19:55 [PATCH 1/2] mailbox: Documentation: remove the old documentation anish kumar 2024-10-19 19:55 ` [PATCH 2/2] mailbox: Documentation: add the latest documentation anish kumar 2024-10-24 18:42 ` anish kumar 2024-10-25 3:38 ` Bagas Sanjaya 2024-10-25 19:24 ` anish kumar 2024-10-29 18:06 ` anish kumar 2024-10-29 23:51 ` Bagas Sanjaya 2024-10-30 0:42 ` anish kumar 2024-10-30 1:17 ` Bagas Sanjaya 2024-10-30 17:41 ` Jassi Brar 2024-10-30 18:13 ` anish kumar 2024-12-05 20:32 ` anish kumar
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®