diff --git a/drivers/rpmsg/rpmsg.c b/drivers/rpmsg/rpmsg.c index b7b77f4d05b..311e22211a1 100644 --- a/drivers/rpmsg/rpmsg.c +++ b/drivers/rpmsg/rpmsg.c @@ -32,8 +32,10 @@ #include #include #include +#include #include "rpmsg_ping.h" +#include "rpmsg_router.h" #include "rpmsg_test.h" /**************************************************************************** @@ -587,6 +589,36 @@ void rpmsg_dump_all(void) void rpmsg_modify_signals(FAR struct rpmsg_s *rpmsg, int setflags, int clrflags) { + FAR struct rpmsg_device *rdev = rpmsg->rdev; + FAR struct rpmsg_endpoint *ept; + FAR struct metal_list *node; + bool needlock; + atomic_fetch_and(&rpmsg->signals, ~clrflags); atomic_fetch_or(&rpmsg->signals, setflags); + + /* Send signal to Router Hub */ + + needlock = !up_interrupt_context() && !sched_idletask(); + if (needlock) + { + metal_mutex_acquire(&rdev->lock); + } + + metal_list_for_each(&rdev->endpoints, node) + { + ept = metal_container_of(node, struct rpmsg_endpoint, node); + if (!strncmp(ept->name, RPMSG_ROUTER_NAME, + RPMSG_ROUTER_NAME_LEN)) + { + rpmsg_ept_incref(ept); + ept->cb(ept, NULL, 0, RPMSG_ADDR_ANY, NULL); + rpmsg_ept_decref(ept); + } + } + + if (needlock) + { + metal_mutex_release(&rdev->lock); + } } diff --git a/drivers/rpmsg/rpmsg_router.h b/drivers/rpmsg/rpmsg_router.h index 8f7547f9ce5..cb799cd253b 100644 --- a/drivers/rpmsg/rpmsg_router.h +++ b/drivers/rpmsg/rpmsg_router.h @@ -29,8 +29,6 @@ #include -#ifdef CONFIG_RPMSG_ROUTER - /**************************************************************************** * Pre-processor Definitions ****************************************************************************/ @@ -43,6 +41,10 @@ #define RPMSG_ROUTER_CREATE 1 #define RPMSG_ROUTER_DESTROY 2 +#define RPMSG_ROUTER_SUSPEND 3 +#define RPMSG_ROUTER_RESUME 4 + +#ifdef CONFIG_RPMSG_ROUTER /**************************************************************************** * Public Types diff --git a/drivers/rpmsg/rpmsg_router_edge.c b/drivers/rpmsg/rpmsg_router_edge.c index 294d008959b..3bdfbc8c406 100644 --- a/drivers/rpmsg/rpmsg_router_edge.c +++ b/drivers/rpmsg/rpmsg_router_edge.c @@ -683,15 +683,34 @@ static int rpmsg_router_cb(FAR struct rpmsg_endpoint *ept, if (msg->cmd == RPMSG_ROUTER_DESTROY) { edge = ept->priv; - - if (edge) + if (edge == NULL) { - rpmsg_router_edge_destroy(edge); - ept->priv = NULL; - return 0; + return -EINVAL; } - return -EINVAL; + rpmsg_router_edge_destroy(edge); + ept->priv = NULL; + return 0; + } + else if (msg->cmd == RPMSG_ROUTER_SUSPEND || + msg->cmd == RPMSG_ROUTER_RESUME) + { + edge = ept->priv; + if (edge == NULL) + { + return -EINVAL; + } + + if (msg->cmd == RPMSG_ROUTER_SUSPEND) + { + rpmsg_modify_signals(&edge->rpmsg, 0, RPMSG_SIGNAL_RUNNING); + } + else + { + rpmsg_modify_signals(&edge->rpmsg, RPMSG_SIGNAL_RUNNING, 0); + } + + return 0; } /* Create the router edge device */ diff --git a/drivers/rpmsg/rpmsg_router_hub.c b/drivers/rpmsg/rpmsg_router_hub.c index 5aad21480c5..6f872d90abf 100644 --- a/drivers/rpmsg/rpmsg_router_hub.c +++ b/drivers/rpmsg/rpmsg_router_hub.c @@ -35,6 +35,7 @@ #include #include +#include #include #include "rpmsg_router.h" @@ -59,6 +60,7 @@ struct rpmsg_router_hub_s { struct rpmsg_endpoint ept[2]; + struct work_s work; char cpuname[2][RPMSG_ROUTER_CPUNAME_LEN]; mutex_t lock; }; @@ -359,6 +361,31 @@ static void rpmsg_router_bound(FAR struct rpmsg_endpoint *ept) } } +/**************************************************************************** + * Name: rpmsg_router_notify_edge + ****************************************************************************/ + +static void rpmsg_router_notify_edge(FAR void *arg) +{ + FAR struct rpmsg_endpoint *ept = arg; + FAR struct rpmsg_router_hub_s *hub = ept->priv; + struct rpmsg_router_s msg; + int i; + + msg.cmd = rpmsg_is_running(ept->rdev) ? + RPMSG_ROUTER_RESUME : RPMSG_ROUTER_SUSPEND; + for (i = 0; i < 2; i++) + { + if (strcmp(rpmsg_get_cpuname(ept->rdev), hub->cpuname[i])) + { + rpmsg_send(&hub->ept[i], &msg, sizeof(msg)); + } + } + + rpmsg_ept_decref(&hub->ept[0]); + rpmsg_ept_decref(&hub->ept[1]); +} + /**************************************************************************** * Name: rpmsg_router_cb ****************************************************************************/ @@ -366,6 +393,17 @@ static void rpmsg_router_bound(FAR struct rpmsg_endpoint *ept) 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_hub_s *hub = ept->priv; + + /* Send pm signal to the other edge core */ + + if (data == NULL) + { + rpmsg_ept_incref(&hub->ept[0]); + rpmsg_ept_incref(&hub->ept[1]); + work_queue(HPWORK, &hub->work, rpmsg_router_notify_edge, ept, 0); + } + return 0; }