/** * rpmsg_create_channel() - create a new rpmsg channel * using its name and address info. * @rpdev: rpmsg device * @chinfo: channel_info to bind * * Return: a pointer to the new rpmsg device on success, or NULL on error.
*/ struct rpmsg_device *rpmsg_create_channel(struct rpmsg_device *rpdev, struct rpmsg_channel_info *chinfo)
{ if (WARN_ON(!rpdev)) return NULL; if (!rpdev->ops || !rpdev->ops->create_channel) {
dev_err(&rpdev->dev, "no create_channel ops found\n"); return NULL;
}
/** * rpmsg_release_channel() - release a rpmsg channel * using its name and address info. * @rpdev: rpmsg device * @chinfo: channel_info to bind * * Return: 0 on success or an appropriate error value.
*/ int rpmsg_release_channel(struct rpmsg_device *rpdev, struct rpmsg_channel_info *chinfo)
{ if (WARN_ON(!rpdev)) return -EINVAL; if (!rpdev->ops || !rpdev->ops->release_channel) {
dev_err(&rpdev->dev, "no release_channel ops found\n"); return -ENXIO;
}
/** * rpmsg_create_ept() - create a new rpmsg_endpoint * @rpdev: rpmsg channel device * @cb: rx callback handler * @priv: private data for the driver's use * @chinfo: channel_info with the local rpmsg address to bind with @cb * * 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 * 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 * (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 * (using the rx callback provided 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 * relevant inbound messages arrive (i.e. messages which their dst address * equals to the src address of their rpmsg channel), the driver's handler * is invoked to process it. * * That said, more complicated drivers might need to allocate * additional rpmsg addresses, and bind them to different rx callbacks. * To accomplish that, those drivers need to call this function. * * Drivers should provide their @rpdev channel (so the new endpoint would belong * to the same remote processor their channel belongs to), an rx callback * function, an optional private data (which is provided back when the * rx callback is invoked), and an address they want to bind with the * callback. If @addr is RPMSG_ADDR_ANY, then rpmsg_create_ept will * dynamically assign them an available rpmsg address (drivers should have * a very good reason why not to always use RPMSG_ADDR_ANY here). * * Return: a pointer to the endpoint on success, or NULL on error.
*/ struct rpmsg_endpoint *rpmsg_create_ept(struct rpmsg_device *rpdev,
rpmsg_rx_cb_t cb, void *priv, struct rpmsg_channel_info chinfo)
{ if (WARN_ON(!rpdev)) return NULL;
/** * rpmsg_destroy_ept() - destroy an existing rpmsg endpoint * @ept: endpoing to destroy * * Should be used by drivers to destroy an rpmsg endpoint previously * created with rpmsg_create_ept(). As with other types of "free" NULL * is a valid parameter.
*/ void rpmsg_destroy_ept(struct rpmsg_endpoint *ept)
{ if (ept && ept->ops)
ept->ops->destroy_ept(ept);
}
EXPORT_SYMBOL(rpmsg_destroy_ept);
/** * rpmsg_send() - send a message across to the remote processor * @ept: the rpmsg endpoint * @data: payload of message * @len: length of payload * * This function sends @data of length @len on the @ept endpoint. * The message will be sent to the remote processor which the @ept * endpoint belongs to, using @ept's address and its associated rpmsg * device destination addresses. * In case there are no TX buffers available, the function will block until * one becomes available, or a timeout of 15 seconds elapses. When the latter * happens, -ERESTARTSYS is returned. * * Can only be called from process context (for now). * * Return: 0 on success and an appropriate error value on failure.
*/ int rpmsg_send(struct rpmsg_endpoint *ept, void *data, int len)
{ if (WARN_ON(!ept)) return -EINVAL; if (!ept->ops->send) return -ENXIO;
/** * rpmsg_sendto() - send a message across to the remote processor, specify dst * @ept: the rpmsg endpoint * @data: payload of message * @len: length of payload * @dst: destination address * * This function sends @data of length @len to the remote @dst address. * The message will be sent to the remote processor which the @ept * endpoint belongs to, using @ept's address as source. * In case there are no TX buffers available, the function will block until * one becomes available, or a timeout of 15 seconds elapses. When the latter * happens, -ERESTARTSYS is returned. * * Can only be called from process context (for now). * * Return: 0 on success and an appropriate error value on failure.
*/ int rpmsg_sendto(struct rpmsg_endpoint *ept, void *data, int len, u32 dst)
{ if (WARN_ON(!ept)) return -EINVAL; if (!ept->ops->sendto) return -ENXIO;
/** * rpmsg_trysend() - send a message across to the remote processor * @ept: the rpmsg endpoint * @data: payload of message * @len: length of payload * * This function sends @data of length @len on the @ept endpoint. * The message will be sent to the remote processor which the @ept * endpoint belongs to, using @ept's address as source and its associated * rpdev's address as destination. * In case there are no TX buffers available, the function will immediately * return -ENOMEM without waiting until one becomes available. * * Can only be called from process context (for now). * * Return: 0 on success and an appropriate error value on failure.
*/ int rpmsg_trysend(struct rpmsg_endpoint *ept, void *data, int len)
{ if (WARN_ON(!ept)) return -EINVAL; if (!ept->ops->trysend) return -ENXIO;
/** * rpmsg_trysendto() - send a message across to the remote processor, specify dst * @ept: the rpmsg endpoint * @data: payload of message * @len: length of payload * @dst: destination address * * This function sends @data of length @len to the remote @dst address. * The message will be sent to the remote processor which the @ept * endpoint belongs to, using @ept's address as source. * In case there are no TX buffers available, the function will immediately * return -ENOMEM without waiting until one becomes available. * * Can only be called from process context (for now). * * Return: 0 on success and an appropriate error value on failure.
*/ int rpmsg_trysendto(struct rpmsg_endpoint *ept, void *data, int len, u32 dst)
{ if (WARN_ON(!ept)) return -EINVAL; if (!ept->ops->trysendto) return -ENXIO;
/** * rpmsg_set_flow_control() - request remote to pause/resume transmission * @ept: the rpmsg endpoint * @pause: pause transmission * @dst: destination address of the endpoint * * Return: 0 on success and an appropriate error value on failure.
*/ int rpmsg_set_flow_control(struct rpmsg_endpoint *ept, bool pause, u32 dst)
{ if (WARN_ON(!ept)) return -EINVAL; if (!ept->ops->set_flow_control) return -EOPNOTSUPP;
/** * rpmsg_get_mtu() - get maximum transmission buffer size for sending message. * @ept: the rpmsg endpoint * * This function returns maximum buffer size available for a single outgoing message. * * Return: the maximum transmission size on success and an appropriate error * value on failure.
*/
ssize_t rpmsg_get_mtu(struct rpmsg_endpoint *ept)
{ if (WARN_ON(!ept)) return -EINVAL; if (!ept->ops->get_mtu) return -ENOTSUPP;
/* * match a rpmsg channel with a channel info struct. * this is used to make sure we're not creating rpmsg devices for channels * that already exist.
*/ staticint rpmsg_device_match(struct device *dev, constvoid *data)
{ conststruct rpmsg_channel_info *chinfo = data; struct rpmsg_device *rpdev = to_rpmsg_device(dev);
if (chinfo->src != RPMSG_ADDR_ANY && chinfo->src != rpdev->src) return 0;
if (chinfo->dst != RPMSG_ADDR_ANY && chinfo->dst != rpdev->dst) return 0;
if (strncmp(chinfo->name, rpdev->id.name, RPMSG_NAME_SIZE)) return 0;
/* rpmsg devices and drivers are matched using the service name */ staticinlineint rpmsg_id_match(conststruct rpmsg_device *rpdev, conststruct rpmsg_device_id *id)
{ return strncmp(id->name, rpdev->id.name, RPMSG_NAME_SIZE) == 0;
}
/* * when an rpmsg driver is probed with a channel, we seamlessly create * it an endpoint, binding its rx callback to a unique local rpmsg * address. * * if we need to, we also announce about this channel to the remote * processor (needed in case the driver is exposing an rpmsg service).
*/ staticint rpmsg_dev_probe(struct device *dev)
{ struct rpmsg_device *rpdev = to_rpmsg_device(dev); struct rpmsg_driver *rpdrv = to_rpmsg_driver(rpdev->dev.driver); struct rpmsg_channel_info chinfo = {}; struct rpmsg_endpoint *ept = NULL; int err;
err = dev_pm_domain_attach(dev, PD_FLAG_ATTACH_POWER_ON); if (err) goto out;
/* * A helper for registering rpmsg device with driver override and name. * Drivers should not be using it, but instead rpmsg_register_device().
*/ int rpmsg_register_device_override(struct rpmsg_device *rpdev, constchar *driver_override)
{ struct device *dev = &rpdev->dev; int ret;
if (driver_override)
strscpy_pad(rpdev->id.name, driver_override, RPMSG_NAME_SIZE);
int rpmsg_register_device(struct rpmsg_device *rpdev)
{ return rpmsg_register_device_override(rpdev, NULL);
}
EXPORT_SYMBOL(rpmsg_register_device);
/* * find an existing channel using its name + address properties, * and destroy it
*/ int rpmsg_unregister_device(struct device *parent, struct rpmsg_channel_info *chinfo)
{ struct device *dev;
dev = rpmsg_find_device(parent, chinfo); if (!dev) return -EINVAL;
/** * __register_rpmsg_driver() - register an rpmsg driver with the rpmsg bus * @rpdrv: pointer to a struct rpmsg_driver * @owner: owning module/driver * * Return: 0 on success, and an appropriate error value on failure.
*/ int __register_rpmsg_driver(struct rpmsg_driver *rpdrv, struct module *owner)
{
rpdrv->drv.bus = &rpmsg_bus;
rpdrv->drv.owner = owner; return driver_register(&rpdrv->drv);
}
EXPORT_SYMBOL(__register_rpmsg_driver);
/** * unregister_rpmsg_driver() - unregister an rpmsg driver from the rpmsg bus * @rpdrv: pointer to a struct rpmsg_driver * * Return: 0 on success, and an appropriate error value on failure.
*/ void unregister_rpmsg_driver(struct rpmsg_driver *rpdrv)
{
driver_unregister(&rpdrv->drv);
}
EXPORT_SYMBOL(unregister_rpmsg_driver);
staticint __init rpmsg_init(void)
{ int ret;
ret = class_register(&rpmsg_class); if (ret) {
pr_err("failed to register rpmsg class\n"); return ret;
}
ret = bus_register(&rpmsg_bus); if (ret) {
pr_err("failed to register rpmsg bus: %d\n", ret);
class_destroy(&rpmsg_class);
} return ret;
}
postcore_initcall(rpmsg_init);
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.