diff --git a/drivers/Kconfig b/drivers/Kconfig index 77031932d2..328b726641 100644 --- a/drivers/Kconfig +++ b/drivers/Kconfig @@ -37,6 +37,7 @@ source "drivers/pipes/Kconfig" source "drivers/power/Kconfig" source "drivers/regmap/Kconfig" source "drivers/rmt/Kconfig" +source "drivers/rpmsg/Kconfig" source "drivers/rptun/Kconfig" source "drivers/sensors/Kconfig" source "drivers/serial/Kconfig" diff --git a/drivers/Makefile b/drivers/Makefile index e553af04d3..197ceb3215 100644 --- a/drivers/Makefile +++ b/drivers/Makefile @@ -56,6 +56,7 @@ include pipes/Make.defs include power/Make.defs include regmap/Make.defs include rmt/Make.defs +include rpmsg/Make.defs include rptun/Make.defs include sensors/Make.defs include serial/Make.defs diff --git a/drivers/rpmsg/CMakeLists.txt b/drivers/rpmsg/CMakeLists.txt new file mode 100644 index 0000000000..fd6ec42d4b --- /dev/null +++ b/drivers/rpmsg/CMakeLists.txt @@ -0,0 +1,27 @@ +# ############################################################################## +# drivers/rpmsg/CMakeLists.txt +# +# 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. +# +# ############################################################################## + +if(CONFIG_RPMSG) + set(SRCS) + + list(APPEND SRCS rpmsg.c) + + target_sources(drivers PRIVATE ${SRCS}) +endif() diff --git a/drivers/rpmsg/Kconfig b/drivers/rpmsg/Kconfig new file mode 100644 index 0000000000..1a7a073c8e --- /dev/null +++ b/drivers/rpmsg/Kconfig @@ -0,0 +1,9 @@ +# +# For a description of the syntax of this configuration file, +# see the file kconfig-language.txt in the NuttX tools repository. +# + +config RPMSG + bool + default n + select OPENAMP diff --git a/drivers/rpmsg/Make.defs b/drivers/rpmsg/Make.defs new file mode 100644 index 0000000000..1c9a7ae4a0 --- /dev/null +++ b/drivers/rpmsg/Make.defs @@ -0,0 +1,30 @@ +############################################################################ +# drivers/rptun/Make.defs +# +# 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. +# +############################################################################ + +# Don't build anything if there is no RPMSG support + +ifeq ($(CONFIG_RPMSG),y) + +CSRCS += rpmsg.c + +DEPPATH += --dep-path rpmsg +VPATH += :rpmsg + +endif diff --git a/drivers/rpmsg/rpmsg.c b/drivers/rpmsg/rpmsg.c new file mode 100644 index 0000000000..930ca10cac --- /dev/null +++ b/drivers/rpmsg/rpmsg.c @@ -0,0 +1,414 @@ +/**************************************************************************** + * drivers/rpmsg/rpmsg.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 + +#include +#include +#include +#include + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +struct rpmsg_bind_s +{ + char name[RPMSG_NAME_SIZE]; + uint32_t dest; + struct metal_list node; +}; + +struct rpmsg_cb_s +{ + FAR void *priv; + rpmsg_dev_cb_t device_created; + rpmsg_dev_cb_t device_destroy; + rpmsg_match_cb_t ns_match; + rpmsg_bind_cb_t ns_bind; + struct metal_list node; +}; + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +static METAL_DECLARE_LIST(g_rpmsg_cb); +static METAL_DECLARE_LIST(g_rpmsg); + +static rmutex_t g_rpmsg_lock = NXRMUTEX_INITIALIZER; + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +static inline FAR struct rpmsg_s * +rpmsg_get_by_rdev(FAR struct rpmsg_device *rdev) +{ + if (!rdev) + { + return NULL; + } + + return metal_container_of(rdev, struct rpmsg_s, rdev); +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +int rpmsg_wait(FAR struct rpmsg_endpoint *ept, FAR sem_t *sem) +{ + FAR struct rpmsg_s *rpmsg; + + if (!ept || !sem) + { + return -EINVAL; + } + + rpmsg = rpmsg_get_by_rdev(ept->rdev); + if (!rpmsg || !rpmsg->ops->wait) + { + return nxsem_wait_uninterruptible(sem); + } + + return rpmsg->ops->wait(rpmsg, sem); +} + +int rpmsg_post(FAR struct rpmsg_endpoint *ept, FAR sem_t *sem) +{ + FAR struct rpmsg_s *rpmsg; + + if (!ept || !sem) + { + return -EINVAL; + } + + rpmsg = rpmsg_get_by_rdev(ept->rdev); + if (!rpmsg || !rpmsg->ops->post) + { + return nxsem_post(sem); + } + + return rpmsg->ops->post(rpmsg, sem); +} + +FAR const char *rpmsg_get_cpuname(FAR struct rpmsg_device *rdev) +{ + FAR struct rpmsg_s *rpmsg = rpmsg_get_by_rdev(rdev); + + if (!rpmsg) + { + return NULL; + } + + return rpmsg->ops->get_cpuname(rpmsg); +} + +int rpmsg_register_callback(FAR void *priv, + rpmsg_dev_cb_t device_created, + rpmsg_dev_cb_t device_destroy, + rpmsg_match_cb_t ns_match, + rpmsg_bind_cb_t ns_bind) +{ + FAR struct metal_list *node; + FAR struct metal_list *bnode; + FAR struct rpmsg_cb_s *cb; + FAR struct rpmsg_s *rpmsg; + + cb = kmm_zalloc(sizeof(struct rpmsg_cb_s)); + if (!cb) + { + return -ENOMEM; + } + + cb->priv = priv; + cb->device_created = device_created; + cb->device_destroy = device_destroy; + cb->ns_match = ns_match; + cb->ns_bind = ns_bind; + + nxrmutex_lock(&g_rpmsg_lock); + + metal_list_for_each(&g_rpmsg, node) + { + rpmsg = metal_container_of(node, struct rpmsg_s, node); + if (!rpmsg->rdev->ns_unbind_cb) + { + continue; + } + + if (device_created) + { + device_created(rpmsg->rdev, priv); + } + + if (ns_bind == NULL) + { + continue; + } + + DEBUGASSERT(ns_match != NULL); +again: + + nxrmutex_lock(&rpmsg->lock); + + metal_list_for_each(&rpmsg->bind, bnode) + { + FAR struct rpmsg_bind_s *bind; + + bind = metal_container_of(bnode, struct rpmsg_bind_s, node); + if (ns_match(rpmsg->rdev, priv, bind->name, bind->dest)) + { + metal_list_del(bnode); + nxrmutex_unlock(&rpmsg->lock); + ns_bind(rpmsg->rdev, priv, bind->name, bind->dest); + + kmm_free(bind); + goto again; + } + } + + nxrmutex_unlock(&rpmsg->lock); + } + + metal_list_add_tail(&g_rpmsg_cb, &cb->node); + nxrmutex_unlock(&g_rpmsg_lock); + + return 0; +} + +void rpmsg_unregister_callback(FAR void *priv, + rpmsg_dev_cb_t device_created, + rpmsg_dev_cb_t device_destroy, + rpmsg_match_cb_t ns_match, + rpmsg_bind_cb_t ns_bind) +{ + FAR struct metal_list *node; + FAR struct metal_list *pnode; + + nxrmutex_lock(&g_rpmsg_lock); + + metal_list_for_each(&g_rpmsg_cb, node) + { + FAR struct rpmsg_cb_s *cb = NULL; + + cb = metal_container_of(node, struct rpmsg_cb_s, node); + if (cb->priv == priv && + cb->device_created == device_created && + cb->device_destroy == device_destroy && + cb->ns_match == ns_match && + cb->ns_bind == ns_bind) + { + metal_list_del(&cb->node); + kmm_free(cb); + + break; + } + } + + if (device_destroy) + { + metal_list_for_each(&g_rpmsg, pnode) + { + FAR struct rpmsg_s *rpmsg; + + rpmsg = metal_container_of(pnode, struct rpmsg_s, node); + if (rpmsg->rdev->ns_unbind_cb) + { + device_destroy(rpmsg->rdev, priv); + } + } + } + + nxrmutex_unlock(&g_rpmsg_lock); +} + +void rpmsg_ns_bind(FAR struct rpmsg_device *rdev, + FAR const char *name, uint32_t dest) +{ + FAR struct rpmsg_s *rpmsg = rpmsg_get_by_rdev(rdev); + FAR struct rpmsg_bind_s *bind; + FAR struct metal_list *node; + + nxrmutex_lock(&g_rpmsg_lock); + + metal_list_for_each(&g_rpmsg_cb, node) + { + FAR struct rpmsg_cb_s *cb; + + cb = metal_container_of(node, struct rpmsg_cb_s, node); + if (cb->ns_match && cb->ns_match(rdev, cb->priv, name, dest)) + { + rpmsg_bind_cb_t ns_bind = cb->ns_bind; + FAR void *cb_priv = cb->priv; + + nxrmutex_unlock(&g_rpmsg_lock); + DEBUGASSERT(ns_bind != NULL); + ns_bind(rdev, cb_priv, name, dest); + + return; + } + } + + nxrmutex_unlock(&g_rpmsg_lock); + + bind = kmm_malloc(sizeof(struct rpmsg_bind_s)); + if (bind == NULL) + { + return; + } + + bind->dest = dest; + strlcpy(bind->name, name, RPMSG_NAME_SIZE); + + nxrmutex_lock(&rpmsg->lock); + metal_list_add_tail(&rpmsg->bind, &bind->node); + nxrmutex_unlock(&rpmsg->lock); +} + +void rpmsg_ns_unbind(FAR struct rpmsg_device *rdev, + FAR const char *name, uint32_t dest) +{ + FAR struct rpmsg_s *rpmsg = rpmsg_get_by_rdev(rdev); + FAR struct metal_list *node; + + nxrmutex_lock(&rpmsg->lock); + + metal_list_for_each(&rpmsg->bind, node) + { + FAR struct rpmsg_bind_s *bind; + + bind = metal_container_of(node, struct rpmsg_bind_s, node); + + if (bind->dest == dest && !strncmp(bind->name, name, RPMSG_NAME_SIZE)) + { + metal_list_del(node); + kmm_free(bind); + break; + } + } + + nxrmutex_unlock(&rpmsg->lock); +} + +int rpmsg_foreach(rpmsg_foreach_t callback, FAR void *arg) +{ + FAR struct metal_list *node; + FAR struct rpmsg_s *rpmsg; + int ret = OK; + + nxrmutex_lock(&g_rpmsg_lock); + + metal_list_for_each(&g_rpmsg, node) + { + rpmsg = metal_container_of(node, struct rpmsg_s, node); + ret = callback(rpmsg, arg); + if (ret < 0) + { + break; + } + } + + nxrmutex_unlock(&g_rpmsg_lock); + + return ret; +} + +void rpmsg_device_created(FAR struct rpmsg_s *rpmsg) +{ + FAR struct rpmsg_cb_s *cb; + FAR struct metal_list *node; + + nxrmutex_lock(&g_rpmsg_lock); + + metal_list_for_each(&g_rpmsg_cb, node) + { + cb = metal_container_of(node, struct rpmsg_cb_s, node); + if (cb->device_created) + { + cb->device_created(rpmsg->rdev, cb->priv); + } + } + + nxrmutex_unlock(&g_rpmsg_lock); +} + +void rpmsg_device_destory(FAR struct rpmsg_s *rpmsg) +{ + FAR struct rpmsg_cb_s *cb; + FAR struct metal_list *node; + FAR struct metal_list *tmp; + + nxrmutex_lock(&rpmsg->lock); + + metal_list_for_each_safe(&rpmsg->bind, node, tmp) + { + FAR struct rpmsg_bind_s *bind; + + bind = metal_container_of(node, struct rpmsg_bind_s, node); + metal_list_del(node); + kmm_free(bind); + } + + nxrmutex_unlock(&rpmsg->lock); + + nxrmutex_lock(&g_rpmsg_lock); + + /* Broadcast device_destroy to all registers */ + + metal_list_for_each(&g_rpmsg_cb, node) + { + cb = metal_container_of(node, struct rpmsg_cb_s, node); + if (cb->device_destroy) + { + cb->device_destroy(rpmsg->rdev, cb->priv); + } + } + + nxrmutex_unlock(&g_rpmsg_lock); +} + +void rpmsg_register(FAR struct rpmsg_s *rpmsg, + FAR const struct rpmsg_ops_s *ops) +{ + metal_list_init(&rpmsg->bind); + nxrmutex_init(&rpmsg->lock); + rpmsg->ops = ops; + + /* Add priv to list */ + + nxrmutex_lock(&g_rpmsg_lock); + metal_list_add_tail(&g_rpmsg, &rpmsg->node); + nxrmutex_unlock(&g_rpmsg_lock); +} + +void rpmsg_unregister(FAR struct rpmsg_s *rpmsg) +{ + nxrmutex_lock(&g_rpmsg_lock); + metal_list_del(&rpmsg->node); + nxrmutex_unlock(&g_rpmsg_lock); + + nxrmutex_destroy(&rpmsg->lock); +} diff --git a/drivers/rptun/Kconfig b/drivers/rptun/Kconfig index 10e4834389..9e289de049 100644 --- a/drivers/rptun/Kconfig +++ b/drivers/rptun/Kconfig @@ -6,7 +6,7 @@ menuconfig RPTUN bool "Remote Proc Tunnel Driver Support" default n - select OPENAMP + select RPMSG ---help--- RPTUN driver is used for multi-cores' communication. diff --git a/drivers/rptun/rptun.c b/drivers/rptun/rptun.c index 2f3bf54b06..cae7d21ee6 100644 --- a/drivers/rptun/rptun.c +++ b/drivers/rptun/rptun.c @@ -36,11 +36,11 @@ #include #include #include -#include -#include #include #include #include +#include +#include #include "rptun.h" @@ -60,13 +60,11 @@ struct rptun_priv_s { + struct rpmsg_s rpmsg; + struct rpmsg_virtio_device rvdev; FAR struct rptun_dev_s *dev; struct remoteproc rproc; - struct rpmsg_virtio_device rvdev; struct rpmsg_virtio_shm_pool pool[2]; - struct metal_list bind; - rmutex_t lock; - struct metal_list node; sem_t semtx; sem_t semrx; pid_t tid; @@ -78,29 +76,19 @@ struct rptun_priv_s #endif }; -struct rptun_bind_s -{ - char name[RPMSG_NAME_SIZE]; - uint32_t dest; - struct metal_list node; -}; - -struct rptun_cb_s -{ - FAR void *priv; - rpmsg_dev_cb_t device_created; - rpmsg_dev_cb_t device_destroy; - rpmsg_match_cb_t ns_match; - rpmsg_bind_cb_t ns_bind; - struct metal_list node; -}; - struct rptun_store_s { struct file file; FAR char *buf; }; +struct rptun_ioctl_s +{ + FAR const char *cpuname; + int cmd; + unsigned long value; +}; + /**************************************************************************** * Private Function Prototypes ****************************************************************************/ @@ -122,9 +110,6 @@ rptun_get_mem(FAR struct remoteproc *rproc, FAR struct remoteproc_mem *buf); static int rptun_notify_wait(FAR struct remoteproc *rproc, uint32_t id); -static void rptun_ns_bind(FAR struct rpmsg_device *rdev, - FAR const char *name, uint32_t dest); - static int rptun_dev_start(FAR struct remoteproc *rproc); static int rptun_dev_stop(FAR struct remoteproc *rproc, bool stop_ns); static int rptun_dev_ioctl(FAR struct file *filep, int cmd, @@ -146,6 +131,10 @@ static metal_phys_addr_t rptun_pa_to_da(FAR struct rptun_dev_s *dev, static metal_phys_addr_t rptun_da_to_pa(FAR struct rptun_dev_s *dev, metal_phys_addr_t da); +static FAR const char *rptun_get_cpuname(FAR struct rpmsg_s *rpmsg); +static int rptun_wait(FAR struct rpmsg_s *rpmsg, FAR sem_t *sem); +static int rptun_post(FAR struct rpmsg_s *rpmsg, FAR sem_t *sem); + /**************************************************************************** * Private Data ****************************************************************************/ @@ -162,7 +151,7 @@ static const struct remoteproc_ops g_rptun_ops = .notify_wait = rptun_notify_wait, }; -static const struct file_operations g_rptun_devops = +static const struct file_operations g_rptun_dev_ops = { NULL, /* open */ NULL, /* close */ @@ -173,7 +162,7 @@ static const struct file_operations g_rptun_devops = }; #ifdef CONFIG_RPTUN_LOADER -static const struct image_store_ops g_rptun_storeops = +static const struct image_store_ops g_rptun_store_ops = { .open = rptun_store_open, .close = rptun_store_close, @@ -182,10 +171,12 @@ static const struct image_store_ops g_rptun_storeops = }; #endif -static METAL_DECLARE_LIST(g_rptun_cb); -static METAL_DECLARE_LIST(g_rptun_priv); - -static rmutex_t g_rptun_lockcb = NXRMUTEX_INITIALIZER; +static const struct rpmsg_ops_s g_rptun_rpmsg_ops = +{ + rptun_get_cpuname, + rptun_wait, + rptun_post, +}; /**************************************************************************** * Private Functions @@ -433,102 +424,53 @@ static int rptun_notify_wait(FAR struct remoteproc *rproc, uint32_t id) return 0; } -static void *rptun_get_priv_by_rdev(FAR struct rpmsg_device *rdev) +static FAR const char *rptun_get_cpuname(FAR struct rpmsg_s *rpmsg) { - FAR struct rpmsg_virtio_device *rvdev; - FAR struct virtio_device *vdev; - FAR struct remoteproc_virtio *rpvdev; - FAR struct remoteproc *rproc; + FAR struct rptun_priv_s *priv = (FAR struct rptun_priv_s *)rpmsg; - if (!rdev) - { - return NULL; - } - - rvdev = metal_container_of(rdev, struct rpmsg_virtio_device, rdev); - vdev = rvdev->vdev; - if (!vdev) - { - return NULL; - } - - rpvdev = metal_container_of(vdev, struct remoteproc_virtio, vdev); - rproc = rpvdev->priv; - if (!rproc) - { - return NULL; - } - - return rproc->priv; + return RPTUN_GET_CPUNAME(priv->dev); } -static void rptun_ns_bind(FAR struct rpmsg_device *rdev, - FAR const char *name, uint32_t dest) +static int rptun_wait(FAR struct rpmsg_s *rpmsg, FAR sem_t *sem) { - FAR struct rptun_priv_s *priv = rptun_get_priv_by_rdev(rdev); - FAR struct rptun_bind_s *bind; - FAR struct metal_list *node; + FAR struct rptun_priv_s *priv = (FAR struct rptun_priv_s *)rpmsg; + int ret; - nxrmutex_lock(&g_rptun_lockcb); - - metal_list_for_each(&g_rptun_cb, node) + if (!rptun_is_recursive(priv)) { - FAR struct rptun_cb_s *cb; - - cb = metal_container_of(node, struct rptun_cb_s, node); - if (cb->ns_match && cb->ns_match(rdev, cb->priv, name, dest)) - { - rpmsg_bind_cb_t ns_bind = cb->ns_bind; - FAR void *cb_priv = cb->priv; - - nxrmutex_unlock(&g_rptun_lockcb); - - DEBUGASSERT(ns_bind != NULL); - ns_bind(rdev, cb_priv, name, dest); - - return; - } + return nxsem_wait_uninterruptible(sem); } - nxrmutex_unlock(&g_rptun_lockcb); - - bind = kmm_malloc(sizeof(struct rptun_bind_s)); - if (bind == NULL) + while (1) { - return; - } - - bind->dest = dest; - strlcpy(bind->name, name, RPMSG_NAME_SIZE); - - nxrmutex_lock(&priv->lock); - metal_list_add_tail(&priv->bind, &bind->node); - nxrmutex_unlock(&priv->lock); -} - -static void rptun_ns_unbind(FAR struct rpmsg_device *rdev, - FAR const char *name, uint32_t dest) -{ - FAR struct rptun_priv_s *priv = rptun_get_priv_by_rdev(rdev); - FAR struct metal_list *node; - - nxrmutex_lock(&priv->lock); - - metal_list_for_each(&priv->bind, node) - { - struct rptun_bind_s *bind; - - bind = metal_container_of(node, struct rptun_bind_s, node); - - if (bind->dest == dest && !strncmp(bind->name, name, RPMSG_NAME_SIZE)) + ret = nxsem_trywait(sem); + if (ret >= 0) { - metal_list_del(node); - kmm_free(bind); break; } + + nxsem_wait(&priv->semtx); + rptun_worker(priv); } - nxrmutex_unlock(&priv->lock); + return ret; +} + +static int rptun_post(FAR struct rpmsg_s *rpmsg, FAR sem_t *sem) +{ + FAR struct rptun_priv_s *priv = (FAR struct rptun_priv_s *)rpmsg; + int semcount; + int ret; + + nxsem_get_value(sem, &semcount); + ret = nxsem_post(sem); + + if (priv && semcount >= 0) + { + rptun_wakeup_tx(priv); + } + + return ret; } static int rptun_dev_start(FAR struct remoteproc *rproc) @@ -536,8 +478,6 @@ static int rptun_dev_start(FAR struct remoteproc *rproc) FAR struct rptun_priv_s *priv = rproc->priv; FAR struct virtio_device *vdev; FAR struct rptun_rsc_s *rsc; - FAR struct metal_list *node; - FAR struct rptun_cb_s *cb; unsigned int role = RPMSG_REMOTE; int ret; @@ -556,7 +496,7 @@ static int rptun_dev_start(FAR struct remoteproc *rproc) }; ret = remoteproc_load(rproc, RPTUN_GET_FIRMWARE(priv->dev), - &store, &g_rptun_storeops, NULL); + &store, &g_rptun_store_ops, NULL); if (ret) { return ret; @@ -666,14 +606,14 @@ static int rptun_dev_start(FAR struct remoteproc *rproc) true, }; - ret = rpmsg_init_vdev_with_config(&priv->rvdev, vdev, rptun_ns_bind, + ret = rpmsg_init_vdev_with_config(&priv->rvdev, vdev, rpmsg_ns_bind, metal_io_get_region(), priv->pool, &config); } else { - ret = rpmsg_init_vdev(&priv->rvdev, vdev, rptun_ns_bind, + ret = rpmsg_init_vdev(&priv->rvdev, vdev, rpmsg_ns_bind, metal_io_get_region(), priv->pool); } @@ -683,7 +623,7 @@ static int rptun_dev_start(FAR struct remoteproc *rproc) return ret; } - priv->rvdev.rdev.ns_unbind_cb = rptun_ns_unbind; + priv->rvdev.rdev.ns_unbind_cb = rpmsg_ns_unbind; /* Remote proc start */ @@ -703,18 +643,9 @@ static int rptun_dev_start(FAR struct remoteproc *rproc) /* Broadcast device_created to all registers */ - nxrmutex_lock(&g_rptun_lockcb); + rpmsg_device_created(&priv->rpmsg); - metal_list_for_each(&g_rptun_cb, node) - { - cb = metal_container_of(node, struct rptun_cb_s, node); - if (cb->device_created) - { - cb->device_created(&priv->rvdev.rdev, cb->priv); - } - } - - nxrmutex_unlock(&g_rptun_lockcb); + /* Open tx buffer return callback */ virtqueue_enable_cb(priv->rvdev.svq); @@ -728,9 +659,6 @@ static int rptun_dev_stop(FAR struct remoteproc *rproc, bool stop_ns) { FAR struct rptun_priv_s *priv = rproc->priv; FAR struct rpmsg_device *rdev = &priv->rvdev.rdev; - FAR struct metal_list *node; - FAR struct metal_list *tmp; - FAR struct rptun_cb_s *cb; if (priv->rproc.state == RPROC_OFFLINE) { @@ -748,39 +676,11 @@ static int rptun_dev_stop(FAR struct remoteproc *rproc, bool stop_ns) rptun_ping_deinit(&priv->ping); #endif - nxrmutex_lock(&priv->lock); - - metal_list_for_each_safe(&priv->bind, node, tmp) - { - FAR struct rptun_bind_s *bind; - - bind = metal_container_of(node, struct rptun_bind_s, node); - metal_list_del(node); - kmm_free(bind); - } - - nxrmutex_unlock(&priv->lock); - /* Unregister callback from mbox */ RPTUN_UNREGISTER_CALLBACK(priv->dev); - /* Remove priv from list */ - - nxrmutex_lock(&g_rptun_lockcb); - - /* Broadcast device_destroy to all registers */ - - metal_list_for_each(&g_rptun_cb, node) - { - cb = metal_container_of(node, struct rptun_cb_s, node); - if (cb->device_destroy) - { - cb->device_destroy(&priv->rvdev.rdev, cb->priv); - } - } - - nxrmutex_unlock(&g_rptun_lockcb); + rpmsg_device_destory(&priv->rpmsg); /* Remote proc remove */ @@ -962,215 +862,42 @@ static metal_phys_addr_t rptun_da_to_pa(FAR struct rptun_dev_s *dev, return da; } -static int rptun_ioctl_foreach(FAR const char *cpuname, int cmd, - unsigned long value) +static int rptun_ioctl_foreach_cb(FAR struct rpmsg_s *rpmsg, + FAR void *arg_) { - FAR struct metal_list *node; + FAR struct rptun_priv_s *priv = (struct rptun_priv_s *)rpmsg; + FAR struct rptun_ioctl_s *arg = (struct rptun_ioctl_s *)arg_; int ret = OK; - metal_list_for_each(&g_rptun_priv, node) + if (!arg->cpuname || + !strcmp(RPTUN_GET_CPUNAME(priv->dev), arg->cpuname)) { - FAR struct rptun_priv_s *priv; - - priv = metal_container_of(node, struct rptun_priv_s, node); - - if (!cpuname || !strcmp(RPTUN_GET_CPUNAME(priv->dev), cpuname)) + ret = rptun_do_ioctl(priv, arg->cmd, arg->value); + if (ret < 0) { - ret = rptun_do_ioctl(priv, cmd, value); - if (ret < 0) - break; + return ret; } } return ret; } +static int rptun_ioctl_foreach(FAR const char *cpuname, int cmd, + unsigned long value) +{ + struct rptun_ioctl_s arg; + + arg.cpuname = cpuname; + arg.cmd = cmd; + arg.value = value; + + return rpmsg_foreach(rptun_ioctl_foreach_cb, &arg); +} + /**************************************************************************** * Public Functions ****************************************************************************/ -int rpmsg_wait(FAR struct rpmsg_endpoint *ept, FAR sem_t *sem) -{ - FAR struct rptun_priv_s *priv; - int ret; - - if (!ept || !sem) - { - return -EINVAL; - } - - priv = rptun_get_priv_by_rdev(ept->rdev); - if (!priv || !rptun_is_recursive(priv)) - { - return nxsem_wait_uninterruptible(sem); - } - - while (1) - { - ret = nxsem_trywait(sem); - if (ret >= 0) - { - break; - } - - nxsem_wait(&priv->semtx); - rptun_worker(priv); - } - - return ret; -} - -int rpmsg_post(FAR struct rpmsg_endpoint *ept, FAR sem_t *sem) -{ - FAR struct rptun_priv_s *priv; - int semcount; - int ret; - - if (!ept || !sem) - { - return -EINVAL; - } - - nxsem_get_value(sem, &semcount); - ret = nxsem_post(sem); - - priv = rptun_get_priv_by_rdev(ept->rdev); - if (priv && semcount >= 0) - { - rptun_wakeup_tx(priv); - } - - return ret; -} - -FAR const char *rpmsg_get_cpuname(FAR struct rpmsg_device *rdev) -{ - FAR struct rptun_priv_s *priv = rptun_get_priv_by_rdev(rdev); - - return RPTUN_GET_CPUNAME(priv->dev); -} - -int rpmsg_register_callback(FAR void *priv_, - rpmsg_dev_cb_t device_created, - rpmsg_dev_cb_t device_destroy, - rpmsg_match_cb_t ns_match, - rpmsg_bind_cb_t ns_bind) -{ - FAR struct metal_list *node; - FAR struct metal_list *bnode; - FAR struct rptun_cb_s *cb; - - cb = kmm_zalloc(sizeof(struct rptun_cb_s)); - if (!cb) - { - return -ENOMEM; - } - - cb->priv = priv_; - cb->device_created = device_created; - cb->device_destroy = device_destroy; - cb->ns_match = ns_match; - cb->ns_bind = ns_bind; - - nxrmutex_lock(&g_rptun_lockcb); - - metal_list_for_each(&g_rptun_priv, node) - { - FAR struct rptun_priv_s *priv; - - priv = metal_container_of(node, struct rptun_priv_s, node); - if (priv->rproc.state != RPROC_RUNNING) - { - continue; - } - - if (device_created) - { - device_created(&priv->rvdev.rdev, priv_); - } - - if (ns_bind == NULL) - { - continue; - } - - DEBUGASSERT(ns_match != NULL); -again: - nxrmutex_lock(&priv->lock); - - metal_list_for_each(&priv->bind, bnode) - { - FAR struct rptun_bind_s *bind; - - bind = metal_container_of(bnode, struct rptun_bind_s, node); - if (ns_match(&priv->rvdev.rdev, priv_, bind->name, bind->dest)) - { - metal_list_del(bnode); - nxrmutex_unlock(&priv->lock); - - ns_bind(&priv->rvdev.rdev, priv_, bind->name, bind->dest); - kmm_free(bind); - goto again; - } - } - - nxrmutex_unlock(&priv->lock); - } - - metal_list_add_tail(&g_rptun_cb, &cb->node); - nxrmutex_unlock(&g_rptun_lockcb); - - return 0; -} - -void rpmsg_unregister_callback(FAR void *priv_, - rpmsg_dev_cb_t device_created, - rpmsg_dev_cb_t device_destroy, - rpmsg_match_cb_t ns_match, - rpmsg_bind_cb_t ns_bind) -{ - FAR struct metal_list *node; - FAR struct metal_list *pnode; - - nxrmutex_lock(&g_rptun_lockcb); - - metal_list_for_each(&g_rptun_cb, node) - { - FAR struct rptun_cb_s *cb = NULL; - - cb = metal_container_of(node, struct rptun_cb_s, node); - if (cb->priv == priv_ && - cb->device_created == device_created && - cb->device_destroy == device_destroy && - cb->ns_match == ns_match && - cb->ns_bind == ns_bind) - { - metal_list_del(&cb->node); - kmm_free(cb); - - break; - } - } - - if (device_destroy) - { - metal_list_for_each(&g_rptun_priv, pnode) - { - struct rptun_priv_s *priv; - - priv = metal_container_of(pnode, - struct rptun_priv_s, node); - - if (priv->rproc.state == RPROC_RUNNING) - { - device_destroy(&priv->rvdev.rdev, priv_); - } - } - } - - nxrmutex_unlock(&g_rptun_lockcb); -} - int rptun_initialize(FAR struct rptun_dev_s *dev) { struct metal_init_params params = METAL_INIT_DEFAULTS; @@ -1202,11 +929,10 @@ int rptun_initialize(FAR struct rptun_dev_s *dev) priv->dev = dev; remoteproc_init(&priv->rproc, &g_rptun_ops, priv); - metal_list_init(&priv->bind); - nxrmutex_init(&priv->lock); + rpmsg_register(&priv->rpmsg, &g_rptun_rpmsg_ops); snprintf(name, sizeof(name), "/dev/rptun/%s", RPTUN_GET_CPUNAME(dev)); - ret = register_driver(name, &g_rptun_devops, 0222, priv); + ret = register_driver(name, &g_rptun_dev_ops, 0222, priv); if (ret < 0) { goto err_driver; @@ -1231,14 +957,10 @@ int rptun_initialize(FAR struct rptun_dev_s *dev) /* Add priv to list */ - nxrmutex_lock(&g_rptun_lockcb); - metal_list_add_tail(&g_rptun_priv, &priv->node); - nxrmutex_unlock(&g_rptun_lockcb); - return OK; err_driver: - nxrmutex_destroy(&priv->lock); + rpmsg_unregister(&priv->rpmsg); kmm_free(priv); err_mem: diff --git a/drivers/rptun/rptun.h b/drivers/rptun/rptun.h index b937fabb2c..c19ddb4c3e 100644 --- a/drivers/rptun/rptun.h +++ b/drivers/rptun/rptun.h @@ -26,7 +26,7 @@ ****************************************************************************/ #include -#include +#include #include "rptun_ping.h" diff --git a/drivers/syslog/syslog_rpmsg.c b/drivers/syslog/syslog_rpmsg.c index 0409797ffa..0aa1db1168 100644 --- a/drivers/syslog/syslog_rpmsg.c +++ b/drivers/syslog/syslog_rpmsg.c @@ -29,6 +29,7 @@ #include #include #include +#include #ifdef CONFIG_ARCH_LOWPUTC #include diff --git a/drivers/usrsock/usrsock_rpmsg_server.c b/drivers/usrsock/usrsock_rpmsg_server.c index 9020ec8201..df8657fb62 100644 --- a/drivers/usrsock/usrsock_rpmsg_server.c +++ b/drivers/usrsock/usrsock_rpmsg_server.c @@ -32,6 +32,7 @@ #include +#include #include #include #include diff --git a/drivers/wireless/bluetooth/bt_rpmsghci_server.c b/drivers/wireless/bluetooth/bt_rpmsghci_server.c index fbd97d5768..be3e54b47b 100644 --- a/drivers/wireless/bluetooth/bt_rpmsghci_server.c +++ b/drivers/wireless/bluetooth/bt_rpmsghci_server.c @@ -28,6 +28,7 @@ #include #include +#include #include #include diff --git a/fs/rpmsgfs/rpmsgfs_server.c b/fs/rpmsgfs/rpmsgfs_server.c index f03b565a88..2bf8044326 100644 --- a/fs/rpmsgfs/rpmsgfs_server.c +++ b/fs/rpmsgfs/rpmsgfs_server.c @@ -35,6 +35,7 @@ #include #include #include +#include #include "rpmsgfs.h" diff --git a/include/nuttx/rpmsg/rpmsg.h b/include/nuttx/rpmsg/rpmsg.h new file mode 100644 index 0000000000..36c43333b4 --- /dev/null +++ b/include/nuttx/rpmsg/rpmsg.h @@ -0,0 +1,116 @@ +/**************************************************************************** + * include/nuttx/rpmsg/rpmsg.h + * + * 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. + * + ****************************************************************************/ + +#ifndef __INCLUDE_NUTTX_RPMSG_RPMSG_H +#define __INCLUDE_NUTTX_RPMSG_RPMSG_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#ifdef CONFIG_RPMSG + +#include + +/**************************************************************************** + * Public Types + ****************************************************************************/ + +struct rpmsg_s +{ + struct metal_list bind; + rmutex_t lock; + struct metal_list node; + FAR const struct rpmsg_ops_s *ops; + struct rpmsg_device rdev[0]; +}; + +typedef CODE int (*rpmsg_foreach_t)(FAR struct rpmsg_s *rpmsg, + FAR void *arg); + +/** + * struct rpmsg_ops_s - Rpmsg device operations + * get_cpuname: get cpu name. + * wait: wait sem. + * post: post sem. + */ + +struct rpmsg_ops_s +{ + CODE FAR const char *(*get_cpuname)(FAR struct rpmsg_s *rpmsg); + CODE int (*wait)(FAR struct rpmsg_s *rpmsg, FAR sem_t *sem); + CODE int (*post)(FAR struct rpmsg_s *rpmsg, FAR sem_t *sem); +}; + +CODE typedef void (*rpmsg_dev_cb_t)(FAR struct rpmsg_device *rdev, + FAR void *priv); +CODE typedef bool (*rpmsg_match_cb_t)(FAR struct rpmsg_device *rdev, + FAR void *priv, FAR const char *name, + uint32_t dest); +CODE typedef void (*rpmsg_bind_cb_t)(FAR struct rpmsg_device *rdev, + FAR void *priv, FAR const char *name, + uint32_t dest); + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +#ifdef __cplusplus +#define EXTERN extern "C" +extern "C" +{ +#else +#define EXTERN extern +#endif + +int rpmsg_wait(FAR struct rpmsg_endpoint *ept, FAR sem_t *sem); +int rpmsg_post(FAR struct rpmsg_endpoint *ept, FAR sem_t *sem); + +FAR const char *rpmsg_get_cpuname(FAR struct rpmsg_device *rdev); + +int rpmsg_register_callback(FAR void *priv, + rpmsg_dev_cb_t device_created, + rpmsg_dev_cb_t device_destroy, + rpmsg_match_cb_t ns_match, + rpmsg_bind_cb_t ns_bind); +void rpmsg_unregister_callback(FAR void *priv, + rpmsg_dev_cb_t device_created, + rpmsg_dev_cb_t device_destroy, + rpmsg_match_cb_t ns_match, + rpmsg_bind_cb_t ns_bind); +void rpmsg_ns_bind(FAR struct rpmsg_device *rdev, + FAR const char *name, uint32_t dest); +void rpmsg_ns_unbind(FAR struct rpmsg_device *rdev, + FAR const char *name, uint32_t dest); +void rpmsg_device_created(FAR struct rpmsg_s *rpmsg); +void rpmsg_device_destory(FAR struct rpmsg_s *rpmsg); +void rpmsg_register(FAR struct rpmsg_s *rpmsg, + FAR const struct rpmsg_ops_s *ops); +void rpmsg_unregister(FAR struct rpmsg_s *rpmsg); +int rpmsg_foreach(rpmsg_foreach_t callback, FAR void *arg); + +#ifdef __cplusplus +} +#endif + +#endif /* CONFIG_RPMSG */ +#endif /* __INCLUDE_NUTTX_RPMSG_RPMSG_H */ diff --git a/include/nuttx/rptun/openamp.h b/include/nuttx/rptun/openamp.h index 98f4d54c6d..c06080e02c 100644 --- a/include/nuttx/rptun/openamp.h +++ b/include/nuttx/rptun/openamp.h @@ -27,55 +27,6 @@ #include -#ifdef CONFIG_RPTUN +#include -#include -#include - -/**************************************************************************** - * Public Types - ****************************************************************************/ - -typedef void (*rpmsg_dev_cb_t)(FAR struct rpmsg_device *rdev, - FAR void *priv); -typedef bool (*rpmsg_match_cb_t)(FAR struct rpmsg_device *rdev, - FAR void *priv, FAR const char *name, - uint32_t dest); -typedef void (*rpmsg_bind_cb_t)(FAR struct rpmsg_device *rdev, - FAR void *priv, FAR const char *name, - uint32_t dest); - -/**************************************************************************** - * Public Function Prototypes - ****************************************************************************/ - -#ifdef __cplusplus -#define EXTERN extern "C" -extern "C" -{ -#else -#define EXTERN extern -#endif - -int rpmsg_wait(FAR struct rpmsg_endpoint *ept, FAR sem_t *sem); -int rpmsg_post(FAR struct rpmsg_endpoint *ept, FAR sem_t *sem); - -const char *rpmsg_get_cpuname(FAR struct rpmsg_device *rdev); - -int rpmsg_register_callback(FAR void *priv, - rpmsg_dev_cb_t device_created, - rpmsg_dev_cb_t device_destroy, - rpmsg_match_cb_t ns_match, - rpmsg_bind_cb_t ns_bind); -void rpmsg_unregister_callback(FAR void *priv, - rpmsg_dev_cb_t device_created, - rpmsg_dev_cb_t device_destroy, - rpmsg_match_cb_t ns_match, - rpmsg_bind_cb_t ns_bind); - -#ifdef __cplusplus -} -#endif - -#endif /* CONFIG_RPTUN */ #endif /* __INCLUDE_NUTTX_RPTUN_OPENAMP_H */ diff --git a/include/nuttx/rptun/rptun.h b/include/nuttx/rptun/rptun.h index e887d9b2df..972b78350d 100644 --- a/include/nuttx/rptun/rptun.h +++ b/include/nuttx/rptun/rptun.h @@ -31,7 +31,8 @@ #include #include -#include +#include +#include /**************************************************************************** * Pre-processor Definitions