diff --git a/drivers/rptun/Kconfig b/drivers/rptun/Kconfig index c1a2415b4c..327b20a5f0 100644 --- a/drivers/rptun/Kconfig +++ b/drivers/rptun/Kconfig @@ -52,4 +52,11 @@ config RPTUN_PM goto RAM-retention mode, can't access from another CPU. So, we provide this method to resolve this. +config RPTUN_PING + bool "rptun ping support" + default n + ---help--- + This is for rptun debugging & profiling, create ping rpmsg + channel, user can use it to get send/recv speed & latency. + endif # RPTUN diff --git a/drivers/rptun/Make.defs b/drivers/rptun/Make.defs index 8c79e0a157..03446ec9ac 100644 --- a/drivers/rptun/Make.defs +++ b/drivers/rptun/Make.defs @@ -22,7 +22,11 @@ ifeq ($(CONFIG_RPTUN),y) -CSRCS += rptun.c rpmsg_dump.c +CSRCS += rptun.c rptun_dump.c + +ifeq ($(CONFIG_RPTUN_PING),y) +CSRCS += rptun_ping.c +endif DEPPATH += --dep-path rptun VPATH += :rptun diff --git a/drivers/rptun/rptun.c b/drivers/rptun/rptun.c index 624c92794f..949cf97b5e 100644 --- a/drivers/rptun/rptun.c +++ b/drivers/rptun/rptun.c @@ -39,6 +39,8 @@ #include #include +#include "rptun.h" + /**************************************************************************** * Pre-processor Definitions ****************************************************************************/ @@ -81,6 +83,9 @@ struct rptun_priv_s #ifdef CONFIG_RPTUN_PM bool stay; #endif +#ifdef CONFIG_RPTUN_PING + struct rpmsg_endpoint ping; +#endif }; struct rptun_bind_s @@ -268,7 +273,7 @@ static inline void rptun_pm_action(FAR struct rptun_priv_s *priv, priv->stay = true; } - if (!stay && priv->stay && !rpmsg_buffer_nused(&priv->rvdev, false)) + if (!stay && priv->stay && !rptun_buffer_nused(&priv->rvdev, false)) { pm_relax(0, PM_IDLE); priv->stay = false; @@ -785,6 +790,10 @@ static int rptun_dev_start(FAR struct remoteproc *rproc) rptun_unlock(); virtqueue_enable_cb(priv->rvdev.svq); + +#ifdef CONFIG_RPTUN_PING + rptun_ping_init(&priv->rvdev, &priv->ping); +#endif return 0; } @@ -794,6 +803,10 @@ static int rptun_dev_stop(FAR struct remoteproc *rproc) FAR struct metal_list *node; FAR struct rptun_cb_s *cb; +#ifdef CONFIG_RPTUN_PING + rptun_ping_deinit(&priv->ping); +#endif + /* Unregister callback from mbox */ RPTUN_UNREGISTER_CALLBACK(priv->dev); @@ -862,8 +875,13 @@ static int rptun_dev_ioctl(FAR struct file *filep, int cmd, rptun_dev_reset(&priv->rproc, RPTUN_STATUS_PANIC); break; case RPTUNIOC_DUMP: - rpmsg_dump(&priv->rvdev); + rptun_dump(&priv->rvdev); break; +#ifdef CONFIG_RPTUN_PING + case RPTUNIOC_PING: + rptun_ping(&priv->ping, (FAR const struct rptun_ping_s *)arg); + break; +#endif default: ret = -ENOTTY; break; @@ -996,7 +1014,7 @@ int rpmsg_wait(FAR struct rpmsg_endpoint *ept, FAR sem_t *sem) FAR struct rptun_priv_s *priv; int ret; - if (!ept) + if (!ept || !sem) { return -EINVAL; } @@ -1028,7 +1046,7 @@ int rpmsg_post(FAR struct rpmsg_endpoint *ept, FAR sem_t *sem) int semcount; int ret; - if (!ept) + if (!ept || !sem) { return -EINVAL; } @@ -1052,21 +1070,6 @@ FAR const char *rpmsg_get_cpuname(FAR struct rpmsg_device *rdev) return RPTUN_GET_CPUNAME(priv->dev); } -int rpmsg_buffer_nused(FAR struct rpmsg_virtio_device *rvdev, bool rx) -{ - FAR struct virtqueue *vq = rx ? rvdev->rvq : rvdev->svq; - - if ((rpmsg_virtio_get_role(rvdev) == RPMSG_MASTER) ^ rx) - { - return vq->vq_ring.avail->idx - vq->vq_ring.used->idx; - } - else - { - return vq->vq_nentries - - (vq->vq_ring.avail->idx - vq->vq_ring.used->idx); - } -} - int rpmsg_register_callback(FAR void *priv_, rpmsg_dev_cb_t device_created, rpmsg_dev_cb_t device_destroy, @@ -1295,7 +1298,22 @@ int rptun_panic(FAR const char *cpuname) return rptun_reset(cpuname, RPTUN_STATUS_PANIC); } -void rptun_dump(void) +int rptun_buffer_nused(FAR struct rpmsg_virtio_device *rvdev, bool rx) +{ + FAR struct virtqueue *vq = rx ? rvdev->rvq : rvdev->svq; + + if ((rpmsg_virtio_get_role(rvdev) == RPMSG_MASTER) ^ rx) + { + return vq->vq_ring.avail->idx - vq->vq_ring.used->idx; + } + else + { + return vq->vq_nentries - + (vq->vq_ring.avail->idx - vq->vq_ring.used->idx); + } +} + +void rptun_dump_all(void) { FAR struct metal_list *node; @@ -1304,6 +1322,6 @@ void rptun_dump(void) FAR struct rptun_priv_s *priv = metal_container_of(node, struct rptun_priv_s, node); - rpmsg_dump(&priv->rvdev); + rptun_dump(&priv->rvdev); } } diff --git a/drivers/rptun/rptun.h b/drivers/rptun/rptun.h new file mode 100644 index 0000000000..77038b6dfe --- /dev/null +++ b/drivers/rptun/rptun.h @@ -0,0 +1,44 @@ +/**************************************************************************** + * drivers/rptun/rptun.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 __DRIVERS_RPTUN_RPTUN_H +#define __DRIVERS_RPTUN_RPTUN_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +int rptun_buffer_nused(FAR struct rpmsg_virtio_device *rvdev, bool rx); +void rptun_dump(FAR struct rpmsg_virtio_device *rvdev); + +int rptun_ping_init(FAR struct rpmsg_virtio_device *rvdev, + FAR struct rpmsg_endpoint *ept); +void rptun_ping_deinit(FAR struct rpmsg_endpoint *ept); +int rptun_ping(FAR struct rpmsg_endpoint *ept, + FAR const struct rptun_ping_s *ping); + +#endif /* __DRIVERS_RPTUN_RPTUN_H */ diff --git a/drivers/rptun/rpmsg_dump.c b/drivers/rptun/rptun_dump.c similarity index 90% rename from drivers/rptun/rpmsg_dump.c rename to drivers/rptun/rptun_dump.c index 413431a2a1..cb041cf70e 100644 --- a/drivers/rptun/rpmsg_dump.c +++ b/drivers/rptun/rptun_dump.c @@ -1,5 +1,5 @@ /**************************************************************************** - * drivers/rptun/rpmsg_dump.c + * drivers/rptun/rptun_dump.c * * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with @@ -28,11 +28,13 @@ #include +#include "rptun.h" + /**************************************************************************** * Private Functions ****************************************************************************/ -static void rpmsg_dump_addr(FAR struct rpmsg_device *rdev, +static void rptun_dump_addr(FAR struct rpmsg_device *rdev, FAR void *addr, bool rx) { FAR struct rpmsg_hdr *hdr = addr; @@ -47,7 +49,7 @@ static void rpmsg_dump_addr(FAR struct rpmsg_device *rdev, } } -static void rpmsg_dump_buffer(FAR struct rpmsg_virtio_device *rvdev, +static void rptun_dump_buffer(FAR struct rpmsg_virtio_device *rvdev, bool rx) { FAR struct virtqueue *vq = rx ? rvdev->rvq : rvdev->svq; @@ -56,7 +58,7 @@ static void rpmsg_dump_buffer(FAR struct rpmsg_virtio_device *rvdev, int num; int i; - num = rpmsg_buffer_nused(rvdev, rx); + num = rptun_buffer_nused(rvdev, rx); metal_log(METAL_LOG_INFO, " %s buffer, total %d, pending %d\n", rx ? "RX" : "TX", vq->vq_nentries, num); @@ -78,7 +80,7 @@ static void rpmsg_dump_buffer(FAR struct rpmsg_virtio_device *rvdev, vq->vq_ring.desc[desc_idx].addr); if (addr) { - rpmsg_dump_addr(&rvdev->rdev, addr, rx); + rptun_dump_addr(&rvdev->rdev, addr, rx); } } } @@ -87,7 +89,7 @@ static void rpmsg_dump_buffer(FAR struct rpmsg_virtio_device *rvdev, * Public Functions ****************************************************************************/ -void rpmsg_dump(FAR struct rpmsg_virtio_device *rvdev) +void rptun_dump(FAR struct rpmsg_virtio_device *rvdev) { FAR struct rpmsg_device *rdev = &rvdev->rdev; FAR struct rpmsg_endpoint *ept; @@ -114,8 +116,8 @@ void rpmsg_dump(FAR struct rpmsg_virtio_device *rvdev) metal_log(METAL_LOG_INFO, " rpmsg buffer list:\n"); - rpmsg_dump_buffer(rvdev, true); - rpmsg_dump_buffer(rvdev, false); + rptun_dump_buffer(rvdev, true); + rptun_dump_buffer(rvdev, false); metal_mutex_release(&rdev->lock); } diff --git a/drivers/rptun/rptun_ping.c b/drivers/rptun/rptun_ping.c new file mode 100644 index 0000000000..60055cef37 --- /dev/null +++ b/drivers/rptun/rptun_ping.c @@ -0,0 +1,192 @@ +/**************************************************************************** + * drivers/rptun/rptun_ping.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 "rptun.h" + +/**************************************************************************** + * Pre-processor definitions + ****************************************************************************/ + +#ifndef MIN + #define MIN(n,m) (((n) < (m)) ? (n) : (m)) +#endif + +#ifndef MAX + #define MAX(n,m) (((n) < (m)) ? (m) : (n)) +#endif + +#define RPTUN_PING_EPT_NAME "rpmsg-ping" +#define RPTUN_PING_SEND 1 +#define RPTUN_PING_SEND_NOACK 2 +#define RPTUN_PING_ACK 3 + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +begin_packed_struct struct rptun_ping_msg_s +{ + uint32_t cmd; + uint32_t len; + uint64_t cookie; +} end_packed_struct; + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +static int rptun_ping_ept_cb(FAR struct rpmsg_endpoint *ept, + FAR void *data, size_t len, uint32_t src, + FAR void *priv) +{ + FAR struct rptun_ping_msg_s *msg = data; + FAR sem_t *sem = (FAR sem_t *)(uintptr_t)msg->cookie; + + if (msg->cmd == RPTUN_PING_SEND) + { + msg->cmd = RPTUN_PING_ACK; + rpmsg_send(ept, msg, len); + } + else if (msg->cmd == RPTUN_PING_ACK) + { + nxsem_post(sem); + } + + return 0; +} + +static int rptun_ping_once(FAR struct rpmsg_endpoint *ept, + int len, bool ack) +{ + FAR struct rptun_ping_msg_s *msg; + uint32_t space; + int ret; + + msg = rpmsg_get_tx_payload_buffer(ept, &space, true); + if (!msg) + { + return -ENOMEM; + } + + len = MAX(len, sizeof(struct rptun_ping_msg_s)); + len = MIN(len, space); + + memset(msg, 0, len); + + if (ack) + { + sem_t sem; + + msg->cmd = RPTUN_PING_SEND; + msg->len = len; + msg->cookie = (uintptr_t)&sem; + + nxsem_init(&sem, 0, 0); + nxsem_set_protocol(&sem, SEM_PRIO_NONE); + + ret = rpmsg_send_nocopy(ept, msg, len); + if (ret >= 0) + { + nxsem_wait_uninterruptible(&sem); + } + + nxsem_destroy(&sem); + } + else + { + msg->cmd = RPTUN_PING_SEND_NOACK; + msg->len = len; + ret = rpmsg_send_nocopy(ept, msg, len); + } + + return ret; +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +int rptun_ping(FAR struct rpmsg_endpoint *ept, + FAR const struct rptun_ping_s *ping) +{ + uint32_t min = UINT32_MAX; + uint32_t max = 0; + uint64_t total = 0; + struct timespec ts; + int i; + + if (!ept || !ping || ping->times <= 0) + { + return -EINVAL; + } + + for (i = 0; i < ping->times; i++) + { + uint32_t tm = up_perf_gettime(); + + int ret = rptun_ping_once(ept, ping->len, ping->ack); + if (ret < 0) + { + return ret; + } + + tm = up_perf_gettime() - tm; + min = MIN(min, tm); + max = MAX(max, tm); + total += tm; + } + + syslog(LOG_INFO, "current CPU freq: %" PRIu32 ", ping times: %d\n", + up_perf_getfreq(), ping->times); + + up_perf_convert(total / ping->times, &ts); + syslog(LOG_INFO, "avg: s %" PRIu32 ", ns %ld\n", ts.tv_sec, ts.tv_nsec); + + up_perf_convert(min, &ts); + syslog(LOG_INFO, "min: s %" PRIu32 ", ns %ld\n", ts.tv_sec, ts.tv_nsec); + + up_perf_convert(max, &ts); + syslog(LOG_INFO, "max: s %" PRIu32 ", ns %ld\n", ts.tv_sec, ts.tv_nsec); + + return 0; +} + +int rptun_ping_init(FAR struct rpmsg_virtio_device *rvdev, + FAR struct rpmsg_endpoint *ept) +{ + return rpmsg_create_ept(ept, &rvdev->rdev, RPTUN_PING_EPT_NAME, + RPMSG_ADDR_ANY, RPMSG_ADDR_ANY, + rptun_ping_ept_cb, NULL); +} + +void rptun_ping_deinit(FAR struct rpmsg_endpoint *ept) +{ + rpmsg_destroy_ept(ept); +} diff --git a/include/nuttx/rptun/openamp.h b/include/nuttx/rptun/openamp.h index 4188c4107d..833c477a1a 100644 --- a/include/nuttx/rptun/openamp.h +++ b/include/nuttx/rptun/openamp.h @@ -58,8 +58,6 @@ 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_buffer_nused(FAR struct rpmsg_virtio_device *rvdev, bool rx); -void rpmsg_dump(FAR struct rpmsg_virtio_device *rvdev); int rpmsg_register_callback(FAR void *priv, rpmsg_dev_cb_t device_created, diff --git a/include/nuttx/rptun/rptun.h b/include/nuttx/rptun/rptun.h index eb31847010..95fba398ae 100644 --- a/include/nuttx/rptun/rptun.h +++ b/include/nuttx/rptun/rptun.h @@ -41,6 +41,7 @@ #define RPTUNIOC_RESET _RPTUNIOC(3) #define RPTUNIOC_PANIC _RPTUNIOC(4) #define RPTUNIOC_DUMP _RPTUNIOC(5) +#define RPTUNIOC_PING _RPTUNIOC(6) #define RPTUN_NOTIFY_ALL (UINT32_MAX - 0) @@ -303,6 +304,15 @@ struct rptun_dev_s FAR const struct rptun_ops_s *ops; }; +/* used for ioctl RPTUNIOC_PING */ + +struct rptun_ping_s +{ + int times; + int len; + bool ack; +}; + /**************************************************************************** * Public Function Prototypes ****************************************************************************/ @@ -319,7 +329,7 @@ int rptun_initialize(FAR struct rptun_dev_s *dev); int rptun_boot(FAR const char *cpuname); int rptun_reset(FAR const char *cpuname, int value); int rptun_panic(FAR const char *cpuname); -void rptun_dump(void); +void rptun_dump_all(void); #ifdef __cplusplus }