rptun: add ping rpmsg support

Signed-off-by: ligd <liguiding1@xiaomi.com>
This commit is contained in:
ligd 2022-02-16 15:23:49 +08:00 committed by Petro Karashchenko
parent a19aef4d36
commit 759898c090
8 changed files with 308 additions and 33 deletions

View File

@ -52,4 +52,11 @@ config RPTUN_PM
goto RAM-retention mode, can't access from another CPU. goto RAM-retention mode, can't access from another CPU.
So, we provide this method to resolve this. 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 endif # RPTUN

View File

@ -22,7 +22,11 @@
ifeq ($(CONFIG_RPTUN),y) 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 DEPPATH += --dep-path rptun
VPATH += :rptun VPATH += :rptun

View File

@ -39,6 +39,8 @@
#include <nuttx/wqueue.h> #include <nuttx/wqueue.h>
#include <metal/utilities.h> #include <metal/utilities.h>
#include "rptun.h"
/**************************************************************************** /****************************************************************************
* Pre-processor Definitions * Pre-processor Definitions
****************************************************************************/ ****************************************************************************/
@ -81,6 +83,9 @@ struct rptun_priv_s
#ifdef CONFIG_RPTUN_PM #ifdef CONFIG_RPTUN_PM
bool stay; bool stay;
#endif #endif
#ifdef CONFIG_RPTUN_PING
struct rpmsg_endpoint ping;
#endif
}; };
struct rptun_bind_s struct rptun_bind_s
@ -268,7 +273,7 @@ static inline void rptun_pm_action(FAR struct rptun_priv_s *priv,
priv->stay = true; 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); pm_relax(0, PM_IDLE);
priv->stay = false; priv->stay = false;
@ -785,6 +790,10 @@ static int rptun_dev_start(FAR struct remoteproc *rproc)
rptun_unlock(); rptun_unlock();
virtqueue_enable_cb(priv->rvdev.svq); virtqueue_enable_cb(priv->rvdev.svq);
#ifdef CONFIG_RPTUN_PING
rptun_ping_init(&priv->rvdev, &priv->ping);
#endif
return 0; return 0;
} }
@ -794,6 +803,10 @@ static int rptun_dev_stop(FAR struct remoteproc *rproc)
FAR struct metal_list *node; FAR struct metal_list *node;
FAR struct rptun_cb_s *cb; FAR struct rptun_cb_s *cb;
#ifdef CONFIG_RPTUN_PING
rptun_ping_deinit(&priv->ping);
#endif
/* Unregister callback from mbox */ /* Unregister callback from mbox */
RPTUN_UNREGISTER_CALLBACK(priv->dev); 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); rptun_dev_reset(&priv->rproc, RPTUN_STATUS_PANIC);
break; break;
case RPTUNIOC_DUMP: case RPTUNIOC_DUMP:
rpmsg_dump(&priv->rvdev); rptun_dump(&priv->rvdev);
break; break;
#ifdef CONFIG_RPTUN_PING
case RPTUNIOC_PING:
rptun_ping(&priv->ping, (FAR const struct rptun_ping_s *)arg);
break;
#endif
default: default:
ret = -ENOTTY; ret = -ENOTTY;
break; break;
@ -996,7 +1014,7 @@ int rpmsg_wait(FAR struct rpmsg_endpoint *ept, FAR sem_t *sem)
FAR struct rptun_priv_s *priv; FAR struct rptun_priv_s *priv;
int ret; int ret;
if (!ept) if (!ept || !sem)
{ {
return -EINVAL; return -EINVAL;
} }
@ -1028,7 +1046,7 @@ int rpmsg_post(FAR struct rpmsg_endpoint *ept, FAR sem_t *sem)
int semcount; int semcount;
int ret; int ret;
if (!ept) if (!ept || !sem)
{ {
return -EINVAL; return -EINVAL;
} }
@ -1052,21 +1070,6 @@ FAR const char *rpmsg_get_cpuname(FAR struct rpmsg_device *rdev)
return RPTUN_GET_CPUNAME(priv->dev); 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_, int rpmsg_register_callback(FAR void *priv_,
rpmsg_dev_cb_t device_created, rpmsg_dev_cb_t device_created,
rpmsg_dev_cb_t device_destroy, rpmsg_dev_cb_t device_destroy,
@ -1295,7 +1298,22 @@ int rptun_panic(FAR const char *cpuname)
return rptun_reset(cpuname, RPTUN_STATUS_PANIC); 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; FAR struct metal_list *node;
@ -1304,6 +1322,6 @@ void rptun_dump(void)
FAR struct rptun_priv_s *priv = FAR struct rptun_priv_s *priv =
metal_container_of(node, struct rptun_priv_s, node); metal_container_of(node, struct rptun_priv_s, node);
rpmsg_dump(&priv->rvdev); rptun_dump(&priv->rvdev);
} }
} }

44
drivers/rptun/rptun.h Normal file
View File

@ -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 <nuttx/rptun/rptun.h>
#include <openamp/open_amp.h>
/****************************************************************************
* 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 */

View File

@ -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 * Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with * contributor license agreements. See the NOTICE file distributed with
@ -28,11 +28,13 @@
#include <rpmsg/rpmsg_internal.h> #include <rpmsg/rpmsg_internal.h>
#include "rptun.h"
/**************************************************************************** /****************************************************************************
* Private Functions * 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 void *addr, bool rx)
{ {
FAR struct rpmsg_hdr *hdr = addr; 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) bool rx)
{ {
FAR struct virtqueue *vq = rx ? rvdev->rvq : rvdev->svq; 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 num;
int i; int i;
num = rpmsg_buffer_nused(rvdev, rx); num = rptun_buffer_nused(rvdev, rx);
metal_log(METAL_LOG_INFO, metal_log(METAL_LOG_INFO,
" %s buffer, total %d, pending %d\n", " %s buffer, total %d, pending %d\n",
rx ? "RX" : "TX", vq->vq_nentries, num); 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); vq->vq_ring.desc[desc_idx].addr);
if (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 * 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_device *rdev = &rvdev->rdev;
FAR struct rpmsg_endpoint *ept; 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"); metal_log(METAL_LOG_INFO, " rpmsg buffer list:\n");
rpmsg_dump_buffer(rvdev, true); rptun_dump_buffer(rvdev, true);
rpmsg_dump_buffer(rvdev, false); rptun_dump_buffer(rvdev, false);
metal_mutex_release(&rdev->lock); metal_mutex_release(&rdev->lock);
} }

192
drivers/rptun/rptun_ping.c Normal file
View File

@ -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 <nuttx/config.h>
#include <nuttx/arch.h>
#include <inttypes.h>
#include <string.h>
#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);
}

View File

@ -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); int rpmsg_post(FAR struct rpmsg_endpoint *ept, FAR sem_t *sem);
const char *rpmsg_get_cpuname(FAR struct rpmsg_device *rdev); 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, int rpmsg_register_callback(FAR void *priv,
rpmsg_dev_cb_t device_created, rpmsg_dev_cb_t device_created,

View File

@ -41,6 +41,7 @@
#define RPTUNIOC_RESET _RPTUNIOC(3) #define RPTUNIOC_RESET _RPTUNIOC(3)
#define RPTUNIOC_PANIC _RPTUNIOC(4) #define RPTUNIOC_PANIC _RPTUNIOC(4)
#define RPTUNIOC_DUMP _RPTUNIOC(5) #define RPTUNIOC_DUMP _RPTUNIOC(5)
#define RPTUNIOC_PING _RPTUNIOC(6)
#define RPTUN_NOTIFY_ALL (UINT32_MAX - 0) #define RPTUN_NOTIFY_ALL (UINT32_MAX - 0)
@ -303,6 +304,15 @@ struct rptun_dev_s
FAR const struct rptun_ops_s *ops; 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 * 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_boot(FAR const char *cpuname);
int rptun_reset(FAR const char *cpuname, int value); int rptun_reset(FAR const char *cpuname, int value);
int rptun_panic(FAR const char *cpuname); int rptun_panic(FAR const char *cpuname);
void rptun_dump(void); void rptun_dump_all(void);
#ifdef __cplusplus #ifdef __cplusplus
} }