drivers/rpmsg: add rpmsg router support
Rpmsg Router is new rpmsg transport layer, it can router the rpmsg
messages to a cpu that not directly connected with local cpu by Rpmsg,
For the rpmsg services, it is as if there is a real Rpmsg Channel between
the local cpu and the remote cpu.
For examples, there are three cpus: ap, cp and audio.
ap and cp, ap and audio has share memory and be connected by Rpmsg VirtIO,
so ap and cp, ap and audio can communicate with each other by Rpmsg, but
cp can not communicate with audio direclty.
[cp] <-- rpmsg virtio --> [ap] <-- rpmsg virtio --> [audio]
With rpmsg router, the cp can communicate with audip by Rpmsg dereclty because
the router in ap will forward the rpmsg message from cp/audio to audio/cp, like
this:
+<----- rpmsg router --> hub <-- rpmsg router ------>+
| | |
[cp] <-- rpmsg virtio --> [ap] <-- rpmsg virtio --> [audio]
Signed-off-by: yintao <yintao@xiaomi.com>
2024-04-14 07:17:05 +02:00
|
|
|
/****************************************************************************
|
|
|
|
* drivers/rpmsg/rpmsg_router_edge.c
|
|
|
|
*
|
|
|
|
* Licensed to the Apache Software Foundation (ASF) under one or more
|
|
|
|
* contributor license agreements. See the NOTICE file distributed with
|
|
|
|
* this work for additional information regarding copyright ownership. The
|
|
|
|
* ASF licenses this file to you under the Apache License, Version 2.0 (the
|
|
|
|
* "License"); you may not use this file except in compliance with the
|
|
|
|
* License. You may obtain a copy of the License at
|
|
|
|
*
|
|
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
|
|
*
|
|
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
|
|
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
|
|
|
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
|
|
|
* License for the specific language governing permissions and limitations
|
|
|
|
* under the License.
|
|
|
|
*
|
|
|
|
****************************************************************************/
|
|
|
|
|
|
|
|
/****************************************************************************
|
|
|
|
* Included Files
|
|
|
|
****************************************************************************/
|
|
|
|
|
|
|
|
#include <nuttx/config.h>
|
|
|
|
|
|
|
|
#include <debug.h>
|
|
|
|
#include <stdio.h>
|
|
|
|
#include <stdint.h>
|
|
|
|
#include <string.h>
|
|
|
|
#include <stdbool.h>
|
|
|
|
|
|
|
|
#include <nuttx/kmalloc.h>
|
|
|
|
#include <rpmsg/rpmsg_internal.h>
|
|
|
|
|
|
|
|
#include "rpmsg_router.h"
|
|
|
|
|
|
|
|
/****************************************************************************
|
|
|
|
* Rpmsg-router Model:
|
|
|
|
*
|
|
|
|
* +------+ +------+ +------+
|
|
|
|
* | edge |<----->| hub |<----->| edge |
|
|
|
|
* +------+ +------+ +------+
|
|
|
|
*
|
|
|
|
* Description:
|
|
|
|
* edge CPUs (edge) are physically linked to the central router cpu (hub),
|
|
|
|
* edge CPUs' communication reply on hub cpu message forwarding.
|
|
|
|
*
|
|
|
|
****************************************************************************/
|
|
|
|
|
|
|
|
/****************************************************************************
|
|
|
|
* Pre-processor Definitions
|
|
|
|
****************************************************************************/
|
|
|
|
|
|
|
|
#define rpmsg_router_edge_from_rdev(d) \
|
|
|
|
metal_container_of(d, struct rpmsg_router_edge_s, rdev)
|
|
|
|
|
|
|
|
#define RPMSG_ROUTER_USER_NAME_SIZE \
|
|
|
|
(RPMSG_NAME_SIZE - RPMSG_ROUTER_NAME_PREFIX_LEN - RPMSG_ROUTER_CPUNAME_LEN)
|
|
|
|
|
|
|
|
/****************************************************************************
|
|
|
|
* Private Types
|
|
|
|
****************************************************************************/
|
|
|
|
|
|
|
|
struct rpmsg_router_edge_s
|
|
|
|
{
|
|
|
|
struct rpmsg_s rpmsg;
|
|
|
|
struct rpmsg_device rdev;
|
|
|
|
struct rpmsg_device *hubdev;
|
2024-07-02 12:31:52 +02:00
|
|
|
char name[RPMSG_NAME_SIZE];
|
2024-06-24 11:10:12 +02:00
|
|
|
char localcpu[RPMSG_ROUTER_CPUNAME_LEN];
|
drivers/rpmsg: add rpmsg router support
Rpmsg Router is new rpmsg transport layer, it can router the rpmsg
messages to a cpu that not directly connected with local cpu by Rpmsg,
For the rpmsg services, it is as if there is a real Rpmsg Channel between
the local cpu and the remote cpu.
For examples, there are three cpus: ap, cp and audio.
ap and cp, ap and audio has share memory and be connected by Rpmsg VirtIO,
so ap and cp, ap and audio can communicate with each other by Rpmsg, but
cp can not communicate with audio direclty.
[cp] <-- rpmsg virtio --> [ap] <-- rpmsg virtio --> [audio]
With rpmsg router, the cp can communicate with audip by Rpmsg dereclty because
the router in ap will forward the rpmsg message from cp/audio to audio/cp, like
this:
+<----- rpmsg router --> hub <-- rpmsg router ------>+
| | |
[cp] <-- rpmsg virtio --> [ap] <-- rpmsg virtio --> [audio]
Signed-off-by: yintao <yintao@xiaomi.com>
2024-04-14 07:17:05 +02:00
|
|
|
char remotecpu[RPMSG_ROUTER_CPUNAME_LEN];
|
|
|
|
|
|
|
|
/* Tx/Rx buffer size */
|
|
|
|
|
|
|
|
uint32_t tx_len;
|
|
|
|
uint32_t rx_len;
|
|
|
|
};
|
|
|
|
|
|
|
|
/****************************************************************************
|
|
|
|
* Private Function Prototypes
|
|
|
|
****************************************************************************/
|
|
|
|
|
2024-06-19 13:54:54 +02:00
|
|
|
static FAR const char *
|
|
|
|
rpmsg_router_edge_get_local_cpuname(FAR struct rpmsg_s *rpmsg);
|
drivers/rpmsg: add rpmsg router support
Rpmsg Router is new rpmsg transport layer, it can router the rpmsg
messages to a cpu that not directly connected with local cpu by Rpmsg,
For the rpmsg services, it is as if there is a real Rpmsg Channel between
the local cpu and the remote cpu.
For examples, there are three cpus: ap, cp and audio.
ap and cp, ap and audio has share memory and be connected by Rpmsg VirtIO,
so ap and cp, ap and audio can communicate with each other by Rpmsg, but
cp can not communicate with audio direclty.
[cp] <-- rpmsg virtio --> [ap] <-- rpmsg virtio --> [audio]
With rpmsg router, the cp can communicate with audip by Rpmsg dereclty because
the router in ap will forward the rpmsg message from cp/audio to audio/cp, like
this:
+<----- rpmsg router --> hub <-- rpmsg router ------>+
| | |
[cp] <-- rpmsg virtio --> [ap] <-- rpmsg virtio --> [audio]
Signed-off-by: yintao <yintao@xiaomi.com>
2024-04-14 07:17:05 +02:00
|
|
|
static FAR const char *
|
|
|
|
rpmsg_router_edge_get_cpuname(FAR struct rpmsg_s *rpmsg);
|
|
|
|
static int rpmsg_router_edge_get_tx_buffer_size(FAR struct rpmsg_s *rpmsg);
|
|
|
|
static int rpmsg_router_edge_get_rx_buffer_size(FAR struct rpmsg_s *rpmsg);
|
|
|
|
|
|
|
|
/****************************************************************************
|
|
|
|
* Private Data
|
|
|
|
****************************************************************************/
|
|
|
|
|
|
|
|
static const struct rpmsg_ops_s g_rpmsg_router_edge_ops =
|
|
|
|
{
|
|
|
|
NULL,
|
|
|
|
NULL,
|
|
|
|
NULL,
|
|
|
|
NULL,
|
|
|
|
NULL,
|
2024-06-19 13:54:54 +02:00
|
|
|
rpmsg_router_edge_get_local_cpuname,
|
drivers/rpmsg: add rpmsg router support
Rpmsg Router is new rpmsg transport layer, it can router the rpmsg
messages to a cpu that not directly connected with local cpu by Rpmsg,
For the rpmsg services, it is as if there is a real Rpmsg Channel between
the local cpu and the remote cpu.
For examples, there are three cpus: ap, cp and audio.
ap and cp, ap and audio has share memory and be connected by Rpmsg VirtIO,
so ap and cp, ap and audio can communicate with each other by Rpmsg, but
cp can not communicate with audio direclty.
[cp] <-- rpmsg virtio --> [ap] <-- rpmsg virtio --> [audio]
With rpmsg router, the cp can communicate with audip by Rpmsg dereclty because
the router in ap will forward the rpmsg message from cp/audio to audio/cp, like
this:
+<----- rpmsg router --> hub <-- rpmsg router ------>+
| | |
[cp] <-- rpmsg virtio --> [ap] <-- rpmsg virtio --> [audio]
Signed-off-by: yintao <yintao@xiaomi.com>
2024-04-14 07:17:05 +02:00
|
|
|
rpmsg_router_edge_get_cpuname,
|
|
|
|
rpmsg_router_edge_get_tx_buffer_size,
|
|
|
|
rpmsg_router_edge_get_rx_buffer_size,
|
|
|
|
};
|
|
|
|
|
|
|
|
/****************************************************************************
|
|
|
|
* Private Functions
|
|
|
|
****************************************************************************/
|
|
|
|
|
2024-06-19 13:54:54 +02:00
|
|
|
/****************************************************************************
|
|
|
|
* Name: rpmsg_router_edge_get_local_cpuname
|
|
|
|
****************************************************************************/
|
|
|
|
|
|
|
|
static FAR const char *
|
|
|
|
rpmsg_router_edge_get_local_cpuname(FAR struct rpmsg_s *rpmsg)
|
|
|
|
{
|
2024-06-24 11:10:12 +02:00
|
|
|
FAR struct rpmsg_router_edge_s *edge =
|
|
|
|
(FAR struct rpmsg_router_edge_s *)rpmsg;
|
|
|
|
|
|
|
|
return edge->localcpu;
|
2024-06-19 13:54:54 +02:00
|
|
|
}
|
|
|
|
|
drivers/rpmsg: add rpmsg router support
Rpmsg Router is new rpmsg transport layer, it can router the rpmsg
messages to a cpu that not directly connected with local cpu by Rpmsg,
For the rpmsg services, it is as if there is a real Rpmsg Channel between
the local cpu and the remote cpu.
For examples, there are three cpus: ap, cp and audio.
ap and cp, ap and audio has share memory and be connected by Rpmsg VirtIO,
so ap and cp, ap and audio can communicate with each other by Rpmsg, but
cp can not communicate with audio direclty.
[cp] <-- rpmsg virtio --> [ap] <-- rpmsg virtio --> [audio]
With rpmsg router, the cp can communicate with audip by Rpmsg dereclty because
the router in ap will forward the rpmsg message from cp/audio to audio/cp, like
this:
+<----- rpmsg router --> hub <-- rpmsg router ------>+
| | |
[cp] <-- rpmsg virtio --> [ap] <-- rpmsg virtio --> [audio]
Signed-off-by: yintao <yintao@xiaomi.com>
2024-04-14 07:17:05 +02:00
|
|
|
/****************************************************************************
|
|
|
|
* Name: rpmsg_router_edge_get_cpuname
|
|
|
|
****************************************************************************/
|
|
|
|
|
|
|
|
static FAR const char *
|
|
|
|
rpmsg_router_edge_get_cpuname(FAR struct rpmsg_s *rpmsg)
|
|
|
|
{
|
|
|
|
FAR struct rpmsg_router_edge_s *edge =
|
|
|
|
(FAR struct rpmsg_router_edge_s *)rpmsg;
|
|
|
|
|
|
|
|
return edge->remotecpu;
|
|
|
|
}
|
|
|
|
|
|
|
|
/****************************************************************************
|
|
|
|
* Name: rpmsg_router_edge_get_tx_buffer_size
|
|
|
|
****************************************************************************/
|
|
|
|
|
|
|
|
static int rpmsg_router_edge_get_tx_buffer_size(FAR struct rpmsg_s *rpmsg)
|
|
|
|
{
|
|
|
|
FAR struct rpmsg_router_edge_s *edge =
|
|
|
|
(FAR struct rpmsg_router_edge_s *)rpmsg;
|
|
|
|
|
|
|
|
return edge->tx_len;
|
|
|
|
}
|
|
|
|
|
|
|
|
/****************************************************************************
|
|
|
|
* Name: rpmsg_router_edge_get_rx_buffer_size
|
|
|
|
****************************************************************************/
|
|
|
|
|
|
|
|
static int rpmsg_router_edge_get_rx_buffer_size(FAR struct rpmsg_s *rpmsg)
|
|
|
|
{
|
|
|
|
FAR struct rpmsg_router_edge_s *edge =
|
|
|
|
(FAR struct rpmsg_router_edge_s *)rpmsg;
|
|
|
|
|
|
|
|
return edge->rx_len;
|
|
|
|
}
|
|
|
|
|
|
|
|
/****************************************************************************
|
|
|
|
* Name: rpmsg_router_edge_get_tx_payload_buffer
|
|
|
|
****************************************************************************/
|
|
|
|
|
|
|
|
static FAR void *
|
|
|
|
rpmsg_router_edge_get_tx_payload_buffer(FAR struct rpmsg_device *rdev,
|
|
|
|
FAR uint32_t *len, int wait)
|
|
|
|
{
|
|
|
|
FAR struct rpmsg_router_edge_s *edge = rpmsg_router_edge_from_rdev(rdev);
|
|
|
|
FAR struct rpmsg_device *hubdev = edge->hubdev;
|
|
|
|
FAR void *buf;
|
|
|
|
|
|
|
|
if (!hubdev->ops.get_tx_payload_buffer)
|
|
|
|
{
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
buf = hubdev->ops.get_tx_payload_buffer(hubdev, len, wait);
|
2024-06-18 13:40:33 +02:00
|
|
|
*len = edge->tx_len;
|
drivers/rpmsg: add rpmsg router support
Rpmsg Router is new rpmsg transport layer, it can router the rpmsg
messages to a cpu that not directly connected with local cpu by Rpmsg,
For the rpmsg services, it is as if there is a real Rpmsg Channel between
the local cpu and the remote cpu.
For examples, there are three cpus: ap, cp and audio.
ap and cp, ap and audio has share memory and be connected by Rpmsg VirtIO,
so ap and cp, ap and audio can communicate with each other by Rpmsg, but
cp can not communicate with audio direclty.
[cp] <-- rpmsg virtio --> [ap] <-- rpmsg virtio --> [audio]
With rpmsg router, the cp can communicate with audip by Rpmsg dereclty because
the router in ap will forward the rpmsg message from cp/audio to audio/cp, like
this:
+<----- rpmsg router --> hub <-- rpmsg router ------>+
| | |
[cp] <-- rpmsg virtio --> [ap] <-- rpmsg virtio --> [audio]
Signed-off-by: yintao <yintao@xiaomi.com>
2024-04-14 07:17:05 +02:00
|
|
|
return buf;
|
|
|
|
}
|
|
|
|
|
|
|
|
/****************************************************************************
|
|
|
|
* Name: rpmsg_router_edge_hold_rx_buffer
|
|
|
|
****************************************************************************/
|
|
|
|
|
|
|
|
static void rpmsg_router_edge_hold_rx_buffer(FAR struct rpmsg_device *rdev,
|
|
|
|
FAR void *rxbuf)
|
|
|
|
{
|
|
|
|
FAR struct rpmsg_router_edge_s *edge = rpmsg_router_edge_from_rdev(rdev);
|
|
|
|
FAR struct rpmsg_device *hubdev = edge->hubdev;
|
|
|
|
|
|
|
|
if (!hubdev->ops.hold_rx_buffer)
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
hubdev->ops.hold_rx_buffer(hubdev, rxbuf);
|
|
|
|
}
|
|
|
|
|
|
|
|
/****************************************************************************
|
|
|
|
* Name: rpmsg_router_edge_release_rx_buffer
|
|
|
|
****************************************************************************/
|
|
|
|
|
|
|
|
static void
|
|
|
|
rpmsg_router_edge_release_rx_buffer(FAR struct rpmsg_device *rdev,
|
|
|
|
FAR void *rxbuf)
|
|
|
|
{
|
|
|
|
struct rpmsg_router_edge_s *edge = rpmsg_router_edge_from_rdev(rdev);
|
|
|
|
struct rpmsg_device *hubdev = edge->hubdev;
|
|
|
|
|
|
|
|
if (!hubdev->ops.release_rx_buffer)
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
hubdev->ops.release_rx_buffer(hubdev, rxbuf);
|
|
|
|
}
|
|
|
|
|
|
|
|
/****************************************************************************
|
|
|
|
* Name: rpmsg_router_edge_release_tx_buffer
|
|
|
|
****************************************************************************/
|
|
|
|
|
|
|
|
static int rpmsg_router_edge_release_tx_buffer(FAR struct rpmsg_device *rdev,
|
|
|
|
FAR void *txbuf)
|
|
|
|
{
|
|
|
|
struct rpmsg_router_edge_s *edge = rpmsg_router_edge_from_rdev(rdev);
|
|
|
|
struct rpmsg_device *hubdev = edge->hubdev;
|
|
|
|
|
|
|
|
if (!hubdev->ops.release_tx_buffer)
|
|
|
|
{
|
|
|
|
return RPMSG_ERR_PERM;
|
|
|
|
}
|
|
|
|
|
|
|
|
return hubdev->ops.release_tx_buffer(hubdev, txbuf);
|
|
|
|
}
|
|
|
|
|
|
|
|
/****************************************************************************
|
|
|
|
* Name: rpmsg_router_edge_send_nocopy
|
|
|
|
****************************************************************************/
|
|
|
|
|
|
|
|
static int rpmsg_router_edge_send_nocopy(FAR struct rpmsg_device *rdev,
|
|
|
|
uint32_t src, uint32_t dst,
|
|
|
|
FAR const void *data, int len)
|
|
|
|
{
|
|
|
|
struct rpmsg_router_edge_s *edge = rpmsg_router_edge_from_rdev(rdev);
|
|
|
|
struct rpmsg_device *hubdev = edge->hubdev;
|
|
|
|
|
|
|
|
if (!hubdev->ops.send_offchannel_nocopy)
|
|
|
|
{
|
|
|
|
return RPMSG_ERR_PARAM;
|
|
|
|
}
|
|
|
|
|
|
|
|
return hubdev->ops.send_offchannel_nocopy(hubdev, src, dst, data, len);
|
|
|
|
}
|
|
|
|
|
|
|
|
/****************************************************************************
|
|
|
|
* Name: rpmsg_router_edge_cb
|
|
|
|
*
|
|
|
|
* Description:
|
|
|
|
* This is the callback function for edge core.
|
|
|
|
* It will receive data from real rpmsg channel by ept(r:cpu:name),
|
|
|
|
* and find the corresponding user ept, then processing data through
|
|
|
|
* the user ept callback.
|
|
|
|
*
|
|
|
|
* Parameters:
|
|
|
|
* ept - rpmsg_endpoint for communicating with router core (r:cpu:name)
|
|
|
|
* data - received data
|
|
|
|
* len - received data length
|
|
|
|
* src - source address
|
|
|
|
* priv - save user rpmsg_endpoint generally
|
|
|
|
*
|
|
|
|
* Returned Values:
|
|
|
|
* 0 on success; A negated errno value is returned on any failure.
|
|
|
|
*
|
|
|
|
****************************************************************************/
|
|
|
|
|
|
|
|
static int rpmsg_router_edge_cb(FAR struct rpmsg_endpoint *ept,
|
|
|
|
FAR void *data, size_t len,
|
|
|
|
uint32_t src, FAR void *priv)
|
|
|
|
{
|
|
|
|
FAR struct rpmsg_endpoint *usr_ept = priv;
|
|
|
|
|
|
|
|
if (!usr_ept)
|
|
|
|
{
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Processing data through the user ept callback */
|
|
|
|
|
|
|
|
return usr_ept->cb(usr_ept, data, len, src, usr_ept->priv);
|
|
|
|
}
|
|
|
|
|
|
|
|
/****************************************************************************
|
|
|
|
* Name: rpmsg_router_edge_bound
|
|
|
|
*
|
|
|
|
* Description:
|
|
|
|
* This is the callback function for edge core.
|
|
|
|
* It will be called when the edge core is bound to the router core
|
|
|
|
* by r:cpu:name, save the destination address of the edge core, and
|
|
|
|
* call the bound function of the user endpoint.
|
|
|
|
*
|
|
|
|
* Parameters:
|
|
|
|
* ept - rpmsg_endpoint for communicating with router core (r:cpu:name)
|
|
|
|
*
|
|
|
|
****************************************************************************/
|
|
|
|
|
|
|
|
static void rpmsg_router_edge_bound(FAR struct rpmsg_endpoint *ept)
|
|
|
|
{
|
|
|
|
FAR struct rpmsg_endpoint *usr_ept = ept->priv;
|
|
|
|
|
|
|
|
if (!usr_ept)
|
|
|
|
{
|
|
|
|
rpmsgerr("Try to get user ept failed.\n");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
usr_ept->dest_addr = ept->dest_addr;
|
|
|
|
if (usr_ept->ns_bound_cb)
|
|
|
|
{
|
|
|
|
usr_ept->ns_bound_cb(usr_ept);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/****************************************************************************
|
|
|
|
* Name: rpmsg_router_edge_unbind
|
|
|
|
*
|
|
|
|
* Description:
|
|
|
|
* This is the unbind callback function for edge core.
|
|
|
|
*
|
|
|
|
* Parameters:
|
|
|
|
* ept - rpmsg_endpoint for communicating with router core (r:cpu:name)
|
|
|
|
*
|
|
|
|
****************************************************************************/
|
|
|
|
|
|
|
|
static void rpmsg_router_edge_unbind(FAR struct rpmsg_endpoint *ept)
|
|
|
|
{
|
|
|
|
FAR struct rpmsg_endpoint *usr_ept = ept->priv;
|
|
|
|
|
|
|
|
if (!usr_ept)
|
|
|
|
{
|
|
|
|
rpmsgerr("Try to get user ept failed.\n");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (usr_ept->ns_unbind_cb)
|
|
|
|
{
|
|
|
|
usr_ept->ns_unbind_cb(usr_ept);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/****************************************************************************
|
|
|
|
* Name: rpmsg_router_edge_release
|
|
|
|
****************************************************************************/
|
|
|
|
|
|
|
|
static void rpmsg_router_edge_release(FAR struct rpmsg_endpoint *ept)
|
|
|
|
{
|
|
|
|
kmm_free(ept);
|
|
|
|
}
|
|
|
|
|
|
|
|
/****************************************************************************
|
|
|
|
* Name: rpmsg_router_edge_send_offchannel_raw
|
|
|
|
*
|
|
|
|
* Description:
|
|
|
|
* This function sends normal rpmsg message or ns message to remote device.
|
|
|
|
* If the destination address is RPMSG_NS_EPT_ADDR, it will create a new
|
|
|
|
* endpoint(r:cpu:name) for real communication, and save the user endpoint
|
|
|
|
* information in the private field of the new endpoint.
|
|
|
|
*
|
|
|
|
* Parameters:
|
|
|
|
* rdev - rpmsg_device for router core
|
|
|
|
* src - source address
|
|
|
|
* dst - destination address
|
|
|
|
* data - data to send
|
|
|
|
* len - data length
|
|
|
|
* wait - boolean, wait or not for buffer to become available
|
|
|
|
*
|
|
|
|
* Returned Values:
|
|
|
|
* size of data sent or negative value for failure.
|
|
|
|
*
|
|
|
|
****************************************************************************/
|
|
|
|
|
|
|
|
static int
|
|
|
|
rpmsg_router_edge_send_offchannel_raw(FAR struct rpmsg_device *rdev,
|
|
|
|
uint32_t src, uint32_t dst,
|
|
|
|
FAR const void *data,
|
|
|
|
int len, int wait)
|
|
|
|
{
|
|
|
|
FAR struct rpmsg_router_edge_s *edge = rpmsg_router_edge_from_rdev(rdev);
|
|
|
|
FAR struct rpmsg_ns_msg *ns_msg = (FAR struct rpmsg_ns_msg *)data;
|
|
|
|
FAR struct rpmsg_device *hubdev = edge->hubdev;
|
|
|
|
FAR struct rpmsg_endpoint *usr_ept;
|
|
|
|
FAR struct rpmsg_endpoint *ept;
|
|
|
|
char name[RPMSG_ROUTER_USER_NAME_SIZE];
|
|
|
|
int ret;
|
|
|
|
|
|
|
|
/* Send normal rpmsg "message" to remote device */
|
|
|
|
|
|
|
|
if (dst != RPMSG_NS_EPT_ADDR)
|
|
|
|
{
|
|
|
|
if (!hubdev->ops.send_offchannel_raw)
|
|
|
|
{
|
|
|
|
return RPMSG_ERR_PARAM;
|
|
|
|
}
|
|
|
|
|
|
|
|
return hubdev->ops.send_offchannel_raw(hubdev, src,
|
|
|
|
dst, data, len, wait);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Try to get user ept firstly */
|
|
|
|
|
|
|
|
metal_mutex_acquire(&rdev->lock);
|
|
|
|
usr_ept = rpmsg_get_endpoint(rdev, ns_msg->name, src, dst);
|
|
|
|
metal_mutex_release(&rdev->lock);
|
|
|
|
if (!usr_ept)
|
|
|
|
{
|
|
|
|
rpmsgerr("Try to get user ept failed.\n");
|
|
|
|
return RPMSG_ERR_PARAM;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Set hub endpoint name(r:cpu:name) for real communication */
|
|
|
|
|
|
|
|
strlcpy(name, ns_msg->name, sizeof(name));
|
|
|
|
snprintf(ns_msg->name, sizeof(ns_msg->name),
|
|
|
|
RPMSG_ROUTER_NAME_PREFIX"%s:%s", edge->remotecpu, name);
|
|
|
|
|
|
|
|
if (ns_msg->flags == RPMSG_NS_DESTROY)
|
|
|
|
{
|
|
|
|
/* Processing RPMSG_NS_DESTROY message */
|
|
|
|
|
|
|
|
metal_mutex_acquire(&hubdev->lock);
|
|
|
|
ept = rpmsg_get_endpoint(hubdev, ns_msg->name,
|
|
|
|
RPMSG_ADDR_ANY, usr_ept->dest_addr);
|
|
|
|
metal_mutex_release(&hubdev->lock);
|
|
|
|
if (!ept)
|
|
|
|
{
|
|
|
|
rpmsgerr("Try to get router endpoint (r:ept) failed.\n");
|
|
|
|
return RPMSG_ERR_PARAM;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Destroy endpoint(r:cpu:name) of real communication */
|
|
|
|
|
|
|
|
rpmsg_destroy_ept(ept);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
/* Processing RPMSG_NS_CREATE or RPMSG_NS_CREATE_ACK message */
|
|
|
|
|
|
|
|
ept = kmm_zalloc(sizeof(*ept));
|
|
|
|
if (!ept)
|
|
|
|
{
|
|
|
|
return -ENOMEM;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Save user endpoint */
|
|
|
|
|
|
|
|
ept->priv = usr_ept;
|
|
|
|
ept->ns_bound_cb = rpmsg_router_edge_bound;
|
|
|
|
ept->release_cb = rpmsg_router_edge_release;
|
|
|
|
|
|
|
|
/* Create endpoint (r:cpu:name) for real communication */
|
|
|
|
|
|
|
|
ret = rpmsg_create_ept(ept, hubdev, ns_msg->name,
|
|
|
|
RPMSG_ADDR_ANY, RPMSG_ADDR_ANY,
|
|
|
|
rpmsg_router_edge_cb,
|
|
|
|
rpmsg_router_edge_unbind);
|
|
|
|
if (ret < 0)
|
|
|
|
{
|
|
|
|
rpmsgerr("Create router endpoint failed: %d\n", ret);
|
|
|
|
kmm_free(ept);
|
|
|
|
}
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/****************************************************************************
|
|
|
|
* Name: rpmsg_router_edge_match
|
|
|
|
*
|
|
|
|
* Description:
|
|
|
|
* This function is used to match the edge core device.
|
|
|
|
* rpmsg_router_edge_bind will be called if the device is matched.
|
|
|
|
*
|
|
|
|
* Parameters:
|
|
|
|
* rdev - real rpmsg device
|
|
|
|
* priv - rpmsg router device for edge core
|
|
|
|
* name - endpoint name (r:cpu:name)
|
|
|
|
* dest - destination address
|
|
|
|
*
|
|
|
|
* Returned Values:
|
|
|
|
* true on success; false on failure.
|
|
|
|
*
|
|
|
|
****************************************************************************/
|
|
|
|
|
|
|
|
static bool rpmsg_router_edge_match(FAR struct rpmsg_device *rdev,
|
|
|
|
FAR void *priv, FAR const char *name,
|
|
|
|
uint32_t dest)
|
|
|
|
{
|
|
|
|
FAR struct rpmsg_router_edge_s *edge = priv;
|
|
|
|
|
|
|
|
if (strncmp(name, RPMSG_ROUTER_NAME_PREFIX, RPMSG_ROUTER_NAME_PREFIX_LEN))
|
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
return !strncmp(name + RPMSG_ROUTER_NAME_PREFIX_LEN, edge->remotecpu,
|
|
|
|
strlen(edge->remotecpu));
|
|
|
|
}
|
|
|
|
|
|
|
|
/****************************************************************************
|
|
|
|
* Name: rpmsg_router_edge_bind
|
|
|
|
*
|
|
|
|
* Description:
|
|
|
|
* This function is used to bind the edge core device.
|
|
|
|
* It will try to find rpmsg_user_ns_bind_cb by user ept name.
|
|
|
|
*
|
|
|
|
* Parameters:
|
|
|
|
* rdev - real rpmsg device
|
|
|
|
* priv - rpmsg router device for edge core
|
|
|
|
* name - endpoint name (r:cpu:name)
|
|
|
|
* dest - destination address
|
|
|
|
*
|
|
|
|
****************************************************************************/
|
|
|
|
|
|
|
|
static void rpmsg_router_edge_bind(FAR struct rpmsg_device *rdev,
|
|
|
|
FAR void *priv, FAR const char *name,
|
|
|
|
uint32_t dest)
|
|
|
|
{
|
|
|
|
FAR struct rpmsg_router_edge_s *edge = priv;
|
|
|
|
FAR struct rpmsg_device *edgedev = &edge->rdev;
|
|
|
|
|
|
|
|
edgedev->ns_bind_cb(edgedev,
|
|
|
|
name + RPMSG_ROUTER_NAME_PREFIX_LEN +
|
|
|
|
strlen(edge->remotecpu) + 1, dest);
|
|
|
|
}
|
|
|
|
|
|
|
|
/****************************************************************************
|
2024-07-02 12:31:52 +02:00
|
|
|
* Name: rpmsg_router_edge_destroy
|
drivers/rpmsg: add rpmsg router support
Rpmsg Router is new rpmsg transport layer, it can router the rpmsg
messages to a cpu that not directly connected with local cpu by Rpmsg,
For the rpmsg services, it is as if there is a real Rpmsg Channel between
the local cpu and the remote cpu.
For examples, there are three cpus: ap, cp and audio.
ap and cp, ap and audio has share memory and be connected by Rpmsg VirtIO,
so ap and cp, ap and audio can communicate with each other by Rpmsg, but
cp can not communicate with audio direclty.
[cp] <-- rpmsg virtio --> [ap] <-- rpmsg virtio --> [audio]
With rpmsg router, the cp can communicate with audip by Rpmsg dereclty because
the router in ap will forward the rpmsg message from cp/audio to audio/cp, like
this:
+<----- rpmsg router --> hub <-- rpmsg router ------>+
| | |
[cp] <-- rpmsg virtio --> [ap] <-- rpmsg virtio --> [audio]
Signed-off-by: yintao <yintao@xiaomi.com>
2024-04-14 07:17:05 +02:00
|
|
|
*
|
|
|
|
* Description:
|
2024-07-02 12:31:52 +02:00
|
|
|
* This function is used to destroy the edge core device.
|
drivers/rpmsg: add rpmsg router support
Rpmsg Router is new rpmsg transport layer, it can router the rpmsg
messages to a cpu that not directly connected with local cpu by Rpmsg,
For the rpmsg services, it is as if there is a real Rpmsg Channel between
the local cpu and the remote cpu.
For examples, there are three cpus: ap, cp and audio.
ap and cp, ap and audio has share memory and be connected by Rpmsg VirtIO,
so ap and cp, ap and audio can communicate with each other by Rpmsg, but
cp can not communicate with audio direclty.
[cp] <-- rpmsg virtio --> [ap] <-- rpmsg virtio --> [audio]
With rpmsg router, the cp can communicate with audip by Rpmsg dereclty because
the router in ap will forward the rpmsg message from cp/audio to audio/cp, like
this:
+<----- rpmsg router --> hub <-- rpmsg router ------>+
| | |
[cp] <-- rpmsg virtio --> [ap] <-- rpmsg virtio --> [audio]
Signed-off-by: yintao <yintao@xiaomi.com>
2024-04-14 07:17:05 +02:00
|
|
|
*
|
|
|
|
* Parameters:
|
2024-07-02 12:31:52 +02:00
|
|
|
* edge - rpmsg router edge device
|
|
|
|
*
|
|
|
|
****************************************************************************/
|
|
|
|
|
|
|
|
static void rpmsg_router_edge_destroy(FAR struct rpmsg_router_edge_s *edge)
|
|
|
|
{
|
|
|
|
rpmsg_unregister_callback(edge, NULL, NULL,
|
|
|
|
rpmsg_router_edge_match,
|
|
|
|
rpmsg_router_edge_bind);
|
|
|
|
rpmsg_unregister(edge->name, &edge->rpmsg);
|
|
|
|
rpmsg_device_destory(&edge->rpmsg);
|
|
|
|
kmm_free(edge);
|
|
|
|
}
|
|
|
|
|
|
|
|
/****************************************************************************
|
|
|
|
* Name: rpmsg_router_edge_create
|
|
|
|
*
|
|
|
|
* Description:
|
|
|
|
* This function is used to create the edge core device.
|
|
|
|
*
|
|
|
|
* Parameters:
|
|
|
|
* hubdev - rpmsg device for router hub
|
|
|
|
* msg - sync message from router hub
|
|
|
|
* remotecpu - remote edge cpu name
|
drivers/rpmsg: add rpmsg router support
Rpmsg Router is new rpmsg transport layer, it can router the rpmsg
messages to a cpu that not directly connected with local cpu by Rpmsg,
For the rpmsg services, it is as if there is a real Rpmsg Channel between
the local cpu and the remote cpu.
For examples, there are three cpus: ap, cp and audio.
ap and cp, ap and audio has share memory and be connected by Rpmsg VirtIO,
so ap and cp, ap and audio can communicate with each other by Rpmsg, but
cp can not communicate with audio direclty.
[cp] <-- rpmsg virtio --> [ap] <-- rpmsg virtio --> [audio]
With rpmsg router, the cp can communicate with audip by Rpmsg dereclty because
the router in ap will forward the rpmsg message from cp/audio to audio/cp, like
this:
+<----- rpmsg router --> hub <-- rpmsg router ------>+
| | |
[cp] <-- rpmsg virtio --> [ap] <-- rpmsg virtio --> [audio]
Signed-off-by: yintao <yintao@xiaomi.com>
2024-04-14 07:17:05 +02:00
|
|
|
*
|
|
|
|
* Returned Values:
|
2024-07-02 12:31:52 +02:00
|
|
|
* edge device on success; NULL on failure.
|
drivers/rpmsg: add rpmsg router support
Rpmsg Router is new rpmsg transport layer, it can router the rpmsg
messages to a cpu that not directly connected with local cpu by Rpmsg,
For the rpmsg services, it is as if there is a real Rpmsg Channel between
the local cpu and the remote cpu.
For examples, there are three cpus: ap, cp and audio.
ap and cp, ap and audio has share memory and be connected by Rpmsg VirtIO,
so ap and cp, ap and audio can communicate with each other by Rpmsg, but
cp can not communicate with audio direclty.
[cp] <-- rpmsg virtio --> [ap] <-- rpmsg virtio --> [audio]
With rpmsg router, the cp can communicate with audip by Rpmsg dereclty because
the router in ap will forward the rpmsg message from cp/audio to audio/cp, like
this:
+<----- rpmsg router --> hub <-- rpmsg router ------>+
| | |
[cp] <-- rpmsg virtio --> [ap] <-- rpmsg virtio --> [audio]
Signed-off-by: yintao <yintao@xiaomi.com>
2024-04-14 07:17:05 +02:00
|
|
|
*
|
|
|
|
****************************************************************************/
|
|
|
|
|
2024-07-02 12:31:52 +02:00
|
|
|
static FAR struct rpmsg_router_edge_s *
|
|
|
|
rpmsg_router_edge_create(FAR struct rpmsg_device *hubdev,
|
|
|
|
FAR struct rpmsg_router_s *msg,
|
|
|
|
FAR const char *remotecpu)
|
drivers/rpmsg: add rpmsg router support
Rpmsg Router is new rpmsg transport layer, it can router the rpmsg
messages to a cpu that not directly connected with local cpu by Rpmsg,
For the rpmsg services, it is as if there is a real Rpmsg Channel between
the local cpu and the remote cpu.
For examples, there are three cpus: ap, cp and audio.
ap and cp, ap and audio has share memory and be connected by Rpmsg VirtIO,
so ap and cp, ap and audio can communicate with each other by Rpmsg, but
cp can not communicate with audio direclty.
[cp] <-- rpmsg virtio --> [ap] <-- rpmsg virtio --> [audio]
With rpmsg router, the cp can communicate with audip by Rpmsg dereclty because
the router in ap will forward the rpmsg message from cp/audio to audio/cp, like
this:
+<----- rpmsg router --> hub <-- rpmsg router ------>+
| | |
[cp] <-- rpmsg virtio --> [ap] <-- rpmsg virtio --> [audio]
Signed-off-by: yintao <yintao@xiaomi.com>
2024-04-14 07:17:05 +02:00
|
|
|
{
|
|
|
|
FAR struct rpmsg_router_edge_s *edge;
|
|
|
|
FAR struct rpmsg_device *rdev;
|
|
|
|
int ret;
|
|
|
|
|
2024-07-02 12:31:52 +02:00
|
|
|
/* Create the router edge device */
|
|
|
|
|
drivers/rpmsg: add rpmsg router support
Rpmsg Router is new rpmsg transport layer, it can router the rpmsg
messages to a cpu that not directly connected with local cpu by Rpmsg,
For the rpmsg services, it is as if there is a real Rpmsg Channel between
the local cpu and the remote cpu.
For examples, there are three cpus: ap, cp and audio.
ap and cp, ap and audio has share memory and be connected by Rpmsg VirtIO,
so ap and cp, ap and audio can communicate with each other by Rpmsg, but
cp can not communicate with audio direclty.
[cp] <-- rpmsg virtio --> [ap] <-- rpmsg virtio --> [audio]
With rpmsg router, the cp can communicate with audip by Rpmsg dereclty because
the router in ap will forward the rpmsg message from cp/audio to audio/cp, like
this:
+<----- rpmsg router --> hub <-- rpmsg router ------>+
| | |
[cp] <-- rpmsg virtio --> [ap] <-- rpmsg virtio --> [audio]
Signed-off-by: yintao <yintao@xiaomi.com>
2024-04-14 07:17:05 +02:00
|
|
|
edge = kmm_zalloc(sizeof(*edge));
|
|
|
|
if (!edge)
|
|
|
|
{
|
2024-07-02 12:31:52 +02:00
|
|
|
return NULL;
|
drivers/rpmsg: add rpmsg router support
Rpmsg Router is new rpmsg transport layer, it can router the rpmsg
messages to a cpu that not directly connected with local cpu by Rpmsg,
For the rpmsg services, it is as if there is a real Rpmsg Channel between
the local cpu and the remote cpu.
For examples, there are three cpus: ap, cp and audio.
ap and cp, ap and audio has share memory and be connected by Rpmsg VirtIO,
so ap and cp, ap and audio can communicate with each other by Rpmsg, but
cp can not communicate with audio direclty.
[cp] <-- rpmsg virtio --> [ap] <-- rpmsg virtio --> [audio]
With rpmsg router, the cp can communicate with audip by Rpmsg dereclty because
the router in ap will forward the rpmsg message from cp/audio to audio/cp, like
this:
+<----- rpmsg router --> hub <-- rpmsg router ------>+
| | |
[cp] <-- rpmsg virtio --> [ap] <-- rpmsg virtio --> [audio]
Signed-off-by: yintao <yintao@xiaomi.com>
2024-04-14 07:17:05 +02:00
|
|
|
}
|
|
|
|
|
2024-07-02 12:31:52 +02:00
|
|
|
strlcpy(edge->remotecpu, remotecpu, sizeof(edge->remotecpu));
|
2024-06-24 11:10:12 +02:00
|
|
|
strlcpy(edge->localcpu, msg->cpuname, sizeof(edge->localcpu));
|
drivers/rpmsg: add rpmsg router support
Rpmsg Router is new rpmsg transport layer, it can router the rpmsg
messages to a cpu that not directly connected with local cpu by Rpmsg,
For the rpmsg services, it is as if there is a real Rpmsg Channel between
the local cpu and the remote cpu.
For examples, there are three cpus: ap, cp and audio.
ap and cp, ap and audio has share memory and be connected by Rpmsg VirtIO,
so ap and cp, ap and audio can communicate with each other by Rpmsg, but
cp can not communicate with audio direclty.
[cp] <-- rpmsg virtio --> [ap] <-- rpmsg virtio --> [audio]
With rpmsg router, the cp can communicate with audip by Rpmsg dereclty because
the router in ap will forward the rpmsg message from cp/audio to audio/cp, like
this:
+<----- rpmsg router --> hub <-- rpmsg router ------>+
| | |
[cp] <-- rpmsg virtio --> [ap] <-- rpmsg virtio --> [audio]
Signed-off-by: yintao <yintao@xiaomi.com>
2024-04-14 07:17:05 +02:00
|
|
|
edge->rx_len = msg->rx_len;
|
|
|
|
edge->tx_len = msg->tx_len;
|
2024-07-02 12:31:52 +02:00
|
|
|
edge->hubdev = hubdev;
|
drivers/rpmsg: add rpmsg router support
Rpmsg Router is new rpmsg transport layer, it can router the rpmsg
messages to a cpu that not directly connected with local cpu by Rpmsg,
For the rpmsg services, it is as if there is a real Rpmsg Channel between
the local cpu and the remote cpu.
For examples, there are three cpus: ap, cp and audio.
ap and cp, ap and audio has share memory and be connected by Rpmsg VirtIO,
so ap and cp, ap and audio can communicate with each other by Rpmsg, but
cp can not communicate with audio direclty.
[cp] <-- rpmsg virtio --> [ap] <-- rpmsg virtio --> [audio]
With rpmsg router, the cp can communicate with audip by Rpmsg dereclty because
the router in ap will forward the rpmsg message from cp/audio to audio/cp, like
this:
+<----- rpmsg router --> hub <-- rpmsg router ------>+
| | |
[cp] <-- rpmsg virtio --> [ap] <-- rpmsg virtio --> [audio]
Signed-off-by: yintao <yintao@xiaomi.com>
2024-04-14 07:17:05 +02:00
|
|
|
|
|
|
|
/* Initialize router rpmsg device */
|
|
|
|
|
|
|
|
rdev = &edge->rdev;
|
|
|
|
metal_mutex_init(&rdev->lock);
|
|
|
|
rdev->ns_bind_cb = rpmsg_ns_bind;
|
|
|
|
rdev->ns_unbind_cb = rpmsg_ns_unbind;
|
|
|
|
rdev->ops.hold_rx_buffer = rpmsg_router_edge_hold_rx_buffer;
|
|
|
|
rdev->ops.release_rx_buffer = rpmsg_router_edge_release_rx_buffer;
|
|
|
|
rdev->ops.release_tx_buffer = rpmsg_router_edge_release_tx_buffer;
|
|
|
|
rdev->ops.send_offchannel_nocopy = rpmsg_router_edge_send_nocopy;
|
|
|
|
rdev->ops.send_offchannel_raw = rpmsg_router_edge_send_offchannel_raw;
|
|
|
|
rdev->ops.get_tx_payload_buffer = rpmsg_router_edge_get_tx_payload_buffer;
|
|
|
|
|
|
|
|
metal_list_init(&rdev->endpoints);
|
|
|
|
rdev->support_ack = true;
|
|
|
|
rdev->support_ns = true;
|
|
|
|
|
|
|
|
/* Register rpmsg for edge core */
|
|
|
|
|
2024-07-02 12:31:52 +02:00
|
|
|
snprintf(edge->name, sizeof(edge->name), "/dev/rpmsg/%s", edge->remotecpu);
|
|
|
|
ret = rpmsg_register(edge->name, &edge->rpmsg, &g_rpmsg_router_edge_ops);
|
drivers/rpmsg: add rpmsg router support
Rpmsg Router is new rpmsg transport layer, it can router the rpmsg
messages to a cpu that not directly connected with local cpu by Rpmsg,
For the rpmsg services, it is as if there is a real Rpmsg Channel between
the local cpu and the remote cpu.
For examples, there are three cpus: ap, cp and audio.
ap and cp, ap and audio has share memory and be connected by Rpmsg VirtIO,
so ap and cp, ap and audio can communicate with each other by Rpmsg, but
cp can not communicate with audio direclty.
[cp] <-- rpmsg virtio --> [ap] <-- rpmsg virtio --> [audio]
With rpmsg router, the cp can communicate with audip by Rpmsg dereclty because
the router in ap will forward the rpmsg message from cp/audio to audio/cp, like
this:
+<----- rpmsg router --> hub <-- rpmsg router ------>+
| | |
[cp] <-- rpmsg virtio --> [ap] <-- rpmsg virtio --> [audio]
Signed-off-by: yintao <yintao@xiaomi.com>
2024-04-14 07:17:05 +02:00
|
|
|
if (ret < 0)
|
|
|
|
{
|
|
|
|
rpmsgerr("rpmsg_register failed: %d\n", ret);
|
|
|
|
goto free;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Register callback for edge core */
|
|
|
|
|
|
|
|
ret = rpmsg_register_callback(edge, NULL, NULL,
|
|
|
|
rpmsg_router_edge_match,
|
|
|
|
rpmsg_router_edge_bind);
|
|
|
|
|
|
|
|
if (ret < 0)
|
|
|
|
{
|
|
|
|
rpmsgerr("Register rpmsg callback failed: %d\n", ret);
|
|
|
|
goto unregister;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Broadcast device_created to all registers */
|
|
|
|
|
|
|
|
rpmsg_device_created(&edge->rpmsg);
|
2024-07-02 12:31:52 +02:00
|
|
|
return edge;
|
drivers/rpmsg: add rpmsg router support
Rpmsg Router is new rpmsg transport layer, it can router the rpmsg
messages to a cpu that not directly connected with local cpu by Rpmsg,
For the rpmsg services, it is as if there is a real Rpmsg Channel between
the local cpu and the remote cpu.
For examples, there are three cpus: ap, cp and audio.
ap and cp, ap and audio has share memory and be connected by Rpmsg VirtIO,
so ap and cp, ap and audio can communicate with each other by Rpmsg, but
cp can not communicate with audio direclty.
[cp] <-- rpmsg virtio --> [ap] <-- rpmsg virtio --> [audio]
With rpmsg router, the cp can communicate with audip by Rpmsg dereclty because
the router in ap will forward the rpmsg message from cp/audio to audio/cp, like
this:
+<----- rpmsg router --> hub <-- rpmsg router ------>+
| | |
[cp] <-- rpmsg virtio --> [ap] <-- rpmsg virtio --> [audio]
Signed-off-by: yintao <yintao@xiaomi.com>
2024-04-14 07:17:05 +02:00
|
|
|
|
|
|
|
unregister:
|
2024-07-02 12:31:52 +02:00
|
|
|
rpmsg_unregister(edge->name, &edge->rpmsg);
|
drivers/rpmsg: add rpmsg router support
Rpmsg Router is new rpmsg transport layer, it can router the rpmsg
messages to a cpu that not directly connected with local cpu by Rpmsg,
For the rpmsg services, it is as if there is a real Rpmsg Channel between
the local cpu and the remote cpu.
For examples, there are three cpus: ap, cp and audio.
ap and cp, ap and audio has share memory and be connected by Rpmsg VirtIO,
so ap and cp, ap and audio can communicate with each other by Rpmsg, but
cp can not communicate with audio direclty.
[cp] <-- rpmsg virtio --> [ap] <-- rpmsg virtio --> [audio]
With rpmsg router, the cp can communicate with audip by Rpmsg dereclty because
the router in ap will forward the rpmsg message from cp/audio to audio/cp, like
this:
+<----- rpmsg router --> hub <-- rpmsg router ------>+
| | |
[cp] <-- rpmsg virtio --> [ap] <-- rpmsg virtio --> [audio]
Signed-off-by: yintao <yintao@xiaomi.com>
2024-04-14 07:17:05 +02:00
|
|
|
free:
|
|
|
|
kmm_free(edge);
|
2024-07-02 12:31:52 +02:00
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
/****************************************************************************
|
|
|
|
* Name: rpmsg_router_cb
|
|
|
|
*
|
|
|
|
* Description:
|
|
|
|
* This function is used to receive sync message from router core,
|
|
|
|
* and create or destroy the edge core device.
|
|
|
|
*
|
|
|
|
* Parameters:
|
|
|
|
* ept - endpoint for synchronizing ready messages
|
|
|
|
* data - received data
|
|
|
|
* len - received data length
|
|
|
|
* src - source address
|
|
|
|
* priv - private data
|
|
|
|
*
|
|
|
|
* Returned Values:
|
|
|
|
* 0 on success; A negated errno value is returned on any failure.
|
|
|
|
*
|
|
|
|
****************************************************************************/
|
|
|
|
|
|
|
|
static int rpmsg_router_cb(FAR struct rpmsg_endpoint *ept,
|
|
|
|
FAR void *data, size_t len,
|
|
|
|
uint32_t src, FAR void *priv)
|
|
|
|
{
|
|
|
|
FAR struct rpmsg_router_s *msg = data;
|
|
|
|
FAR struct rpmsg_router_edge_s *edge;
|
|
|
|
|
|
|
|
/* Destroy the router edge device */
|
|
|
|
|
|
|
|
if (msg->cmd == RPMSG_ROUTER_DESTROY)
|
|
|
|
{
|
|
|
|
edge = ept->priv;
|
|
|
|
|
|
|
|
if (edge)
|
|
|
|
{
|
|
|
|
rpmsg_router_edge_destroy(edge);
|
|
|
|
ept->priv = NULL;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
return -EINVAL;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Create the router edge device */
|
|
|
|
|
|
|
|
edge = rpmsg_router_edge_create(ept->rdev, msg,
|
|
|
|
ept->name + RPMSG_ROUTER_NAME_LEN);
|
|
|
|
if (!edge)
|
|
|
|
{
|
|
|
|
return -ENODEV;
|
|
|
|
}
|
|
|
|
|
|
|
|
ept->priv = edge;
|
|
|
|
return 0;
|
drivers/rpmsg: add rpmsg router support
Rpmsg Router is new rpmsg transport layer, it can router the rpmsg
messages to a cpu that not directly connected with local cpu by Rpmsg,
For the rpmsg services, it is as if there is a real Rpmsg Channel between
the local cpu and the remote cpu.
For examples, there are three cpus: ap, cp and audio.
ap and cp, ap and audio has share memory and be connected by Rpmsg VirtIO,
so ap and cp, ap and audio can communicate with each other by Rpmsg, but
cp can not communicate with audio direclty.
[cp] <-- rpmsg virtio --> [ap] <-- rpmsg virtio --> [audio]
With rpmsg router, the cp can communicate with audip by Rpmsg dereclty because
the router in ap will forward the rpmsg message from cp/audio to audio/cp, like
this:
+<----- rpmsg router --> hub <-- rpmsg router ------>+
| | |
[cp] <-- rpmsg virtio --> [ap] <-- rpmsg virtio --> [audio]
Signed-off-by: yintao <yintao@xiaomi.com>
2024-04-14 07:17:05 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/****************************************************************************
|
|
|
|
* Name: rpmsg_router_unbind
|
|
|
|
*
|
|
|
|
* Description:
|
|
|
|
* This function is used to destroy the sync endpoint
|
|
|
|
* when another edge core is disconnected.
|
|
|
|
*
|
|
|
|
* Parameters:
|
|
|
|
* ept - rpmsg endpoint for synchronizing message.
|
|
|
|
*
|
|
|
|
****************************************************************************/
|
|
|
|
|
|
|
|
static void rpmsg_router_unbind(FAR struct rpmsg_endpoint *ept)
|
|
|
|
{
|
|
|
|
struct rpmsg_router_edge_s *edge = ept->priv;
|
|
|
|
|
|
|
|
if (edge)
|
|
|
|
{
|
2024-07-02 12:31:52 +02:00
|
|
|
rpmsg_router_edge_destroy(edge);
|
drivers/rpmsg: add rpmsg router support
Rpmsg Router is new rpmsg transport layer, it can router the rpmsg
messages to a cpu that not directly connected with local cpu by Rpmsg,
For the rpmsg services, it is as if there is a real Rpmsg Channel between
the local cpu and the remote cpu.
For examples, there are three cpus: ap, cp and audio.
ap and cp, ap and audio has share memory and be connected by Rpmsg VirtIO,
so ap and cp, ap and audio can communicate with each other by Rpmsg, but
cp can not communicate with audio direclty.
[cp] <-- rpmsg virtio --> [ap] <-- rpmsg virtio --> [audio]
With rpmsg router, the cp can communicate with audip by Rpmsg dereclty because
the router in ap will forward the rpmsg message from cp/audio to audio/cp, like
this:
+<----- rpmsg router --> hub <-- rpmsg router ------>+
| | |
[cp] <-- rpmsg virtio --> [ap] <-- rpmsg virtio --> [audio]
Signed-off-by: yintao <yintao@xiaomi.com>
2024-04-14 07:17:05 +02:00
|
|
|
ept->priv = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
rpmsg_destroy_ept(ept);
|
|
|
|
kmm_free(ept);
|
|
|
|
}
|
|
|
|
|
|
|
|
/****************************************************************************
|
|
|
|
* Name: rpmsg_router_match
|
|
|
|
*
|
|
|
|
* Description:
|
|
|
|
* This function is used to match the endpoint for
|
|
|
|
* synchronizing ready messages.
|
|
|
|
*
|
|
|
|
* Parameters:
|
|
|
|
* rdev - real rpmsg device
|
|
|
|
* priv - rpmsg_router_priv
|
|
|
|
* name - endpoint name
|
|
|
|
* dest - destination address
|
|
|
|
*
|
|
|
|
* Returned Values:
|
|
|
|
* true on success; false on failure.
|
|
|
|
*
|
|
|
|
****************************************************************************/
|
|
|
|
|
|
|
|
static bool rpmsg_router_match(FAR struct rpmsg_device *rdev, FAR void *priv,
|
|
|
|
FAR const char *name, uint32_t dest)
|
|
|
|
{
|
|
|
|
return !strncmp(name, RPMSG_ROUTER_NAME, RPMSG_ROUTER_NAME_LEN);
|
|
|
|
}
|
|
|
|
|
|
|
|
/****************************************************************************
|
|
|
|
* Name: rpmsg_router_bind
|
|
|
|
*
|
|
|
|
* Description:
|
|
|
|
* This function is used to bind the endpoint for
|
|
|
|
* synchronizing ready messages.
|
|
|
|
*
|
|
|
|
* Parameters:
|
|
|
|
* rdev - real rpmsg device
|
|
|
|
* priv - private data
|
|
|
|
* name - endpoint name
|
|
|
|
* dest - destination address
|
|
|
|
*
|
|
|
|
****************************************************************************/
|
|
|
|
|
|
|
|
static void rpmsg_router_bind(FAR struct rpmsg_device *rdev, FAR void *priv,
|
|
|
|
FAR const char *name, uint32_t dest)
|
|
|
|
{
|
|
|
|
FAR struct rpmsg_endpoint *ept;
|
|
|
|
int ret;
|
|
|
|
|
|
|
|
ept = kmm_zalloc(sizeof(*ept));
|
|
|
|
DEBUGASSERT(ept);
|
|
|
|
|
|
|
|
ret = rpmsg_create_ept(ept, rdev, name, RPMSG_ADDR_ANY, dest,
|
|
|
|
rpmsg_router_cb, rpmsg_router_unbind);
|
|
|
|
if (ret < 0)
|
|
|
|
{
|
|
|
|
rpmsgerr("Create router endpoint failed: %d\n", ret);
|
|
|
|
kmm_free(ept);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/****************************************************************************
|
|
|
|
* Public Functions
|
|
|
|
****************************************************************************/
|
|
|
|
|
|
|
|
/****************************************************************************
|
|
|
|
* Name: rpmsg_router_edge_init
|
|
|
|
*
|
|
|
|
* Description:
|
|
|
|
* This function is used to initialize the edge core.
|
|
|
|
*
|
|
|
|
* Returned Values:
|
|
|
|
* OK on success; A negated errno value is returned on any failure.
|
|
|
|
*
|
|
|
|
****************************************************************************/
|
|
|
|
|
|
|
|
int rpmsg_router_edge_init(void)
|
|
|
|
{
|
|
|
|
/* Register callback for listening sync message from router hub */
|
|
|
|
|
|
|
|
return rpmsg_register_callback(NULL, NULL, NULL,
|
|
|
|
rpmsg_router_match,
|
|
|
|
rpmsg_router_bind);
|
|
|
|
}
|