rptun: Strip rpmsg and rptun

nuttx/driver/rpmsg: new folder, extract common rpmsg api in rptun.c to rpmsg.c.
rpmsg provide rpmsg_ops to each backend for specific implementation.

Signed-off-by: wangyongrong <wangyongrong@xiaomi.com>
This commit is contained in:
wangyongrong 2023-12-12 10:53:45 +08:00 committed by Mateusz Szafoni
parent 95fcc286a2
commit 7508a10e20
16 changed files with 693 additions and 417 deletions

View File

@ -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"

View File

@ -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

View File

@ -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()

9
drivers/rpmsg/Kconfig Normal file
View File

@ -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

30
drivers/rpmsg/Make.defs Normal file
View File

@ -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

414
drivers/rpmsg/rpmsg.c Normal file
View File

@ -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 <nuttx/config.h>
#include <nuttx/kmalloc.h>
#include <nuttx/mutex.h>
#include <nuttx/semaphore.h>
#include <nuttx/rpmsg/rpmsg.h>
/****************************************************************************
* 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);
}

View File

@ -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.

View File

@ -36,11 +36,11 @@
#include <nuttx/kthread.h>
#include <nuttx/mutex.h>
#include <nuttx/semaphore.h>
#include <nuttx/rptun/openamp.h>
#include <nuttx/rptun/rptun.h>
#include <nuttx/power/pm.h>
#include <nuttx/wqueue.h>
#include <metal/utilities.h>
#include <openamp/remoteproc_loader.h>
#include <openamp/remoteproc_virtio.h>
#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)
ret = nxsem_trywait(sem);
if (ret >= 0)
{
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))
{
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, cmd, value);
ret = rptun_do_ioctl(priv, arg->cmd, arg->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:

View File

@ -26,7 +26,7 @@
****************************************************************************/
#include <nuttx/rptun/rptun.h>
#include <openamp/open_amp.h>
#include <nuttx/rpmsg/rpmsg.h>
#include "rptun_ping.h"

View File

@ -29,6 +29,7 @@
#include <errno.h>
#include <string.h>
#include <sys/boardctl.h>
#include <syslog.h>
#ifdef CONFIG_ARCH_LOWPUTC
#include <nuttx/arch.h>

View File

@ -32,6 +32,7 @@
#include <sys/ioctl.h>
#include <nuttx/kmalloc.h>
#include <nuttx/mutex.h>
#include <nuttx/net/dns.h>
#include <nuttx/net/net.h>

View File

@ -28,6 +28,7 @@
#include <debug.h>
#include <stdlib.h>
#include <nuttx/kmalloc.h>
#include <nuttx/rptun/openamp.h>
#include <nuttx/wireless/bluetooth/bt_rpmsghci.h>

View File

@ -35,6 +35,7 @@
#include <nuttx/mutex.h>
#include <nuttx/fs/fs.h>
#include <nuttx/rptun/openamp.h>
#include <openamp/rpmsg_virtio.h>
#include "rpmsgfs.h"

116
include/nuttx/rpmsg/rpmsg.h Normal file
View File

@ -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 <nuttx/config.h>
#ifdef CONFIG_RPMSG
#include <openamp/rpmsg.h>
/****************************************************************************
* 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 */

View File

@ -27,55 +27,6 @@
#include <nuttx/config.h>
#ifdef CONFIG_RPTUN
#include <nuttx/rpmsg/rpmsg.h>
#include <openamp/open_amp.h>
#include <openamp/remoteproc_loader.h>
/****************************************************************************
* 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 */

View File

@ -31,7 +31,8 @@
#include <nuttx/fs/ioctl.h>
#include <nuttx/rptun/rptun_ping.h>
#include <openamp/open_amp.h>
#include <openamp/remoteproc.h>
#include <openamp/rpmsg_virtio.h>
/****************************************************************************
* Pre-processor Definitions