Commit af3137f1 authored by Mauro Carvalho Chehab's avatar Mauro Carvalho Chehab Committed by Jonathan Corbet

rpmsg.txt: standardize document format

Each text file under Documentation follows a different
format. Some doesn't even have titles!

Change its representation to follow the adopted standard,
using ReST markups for it to be parseable by Sphinx:

- mark document and chapter titles;
- mark notes;
- mark literal blocks;
- adjust identation.
Signed-off-by: default avatarMauro Carvalho Chehab <mchehab@s-opensource.com>
Signed-off-by: default avatarJonathan Corbet <corbet@lwn.net>
parent 773810d3
============================================
Remote Processor Messaging (rpmsg) Framework Remote Processor Messaging (rpmsg) Framework
============================================
Note: this document describes the rpmsg bus and how to write rpmsg drivers. .. note::
To learn how to add rpmsg support for new platforms, check out remoteproc.txt
(also a resident of Documentation/).
1. Introduction This document describes the rpmsg bus and how to write rpmsg drivers.
To learn how to add rpmsg support for new platforms, check out remoteproc.txt
(also a resident of Documentation/).
Introduction
============
Modern SoCs typically employ heterogeneous remote processor devices in Modern SoCs typically employ heterogeneous remote processor devices in
asymmetric multiprocessing (AMP) configurations, which may be running asymmetric multiprocessing (AMP) configurations, which may be running
...@@ -58,170 +63,222 @@ to their destination address (this is done by invoking the driver's rx handler ...@@ -58,170 +63,222 @@ to their destination address (this is done by invoking the driver's rx handler
with the payload of the inbound message). with the payload of the inbound message).
2. User API User API
========
::
int rpmsg_send(struct rpmsg_channel *rpdev, void *data, int len); int rpmsg_send(struct rpmsg_channel *rpdev, void *data, int len);
- sends a message across to the remote processor on a given channel.
The caller should specify the channel, the data it wants to send, sends a message across to the remote processor on a given channel.
and its length (in bytes). The message will be sent on the specified The caller should specify the channel, the data it wants to send,
channel, i.e. its source and destination address fields will be and its length (in bytes). The message will be sent on the specified
set to the channel's src and dst addresses. channel, i.e. its source and destination address fields will be
set to the channel's src and dst addresses.
In case there are no TX buffers available, the function will block until
one becomes available (i.e. until the remote processor consumes In case there are no TX buffers available, the function will block until
a tx buffer and puts it back on virtio's used descriptor ring), one becomes available (i.e. until the remote processor consumes
or a timeout of 15 seconds elapses. When the latter happens, a tx buffer and puts it back on virtio's used descriptor ring),
-ERESTARTSYS is returned. or a timeout of 15 seconds elapses. When the latter happens,
The function can only be called from a process context (for now). -ERESTARTSYS is returned.
Returns 0 on success and an appropriate error value on failure.
The function can only be called from a process context (for now).
Returns 0 on success and an appropriate error value on failure.
::
int rpmsg_sendto(struct rpmsg_channel *rpdev, void *data, int len, u32 dst); int rpmsg_sendto(struct rpmsg_channel *rpdev, void *data, int len, u32 dst);
- sends a message across to the remote processor on a given channel,
to a destination address provided by the caller. sends a message across to the remote processor on a given channel,
The caller should specify the channel, the data it wants to send, to a destination address provided by the caller.
its length (in bytes), and an explicit destination address.
The message will then be sent to the remote processor to which the The caller should specify the channel, the data it wants to send,
channel belongs, using the channel's src address, and the user-provided its length (in bytes), and an explicit destination address.
dst address (thus the channel's dst address will be ignored).
The message will then be sent to the remote processor to which the
In case there are no TX buffers available, the function will block until channel belongs, using the channel's src address, and the user-provided
one becomes available (i.e. until the remote processor consumes dst address (thus the channel's dst address will be ignored).
a tx buffer and puts it back on virtio's used descriptor ring),
or a timeout of 15 seconds elapses. When the latter happens, In case there are no TX buffers available, the function will block until
-ERESTARTSYS is returned. one becomes available (i.e. until the remote processor consumes
The function can only be called from a process context (for now). a tx buffer and puts it back on virtio's used descriptor ring),
Returns 0 on success and an appropriate error value on failure. or a timeout of 15 seconds elapses. When the latter happens,
-ERESTARTSYS is returned.
The function can only be called from a process context (for now).
Returns 0 on success and an appropriate error value on failure.
::
int rpmsg_send_offchannel(struct rpmsg_channel *rpdev, u32 src, u32 dst, int rpmsg_send_offchannel(struct rpmsg_channel *rpdev, u32 src, u32 dst,
void *data, int len); void *data, int len);
- sends a message across to the remote processor, using the src and dst
addresses provided by the user.
The caller should specify the channel, the data it wants to send, sends a message across to the remote processor, using the src and dst
its length (in bytes), and explicit source and destination addresses. addresses provided by the user.
The message will then be sent to the remote processor to which the
channel belongs, but the channel's src and dst addresses will be The caller should specify the channel, the data it wants to send,
ignored (and the user-provided addresses will be used instead). its length (in bytes), and explicit source and destination addresses.
The message will then be sent to the remote processor to which the
In case there are no TX buffers available, the function will block until channel belongs, but the channel's src and dst addresses will be
one becomes available (i.e. until the remote processor consumes ignored (and the user-provided addresses will be used instead).
a tx buffer and puts it back on virtio's used descriptor ring),
or a timeout of 15 seconds elapses. When the latter happens, In case there are no TX buffers available, the function will block until
-ERESTARTSYS is returned. one becomes available (i.e. until the remote processor consumes
The function can only be called from a process context (for now). a tx buffer and puts it back on virtio's used descriptor ring),
Returns 0 on success and an appropriate error value on failure. or a timeout of 15 seconds elapses. When the latter happens,
-ERESTARTSYS is returned.
The function can only be called from a process context (for now).
Returns 0 on success and an appropriate error value on failure.
::
int rpmsg_trysend(struct rpmsg_channel *rpdev, void *data, int len); int rpmsg_trysend(struct rpmsg_channel *rpdev, void *data, int len);
- sends a message across to the remote processor on a given channel.
The caller should specify the channel, the data it wants to send,
and its length (in bytes). The message will be sent on the specified
channel, i.e. its source and destination address fields will be
set to the channel's src and dst addresses.
In case there are no TX buffers available, the function will immediately sends a message across to the remote processor on a given channel.
return -ENOMEM without waiting until one becomes available. The caller should specify the channel, the data it wants to send,
The function can only be called from a process context (for now). and its length (in bytes). The message will be sent on the specified
Returns 0 on success and an appropriate error value on failure. channel, i.e. its source and destination address fields will be
set to the channel's src and dst addresses.
In case there are no TX buffers available, the function will immediately
return -ENOMEM without waiting until one becomes available.
The function can only be called from a process context (for now).
Returns 0 on success and an appropriate error value on failure.
::
int rpmsg_trysendto(struct rpmsg_channel *rpdev, void *data, int len, u32 dst) int rpmsg_trysendto(struct rpmsg_channel *rpdev, void *data, int len, u32 dst)
- sends a message across to the remote processor on a given channel,
to a destination address provided by the user.
The user should specify the channel, the data it wants to send, sends a message across to the remote processor on a given channel,
its length (in bytes), and an explicit destination address. to a destination address provided by the user.
The message will then be sent to the remote processor to which the
channel belongs, using the channel's src address, and the user-provided The user should specify the channel, the data it wants to send,
dst address (thus the channel's dst address will be ignored). its length (in bytes), and an explicit destination address.
In case there are no TX buffers available, the function will immediately The message will then be sent to the remote processor to which the
return -ENOMEM without waiting until one becomes available. channel belongs, using the channel's src address, and the user-provided
The function can only be called from a process context (for now). dst address (thus the channel's dst address will be ignored).
Returns 0 on success and an appropriate error value on failure.
In case there are no TX buffers available, the function will immediately
return -ENOMEM without waiting until one becomes available.
The function can only be called from a process context (for now).
Returns 0 on success and an appropriate error value on failure.
::
int rpmsg_trysend_offchannel(struct rpmsg_channel *rpdev, u32 src, u32 dst, int rpmsg_trysend_offchannel(struct rpmsg_channel *rpdev, u32 src, u32 dst,
void *data, int len); void *data, int len);
- sends a message across to the remote processor, using source and
destination addresses provided by the user.
The user should specify the channel, the data it wants to send, sends a message across to the remote processor, using source and
its length (in bytes), and explicit source and destination addresses. destination addresses provided by the user.
The message will then be sent to the remote processor to which the
channel belongs, but the channel's src and dst addresses will be The user should specify the channel, the data it wants to send,
ignored (and the user-provided addresses will be used instead). its length (in bytes), and explicit source and destination addresses.
The message will then be sent to the remote processor to which the
In case there are no TX buffers available, the function will immediately channel belongs, but the channel's src and dst addresses will be
return -ENOMEM without waiting until one becomes available. ignored (and the user-provided addresses will be used instead).
The function can only be called from a process context (for now).
Returns 0 on success and an appropriate error value on failure. In case there are no TX buffers available, the function will immediately
return -ENOMEM without waiting until one becomes available.
The function can only be called from a process context (for now).
Returns 0 on success and an appropriate error value on failure.
::
struct rpmsg_endpoint *rpmsg_create_ept(struct rpmsg_channel *rpdev, struct rpmsg_endpoint *rpmsg_create_ept(struct rpmsg_channel *rpdev,
void (*cb)(struct rpmsg_channel *, void *, int, void *, u32), void (*cb)(struct rpmsg_channel *, void *, int, void *, u32),
void *priv, u32 addr); void *priv, u32 addr);
- every rpmsg address in the system is bound to an rx callback (so when
inbound messages arrive, they are dispatched by the rpmsg bus using the every rpmsg address in the system is bound to an rx callback (so when
appropriate callback handler) by means of an rpmsg_endpoint struct. inbound messages arrive, they are dispatched by the rpmsg bus using the
appropriate callback handler) by means of an rpmsg_endpoint struct.
This function allows drivers to create such an endpoint, and by that,
bind a callback, and possibly some private data too, to an rpmsg address This function allows drivers to create such an endpoint, and by that,
(either one that is known in advance, or one that will be dynamically bind a callback, and possibly some private data too, to an rpmsg address
assigned for them). (either one that is known in advance, or one that will be dynamically
assigned for them).
Simple rpmsg drivers need not call rpmsg_create_ept, because an endpoint
is already created for them when they are probed by the rpmsg bus Simple rpmsg drivers need not call rpmsg_create_ept, because an endpoint
(using the rx callback they provide when they registered to the rpmsg bus). is already created for them when they are probed by the rpmsg bus
(using the rx callback they provide when they registered to the rpmsg bus).
So things should just work for simple drivers: they already have an
endpoint, their rx callback is bound to their rpmsg address, and when So things should just work for simple drivers: they already have an
relevant inbound messages arrive (i.e. messages which their dst address endpoint, their rx callback is bound to their rpmsg address, and when
equals to the src address of their rpmsg channel), the driver's handler relevant inbound messages arrive (i.e. messages which their dst address
is invoked to process it. equals to the src address of their rpmsg channel), the driver's handler
is invoked to process it.
That said, more complicated drivers might do need to allocate
additional rpmsg addresses, and bind them to different rx callbacks. That said, more complicated drivers might do need to allocate
To accomplish that, those drivers need to call this function. additional rpmsg addresses, and bind them to different rx callbacks.
Drivers should provide their channel (so the new endpoint would bind To accomplish that, those drivers need to call this function.
to the same remote processor their channel belongs to), an rx callback Drivers should provide their channel (so the new endpoint would bind
function, an optional private data (which is provided back when the to the same remote processor their channel belongs to), an rx callback
rx callback is invoked), and an address they want to bind with the function, an optional private data (which is provided back when the
callback. If addr is RPMSG_ADDR_ANY, then rpmsg_create_ept will rx callback is invoked), and an address they want to bind with the
dynamically assign them an available rpmsg address (drivers should have callback. If addr is RPMSG_ADDR_ANY, then rpmsg_create_ept will
a very good reason why not to always use RPMSG_ADDR_ANY here). dynamically assign them an available rpmsg address (drivers should have
a very good reason why not to always use RPMSG_ADDR_ANY here).
Returns a pointer to the endpoint on success, or NULL on error.
Returns a pointer to the endpoint on success, or NULL on error.
::
void rpmsg_destroy_ept(struct rpmsg_endpoint *ept); void rpmsg_destroy_ept(struct rpmsg_endpoint *ept);
- destroys an existing rpmsg endpoint. user should provide a pointer
to an rpmsg endpoint that was previously created with rpmsg_create_ept().
destroys an existing rpmsg endpoint. user should provide a pointer
to an rpmsg endpoint that was previously created with rpmsg_create_ept().
::
int register_rpmsg_driver(struct rpmsg_driver *rpdrv); int register_rpmsg_driver(struct rpmsg_driver *rpdrv);
- registers an rpmsg driver with the rpmsg bus. user should provide
a pointer to an rpmsg_driver struct, which contains the driver's
->probe() and ->remove() functions, an rx callback, and an id_table registers an rpmsg driver with the rpmsg bus. user should provide
specifying the names of the channels this driver is interested to a pointer to an rpmsg_driver struct, which contains the driver's
be probed with. ->probe() and ->remove() functions, an rx callback, and an id_table
specifying the names of the channels this driver is interested to
be probed with.
::
void unregister_rpmsg_driver(struct rpmsg_driver *rpdrv); void unregister_rpmsg_driver(struct rpmsg_driver *rpdrv);
- unregisters an rpmsg driver from the rpmsg bus. user should provide
a pointer to a previously-registered rpmsg_driver struct.
Returns 0 on success, and an appropriate error value on failure.
3. Typical usage unregisters an rpmsg driver from the rpmsg bus. user should provide
a pointer to a previously-registered rpmsg_driver struct.
Returns 0 on success, and an appropriate error value on failure.
Typical usage
=============
The following is a simple rpmsg driver, that sends an "hello!" message The following is a simple rpmsg driver, that sends an "hello!" message
on probe(), and whenever it receives an incoming message, it dumps its on probe(), and whenever it receives an incoming message, it dumps its
content to the console. content to the console.
#include <linux/kernel.h> ::
#include <linux/module.h>
#include <linux/rpmsg.h> #include <linux/kernel.h>
#include <linux/module.h>
#include <linux/rpmsg.h>
static void rpmsg_sample_cb(struct rpmsg_channel *rpdev, void *data, int len, static void rpmsg_sample_cb(struct rpmsg_channel *rpdev, void *data, int len,
void *priv, u32 src) void *priv, u32 src)
{ {
print_hex_dump(KERN_INFO, "incoming message:", DUMP_PREFIX_NONE, print_hex_dump(KERN_INFO, "incoming message:", DUMP_PREFIX_NONE,
16, 1, data, len, true); 16, 1, data, len, true);
} }
static int rpmsg_sample_probe(struct rpmsg_channel *rpdev) static int rpmsg_sample_probe(struct rpmsg_channel *rpdev)
{ {
int err; int err;
dev_info(&rpdev->dev, "chnl: 0x%x -> 0x%x\n", rpdev->src, rpdev->dst); dev_info(&rpdev->dev, "chnl: 0x%x -> 0x%x\n", rpdev->src, rpdev->dst);
...@@ -234,32 +291,35 @@ static int rpmsg_sample_probe(struct rpmsg_channel *rpdev) ...@@ -234,32 +291,35 @@ static int rpmsg_sample_probe(struct rpmsg_channel *rpdev)
} }
return 0; return 0;
} }
static void rpmsg_sample_remove(struct rpmsg_channel *rpdev) static void rpmsg_sample_remove(struct rpmsg_channel *rpdev)
{ {
dev_info(&rpdev->dev, "rpmsg sample client driver is removed\n"); dev_info(&rpdev->dev, "rpmsg sample client driver is removed\n");
} }
static struct rpmsg_device_id rpmsg_driver_sample_id_table[] = { static struct rpmsg_device_id rpmsg_driver_sample_id_table[] = {
{ .name = "rpmsg-client-sample" }, { .name = "rpmsg-client-sample" },
{ }, { },
}; };
MODULE_DEVICE_TABLE(rpmsg, rpmsg_driver_sample_id_table); MODULE_DEVICE_TABLE(rpmsg, rpmsg_driver_sample_id_table);
static struct rpmsg_driver rpmsg_sample_client = { static struct rpmsg_driver rpmsg_sample_client = {
.drv.name = KBUILD_MODNAME, .drv.name = KBUILD_MODNAME,
.id_table = rpmsg_driver_sample_id_table, .id_table = rpmsg_driver_sample_id_table,
.probe = rpmsg_sample_probe, .probe = rpmsg_sample_probe,
.callback = rpmsg_sample_cb, .callback = rpmsg_sample_cb,
.remove = rpmsg_sample_remove, .remove = rpmsg_sample_remove,
}; };
module_rpmsg_driver(rpmsg_sample_client); module_rpmsg_driver(rpmsg_sample_client);
.. note::
Note: a similar sample which can be built and loaded can be found a similar sample which can be built and loaded can be found
in samples/rpmsg/. in samples/rpmsg/.
4. Allocations of rpmsg channels: Allocations of rpmsg channels
=============================
At this point we only support dynamic allocations of rpmsg channels. At this point we only support dynamic allocations of rpmsg channels.
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment