rpmsg/rpmsg_virtio_lite: rename rpmsg_virtio to rpmsg_virtio_lite
Because rpmsg_virtio_lite is a better name to inform user that the rpmsg virtio (original name) is a lite implementation of rpmsg virtio. Signed-off-by: Bowen Wang <wangbowen6@xiaomi.com>
This commit is contained in:
parent
db1ebe0095
commit
f0a3c43a54
12 changed files with 962 additions and 789 deletions
|
@ -254,7 +254,7 @@ ifeq ($(CONFIG_SIM_LIBUSB),y)
|
|||
endif
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_RPMSG_VIRTIO),y)
|
||||
ifeq ($(CONFIG_RPMSG_VIRTIO_LITE),y)
|
||||
CSRCS += sim_rpmsg_virtio.c
|
||||
endif
|
||||
|
||||
|
|
|
@ -119,7 +119,7 @@ if(CONFIG_LIBM_TOOLCHAIN)
|
|||
list(APPEND STDLIBS m)
|
||||
endif()
|
||||
|
||||
if(CONFIG_RPMSG_VIRTIO)
|
||||
if(CONFIG_RPMSG_VIRTIO_LITE)
|
||||
list(APPEND SRCS sim_rpmsg_vritio.c)
|
||||
endif()
|
||||
|
||||
|
|
|
@ -415,7 +415,7 @@ int sim_rptun_init(const char *shmemname, const char *cpuname, int master);
|
|||
|
||||
/* sim_rpmsg_virtio.c *******************************************************/
|
||||
|
||||
#ifdef CONFIG_RPMSG_VIRTIO
|
||||
#ifdef CONFIG_RPMSG_VIRTIO_LITE
|
||||
int sim_rpmsg_virtio_init(const char *shmemname, const char *cpuname,
|
||||
bool master);
|
||||
#endif
|
||||
|
|
|
@ -29,7 +29,7 @@
|
|||
#include <nuttx/drivers/addrenv.h>
|
||||
#include <nuttx/kmalloc.h>
|
||||
#include <nuttx/nuttx.h>
|
||||
#include <nuttx/rpmsg/rpmsg_virtio.h>
|
||||
#include <nuttx/rpmsg/rpmsg_virtio_lite.h>
|
||||
#include <nuttx/wdog.h>
|
||||
|
||||
#include "sim_internal.h"
|
||||
|
@ -46,18 +46,18 @@
|
|||
|
||||
struct sim_rpmsg_virtio_shmem_s
|
||||
{
|
||||
volatile uintptr_t base;
|
||||
volatile unsigned int seqs;
|
||||
volatile unsigned int seqm;
|
||||
volatile unsigned int boots;
|
||||
volatile unsigned int bootm;
|
||||
struct rpmsg_virtio_rsc_s rsc;
|
||||
char buf[0x10000];
|
||||
volatile uintptr_t base;
|
||||
volatile unsigned int seqs;
|
||||
volatile unsigned int seqm;
|
||||
volatile unsigned int boots;
|
||||
volatile unsigned int bootm;
|
||||
struct rpmsg_virtio_lite_rsc_s rsc;
|
||||
char buf[0x10000];
|
||||
};
|
||||
|
||||
struct sim_rpmsg_virtio_dev_s
|
||||
{
|
||||
struct rpmsg_virtio_s dev;
|
||||
struct rpmsg_virtio_lite_s dev;
|
||||
rpmsg_virtio_callback_t callback;
|
||||
void *arg;
|
||||
int master;
|
||||
|
@ -76,7 +76,8 @@ struct sim_rpmsg_virtio_dev_s
|
|||
* Private Functions
|
||||
****************************************************************************/
|
||||
|
||||
static const char *sim_rpmsg_virtio_get_cpuname(struct rpmsg_virtio_s *dev)
|
||||
static const char *
|
||||
sim_rpmsg_virtio_get_cpuname(struct rpmsg_virtio_lite_s *dev)
|
||||
{
|
||||
struct sim_rpmsg_virtio_dev_s *priv =
|
||||
container_of(dev, struct sim_rpmsg_virtio_dev_s, dev);
|
||||
|
@ -84,13 +85,13 @@ static const char *sim_rpmsg_virtio_get_cpuname(struct rpmsg_virtio_s *dev)
|
|||
return priv->cpuname;
|
||||
}
|
||||
|
||||
static struct rpmsg_virtio_rsc_s *
|
||||
sim_rpmsg_virtio_get_resource(struct rpmsg_virtio_s *dev)
|
||||
static struct rpmsg_virtio_lite_rsc_s *
|
||||
sim_rpmsg_virtio_get_resource(struct rpmsg_virtio_lite_s *dev)
|
||||
{
|
||||
struct sim_rpmsg_virtio_dev_s *priv =
|
||||
container_of(dev, struct sim_rpmsg_virtio_dev_s, dev);
|
||||
struct rpmsg_virtio_rsc_s *rsc;
|
||||
struct rpmsg_virtio_cmd_s *cmd;
|
||||
struct rpmsg_virtio_lite_rsc_s *rsc;
|
||||
struct rpmsg_virtio_lite_cmd_s *cmd;
|
||||
|
||||
priv->shmem = host_allocshmem(priv->shmemname, sizeof(*priv->shmem));
|
||||
if (!priv->shmem)
|
||||
|
@ -141,7 +142,7 @@ sim_rpmsg_virtio_get_resource(struct rpmsg_virtio_s *dev)
|
|||
return rsc;
|
||||
}
|
||||
|
||||
static int sim_rpmsg_virtio_is_master(struct rpmsg_virtio_s *dev)
|
||||
static int sim_rpmsg_virtio_is_master(struct rpmsg_virtio_lite_s *dev)
|
||||
{
|
||||
struct sim_rpmsg_virtio_dev_s *priv =
|
||||
container_of(dev, struct sim_rpmsg_virtio_dev_s, dev);
|
||||
|
@ -150,7 +151,7 @@ static int sim_rpmsg_virtio_is_master(struct rpmsg_virtio_s *dev)
|
|||
}
|
||||
|
||||
static int
|
||||
sim_rpmsg_virtio_register_callback(struct rpmsg_virtio_s *dev,
|
||||
sim_rpmsg_virtio_register_callback(struct rpmsg_virtio_lite_s *dev,
|
||||
rpmsg_virtio_callback_t callback,
|
||||
void *arg)
|
||||
{
|
||||
|
@ -184,7 +185,7 @@ static void sim_rpmsg_virtio_work(wdparm_t arg)
|
|||
|
||||
if (should_notify && dev->callback != NULL)
|
||||
{
|
||||
dev->callback(dev->arg, RPMSG_VIRTIO_NOTIFY_ALL);
|
||||
dev->callback(dev->arg, RPMSG_VIRTIO_LITE_NOTIFY_ALL);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -192,7 +193,8 @@ static void sim_rpmsg_virtio_work(wdparm_t arg)
|
|||
sim_rpmsg_virtio_work, (wdparm_t)dev);
|
||||
}
|
||||
|
||||
static int sim_rpmsg_virtio_notify(struct rpmsg_virtio_s *dev, uint32_t vqid)
|
||||
static int sim_rpmsg_virtio_notify(struct rpmsg_virtio_lite_s *dev,
|
||||
uint32_t vqid)
|
||||
{
|
||||
struct sim_rpmsg_virtio_dev_s *priv =
|
||||
container_of(dev, struct sim_rpmsg_virtio_dev_s, dev);
|
||||
|
@ -213,7 +215,7 @@ static int sim_rpmsg_virtio_notify(struct rpmsg_virtio_s *dev, uint32_t vqid)
|
|||
* Private Data
|
||||
****************************************************************************/
|
||||
|
||||
static const struct rpmsg_virtio_ops_s g_sim_rpmsg_virtio_ops =
|
||||
static const struct rpmsg_virtio_lite_ops_s g_sim_rpmsg_virtio_ops =
|
||||
{
|
||||
.get_cpuname = sim_rpmsg_virtio_get_cpuname,
|
||||
.get_resource = sim_rpmsg_virtio_get_resource,
|
||||
|
@ -243,7 +245,7 @@ int sim_rpmsg_virtio_init(const char *shmemname, const char *cpuname,
|
|||
strlcpy(priv->cpuname, cpuname, RPMSG_NAME_SIZE);
|
||||
strlcpy(priv->shmemname, shmemname, RPMSG_NAME_SIZE);
|
||||
|
||||
ret = rpmsg_virtio_initialize(&priv->dev);
|
||||
ret = rpmsg_virtio_lite_initialize(&priv->dev);
|
||||
if (ret < 0)
|
||||
{
|
||||
kmm_free(priv);
|
||||
|
|
|
@ -485,7 +485,7 @@ int sim_bringup(void)
|
|||
# endif
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_RPMSG_VIRTIO
|
||||
#ifdef CONFIG_RPMSG_VIRTIO_LITE
|
||||
# ifdef CONFIG_SIM_RPMSG_MASTER
|
||||
sim_rpmsg_virtio_init("server-proxy", "proxy", true);
|
||||
# else
|
||||
|
|
|
@ -47,8 +47,8 @@ if(CONFIG_RPMSG)
|
|||
list(APPEND SRCS rpmsg_port_uart.c)
|
||||
endif()
|
||||
|
||||
if(CONFIG_RPMSG_VIRTIO)
|
||||
list(APPEND SRCS rpmsg_virtio.c)
|
||||
if(CONFIG_RPMSG_VIRTIO_LITE)
|
||||
list(APPEND SRCS rpmsg_virtio_lite.c)
|
||||
endif()
|
||||
|
||||
if(CONFIG_RPMSG_VIRTIO_IVSHMEM)
|
||||
|
|
|
@ -107,32 +107,50 @@ config RPMSG_PORT_UART_DEBUG
|
|||
|
||||
endif # RPMSG_PORT_UART
|
||||
|
||||
config RPMSG_VIRTIO
|
||||
config RPMSG_VIRTIO_LITE
|
||||
bool "rpmsg virtio transport support"
|
||||
default n
|
||||
select RPMSG
|
||||
|
||||
if RPMSG_VIRTIO
|
||||
if RPMSG_VIRTIO_LITE
|
||||
|
||||
config RPMSG_VIRTIO_PRIORITY
|
||||
int "rpmsg virtio rx thread priority"
|
||||
config RPMSG_VIRTIO_LITE_PRIORITY
|
||||
int "rpmsg virtio lite rx thread priority"
|
||||
default 224
|
||||
|
||||
config RPMSG_VIRTIO_STACKSIZE
|
||||
int "rpmsg virtio rx thread stack size"
|
||||
config RPMSG_VIRTIO_LITE_STACKSIZE
|
||||
int "rpmsg virtio lite rx thread stack size"
|
||||
default DEFAULT_TASK_STACKSIZE
|
||||
|
||||
config RPMSG_VIRTIO_IVSHMEM
|
||||
bool "rpmsg virtio ivshmem support"
|
||||
bool "rpmsg virtio lite ivshmem support"
|
||||
default n
|
||||
depends on PCI_IVSHMEM
|
||||
---help---
|
||||
This is rpmsg virtio driver based on pci ivshmem.
|
||||
|
||||
config RPMSG_VIRTIO_LITE_PM
|
||||
bool "rpmsg virtio lite power management"
|
||||
depends on PM
|
||||
default n
|
||||
---help---
|
||||
If TX/RX buffer is supplied and powered by each CPU.
|
||||
And when one CPU in DEEP sleep, then it's buffer will
|
||||
goto RAM-retention mode, can't access from another CPU.
|
||||
So, we provide this method to resolve this.
|
||||
|
||||
config RPMSG_VIRTIO_LITE_PM_AUTORELAX
|
||||
bool "rpmsg virtio lite pm autorelax"
|
||||
depends on RPMSG_VIRTIO_LITE_PM
|
||||
default y
|
||||
---help---
|
||||
use wd_timer to auto relax pm
|
||||
|
||||
|
||||
if RPMSG_VIRTIO_IVSHMEM
|
||||
|
||||
config RPMSG_VIRTIO_IVSHMEM_NAME
|
||||
string "rpmsg virtio ivshmem name"
|
||||
string "rpmsg virtio lite ivshmem name"
|
||||
---help---
|
||||
Using this config to custom the rpmsg virtio ivshmem id, cpuname and role,
|
||||
using ";" to split the names.
|
||||
|
@ -141,14 +159,14 @@ config RPMSG_VIRTIO_IVSHMEM_NAME
|
|||
with remote cpu ids: "0","1", names: "cpu1", "cpu2", and roles: "master", "slave"
|
||||
|
||||
config RPMSG_VIRTIO_IVSHMEM_BUFFSIZE
|
||||
int "rpmsg virtio ivshmem rpmsg buffer size"
|
||||
int "rpmsg virtio lite ivshmem rpmsg buffer size"
|
||||
default 2048
|
||||
---help---
|
||||
The rpmsg buffer size in share memory, the RX and TX buffer size
|
||||
are same for now.
|
||||
|
||||
config RPMSG_VIRTIO_IVSHMEM_BUFFNUM
|
||||
int "rpmsg virtio ivshmem rpmsg buffer number"
|
||||
int "rpmsg virtio lite ivshmem rpmsg buffer number"
|
||||
default 8
|
||||
---help---
|
||||
The rpmsg virtio buffer number in share memory, the RX and TX buffer number
|
||||
|
|
|
@ -51,8 +51,8 @@ ifeq ($(CONFIG_RPMSG_PORT_UART),y)
|
|||
CSRCS += rpmsg_port_uart.c
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_RPMSG_VIRTIO),y)
|
||||
CSRCS += rpmsg_virtio.c
|
||||
ifeq ($(CONFIG_RPMSG_VIRTIO_LITE),y)
|
||||
CSRCS += rpmsg_virtio_lite.c
|
||||
CFLAGS += ${INCDIR_PREFIX}$(TOPDIR)$(DELIM)openamp$(DELIM)open-amp$(DELIM)lib
|
||||
endif
|
||||
|
||||
|
|
|
@ -1,684 +0,0 @@
|
|||
/****************************************************************************
|
||||
* drivers/rpmsg/rpmsg_virtio.c
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* 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 <debug.h>
|
||||
#include <stdio.h>
|
||||
#include <sys/param.h>
|
||||
|
||||
#include <nuttx/kmalloc.h>
|
||||
#include <nuttx/kthread.h>
|
||||
#include <nuttx/nuttx.h>
|
||||
#include <nuttx/semaphore.h>
|
||||
#include <nuttx/rpmsg/rpmsg_virtio.h>
|
||||
#include <rpmsg/rpmsg_internal.h>
|
||||
|
||||
/****************************************************************************
|
||||
* Pre-processor Definitions
|
||||
****************************************************************************/
|
||||
|
||||
#define RPMSG_VIRTIO_TIMEOUT_MS 20
|
||||
#define RPMSG_VIRTIO_NOTIFYID 0
|
||||
|
||||
/****************************************************************************
|
||||
* Private Types
|
||||
****************************************************************************/
|
||||
|
||||
struct rpmsg_virtio_priv_s
|
||||
{
|
||||
struct rpmsg_s rpmsg;
|
||||
struct rpmsg_virtio_device rvdev;
|
||||
FAR struct rpmsg_virtio_s *dev;
|
||||
FAR struct rpmsg_virtio_rsc_s *rsc;
|
||||
struct virtio_device vdev;
|
||||
struct rpmsg_virtio_shm_pool pool[2];
|
||||
struct virtio_vring_info rvrings[2];
|
||||
sem_t semtx;
|
||||
sem_t semrx;
|
||||
pid_t tid;
|
||||
};
|
||||
|
||||
/****************************************************************************
|
||||
* Private Function Prototypes
|
||||
****************************************************************************/
|
||||
|
||||
static int rpmsg_virtio_wait(FAR struct rpmsg_s *rpmsg, FAR sem_t *sem);
|
||||
static int rpmsg_virtio_post(FAR struct rpmsg_s *rpmsg, FAR sem_t *sem);
|
||||
static void rpmsg_virtio_panic(FAR struct rpmsg_s *rpmsg);
|
||||
static void rpmsg_virtio_dump(FAR struct rpmsg_s *rpmsg);
|
||||
static FAR const char *
|
||||
rpmsg_virtio_get_local_cpuname(FAR struct rpmsg_s *rpmsg);
|
||||
static FAR const char *rpmsg_virtio_get_cpuname(FAR struct rpmsg_s *rpmsg);
|
||||
|
||||
static int rpmsg_virtio_create_virtqueues_(FAR struct virtio_device *vdev,
|
||||
unsigned int flags,
|
||||
unsigned int nvqs,
|
||||
FAR const char *names[],
|
||||
vq_callback callbacks[],
|
||||
FAR void *callback_args[]);
|
||||
static uint8_t rpmsg_virtio_get_status_(FAR struct virtio_device *dev);
|
||||
static void rpmsg_virtio_set_status_(FAR struct virtio_device *dev,
|
||||
uint8_t status);
|
||||
static uint64_t rpmsg_virtio_get_features_(FAR struct virtio_device *dev);
|
||||
static void rpmsg_virtio_set_features(FAR struct virtio_device *dev,
|
||||
uint64_t feature);
|
||||
static void rpmsg_virtio_notify(FAR struct virtqueue *vq);
|
||||
|
||||
/****************************************************************************
|
||||
* Private Data
|
||||
****************************************************************************/
|
||||
|
||||
static const struct rpmsg_ops_s g_rpmsg_virtio_ops =
|
||||
{
|
||||
.wait = rpmsg_virtio_wait,
|
||||
.post = rpmsg_virtio_post,
|
||||
.panic = rpmsg_virtio_panic,
|
||||
.dump = rpmsg_virtio_dump,
|
||||
.get_local_cpuname = rpmsg_virtio_get_local_cpuname,
|
||||
.get_cpuname = rpmsg_virtio_get_cpuname,
|
||||
};
|
||||
|
||||
static const struct virtio_dispatch g_rpmsg_virtio_dispatch =
|
||||
{
|
||||
.create_virtqueues = rpmsg_virtio_create_virtqueues_,
|
||||
.get_status = rpmsg_virtio_get_status_,
|
||||
.set_status = rpmsg_virtio_set_status_,
|
||||
.get_features = rpmsg_virtio_get_features_,
|
||||
.set_features = rpmsg_virtio_set_features,
|
||||
.notify = rpmsg_virtio_notify,
|
||||
};
|
||||
|
||||
/****************************************************************************
|
||||
* Private Functions
|
||||
****************************************************************************/
|
||||
|
||||
static FAR struct rpmsg_virtio_priv_s *
|
||||
rpmsg_virtio_get_priv(FAR struct virtio_device *vdev)
|
||||
{
|
||||
FAR struct rpmsg_virtio_device *rvdev = vdev->priv;
|
||||
|
||||
return metal_container_of(rvdev, struct rpmsg_virtio_priv_s, rvdev);
|
||||
}
|
||||
|
||||
static int rpmsg_virtio_create_virtqueues_(FAR struct virtio_device *vdev,
|
||||
unsigned int flags,
|
||||
unsigned int nvqs,
|
||||
FAR const char *names[],
|
||||
vq_callback callbacks[],
|
||||
FAR void *callback_args[])
|
||||
{
|
||||
int ret;
|
||||
int i;
|
||||
|
||||
if (nvqs > vdev->vrings_num)
|
||||
{
|
||||
return ERROR_VQUEUE_INVLD_PARAM;
|
||||
}
|
||||
|
||||
/* Initialize virtqueue for each vring */
|
||||
|
||||
for (i = 0; i < nvqs; i++)
|
||||
{
|
||||
FAR struct virtio_vring_info *vinfo = &vdev->vrings_info[i];
|
||||
FAR struct vring_alloc_info *valloc = &vinfo->info;
|
||||
#ifndef CONFIG_OPENAMP_VIRTIO_DEVICE_ONLY
|
||||
if (vdev->role == VIRTIO_DEV_DRIVER)
|
||||
{
|
||||
size_t offset;
|
||||
|
||||
offset = metal_io_virt_to_offset(vinfo->io, valloc->vaddr);
|
||||
metal_io_block_set(vinfo->io, offset, 0,
|
||||
vring_size(valloc->num_descs, valloc->align));
|
||||
}
|
||||
#endif
|
||||
|
||||
ret = virtqueue_create(vdev, i, names[i], valloc,
|
||||
callbacks[i], vdev->func->notify,
|
||||
vinfo->vq);
|
||||
if (ret < 0)
|
||||
{
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static uint8_t rpmsg_virtio_get_status_(FAR struct virtio_device *vdev)
|
||||
{
|
||||
FAR struct rpmsg_virtio_priv_s *priv = rpmsg_virtio_get_priv(vdev);
|
||||
|
||||
return priv->rsc->rpmsg_vdev.status;
|
||||
}
|
||||
|
||||
static void rpmsg_virtio_set_status_(FAR struct virtio_device *vdev,
|
||||
uint8_t status)
|
||||
{
|
||||
FAR struct rpmsg_virtio_priv_s *priv = rpmsg_virtio_get_priv(vdev);
|
||||
|
||||
priv->rsc->rpmsg_vdev.status = status;
|
||||
}
|
||||
|
||||
static uint64_t rpmsg_virtio_get_features_(FAR struct virtio_device *vdev)
|
||||
{
|
||||
FAR struct rpmsg_virtio_priv_s *priv = rpmsg_virtio_get_priv(vdev);
|
||||
|
||||
return priv->rsc->rpmsg_vdev.dfeatures;
|
||||
}
|
||||
|
||||
static void rpmsg_virtio_set_features(FAR struct virtio_device *vdev,
|
||||
uint64_t features)
|
||||
{
|
||||
FAR struct rpmsg_virtio_priv_s *priv = rpmsg_virtio_get_priv(vdev);
|
||||
|
||||
priv->rsc->rpmsg_vdev.gfeatures = features;
|
||||
}
|
||||
|
||||
static void rpmsg_virtio_notify(FAR struct virtqueue *vq)
|
||||
{
|
||||
FAR struct virtio_device *vdev = vq->vq_dev;
|
||||
FAR struct rpmsg_virtio_priv_s *priv = rpmsg_virtio_get_priv(vdev);
|
||||
|
||||
RPMSG_VIRTIO_NOTIFY(priv->dev, vdev->vrings_info->notifyid);
|
||||
}
|
||||
|
||||
static bool rpmsg_virtio_is_recursive(FAR struct rpmsg_virtio_priv_s *priv)
|
||||
{
|
||||
return nxsched_gettid() == priv->tid;
|
||||
}
|
||||
|
||||
static int rpmsg_virtio_wait(FAR struct rpmsg_s *rpmsg, FAR sem_t *sem)
|
||||
{
|
||||
FAR struct rpmsg_virtio_priv_s *priv =
|
||||
(FAR struct rpmsg_virtio_priv_s *)rpmsg;
|
||||
int ret;
|
||||
|
||||
if (!rpmsg_virtio_is_recursive(priv))
|
||||
{
|
||||
return nxsem_wait_uninterruptible(sem);
|
||||
}
|
||||
|
||||
while (1)
|
||||
{
|
||||
ret = nxsem_trywait(sem);
|
||||
if (ret >= 0)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
nxsem_wait(&priv->semtx);
|
||||
virtqueue_notification(priv->rvdev.rvq);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void rpmsg_virtio_wakeup_tx(FAR struct rpmsg_virtio_priv_s *priv)
|
||||
{
|
||||
int semcount;
|
||||
|
||||
nxsem_get_value(&priv->semtx, &semcount);
|
||||
while (semcount++ < 1)
|
||||
{
|
||||
nxsem_post(&priv->semtx);
|
||||
}
|
||||
}
|
||||
|
||||
static int rpmsg_virtio_post(FAR struct rpmsg_s *rpmsg, FAR sem_t *sem)
|
||||
{
|
||||
FAR struct rpmsg_virtio_priv_s *priv =
|
||||
(FAR struct rpmsg_virtio_priv_s *)rpmsg;
|
||||
int semcount;
|
||||
int ret;
|
||||
|
||||
nxsem_get_value(sem, &semcount);
|
||||
ret = nxsem_post(sem);
|
||||
|
||||
if (priv && semcount >= 0)
|
||||
{
|
||||
rpmsg_virtio_wakeup_tx(priv);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void rpmsg_virtio_panic(FAR struct rpmsg_s *rpmsg)
|
||||
{
|
||||
FAR struct rpmsg_virtio_priv_s *priv =
|
||||
(FAR struct rpmsg_virtio_priv_s *)rpmsg;
|
||||
FAR struct rpmsg_virtio_cmd_s *cmd = RPMSG_VIRTIO_RSC2CMD(priv->rsc);
|
||||
|
||||
if (RPMSG_VIRTIO_IS_MASTER(priv->dev))
|
||||
{
|
||||
cmd->cmd_master = RPMSG_VIRTIO_CMD(RPMSG_VIRTIO_CMD_PANIC, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
cmd->cmd_slave = RPMSG_VIRTIO_CMD(RPMSG_VIRTIO_CMD_PANIC, 0);
|
||||
}
|
||||
|
||||
rpmsg_virtio_notify(priv->vdev.vrings_info->vq);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_OPENAMP_DEBUG
|
||||
static int rpmsg_virtio_buffer_nused(FAR struct rpmsg_virtio_device *rvdev,
|
||||
bool rx)
|
||||
{
|
||||
FAR struct virtqueue *vq = rx ? rvdev->rvq : rvdev->svq;
|
||||
uint16_t nused = vq->vq_ring.avail->idx - vq->vq_ring.used->idx;
|
||||
|
||||
if ((rpmsg_virtio_get_role(rvdev) == RPMSG_HOST) ^ rx)
|
||||
{
|
||||
return nused;
|
||||
}
|
||||
else
|
||||
{
|
||||
return vq->vq_nentries - nused;
|
||||
}
|
||||
}
|
||||
|
||||
static void rpmsg_virtio_dump_buffer(FAR struct rpmsg_virtio_device *rvdev,
|
||||
bool rx)
|
||||
{
|
||||
FAR struct virtqueue *vq = rx ? rvdev->rvq : rvdev->svq;
|
||||
int num;
|
||||
int i;
|
||||
|
||||
num = rpmsg_virtio_buffer_nused(rvdev, rx);
|
||||
metal_log(METAL_LOG_EMERGENCY,
|
||||
" %s buffer, total %d, pending %d\n",
|
||||
rx ? "RX" : "TX", vq->vq_nentries, num);
|
||||
|
||||
for (i = 0; i < num; i++)
|
||||
{
|
||||
FAR void *addr;
|
||||
int desc_idx;
|
||||
|
||||
if ((rpmsg_virtio_get_role(rvdev) == RPMSG_HOST) ^ rx)
|
||||
{
|
||||
desc_idx = (vq->vq_ring.used->idx + i) & (vq->vq_nentries - 1);
|
||||
desc_idx = vq->vq_ring.avail->ring[desc_idx];
|
||||
}
|
||||
else
|
||||
{
|
||||
desc_idx = (vq->vq_ring.avail->idx + i) & (vq->vq_nentries - 1);
|
||||
desc_idx = vq->vq_ring.used->ring[desc_idx].id;
|
||||
}
|
||||
|
||||
addr = metal_io_phys_to_virt(vq->shm_io,
|
||||
vq->vq_ring.desc[desc_idx].addr);
|
||||
if (addr)
|
||||
{
|
||||
FAR struct rpmsg_hdr *hdr = addr;
|
||||
FAR struct rpmsg_endpoint *ept;
|
||||
|
||||
ept = rpmsg_get_ept_from_addr(&rvdev->rdev,
|
||||
rx ? hdr->dst : hdr->src);
|
||||
if (ept)
|
||||
{
|
||||
metal_log(METAL_LOG_EMERGENCY,
|
||||
" %s buffer %p hold by %s\n",
|
||||
rx ? "RX" : "TX", hdr, ept->name);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void rpmsg_virtio_dump(FAR struct rpmsg_s *rpmsg)
|
||||
{
|
||||
FAR struct rpmsg_virtio_priv_s *priv =
|
||||
(FAR struct rpmsg_virtio_priv_s *)rpmsg;
|
||||
FAR struct rpmsg_virtio_device *rvdev = &priv->rvdev;
|
||||
FAR struct rpmsg_device *rdev = rpmsg->rdev;
|
||||
FAR struct rpmsg_endpoint *ept;
|
||||
FAR struct metal_list *node;
|
||||
bool needlock = true;
|
||||
|
||||
if (!rvdev->vdev)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (up_interrupt_context() || sched_idletask() ||
|
||||
nxmutex_is_hold(&rdev->lock))
|
||||
{
|
||||
needlock = false;
|
||||
}
|
||||
|
||||
if (needlock)
|
||||
{
|
||||
metal_mutex_acquire(&rdev->lock);
|
||||
}
|
||||
|
||||
metal_log(METAL_LOG_EMERGENCY,
|
||||
"Dump rpmsg info between cpu (master: %s)%s <==> %s:\n",
|
||||
rpmsg_virtio_get_role(rvdev) == RPMSG_HOST ? "yes" : "no",
|
||||
CONFIG_RPMSG_LOCAL_CPUNAME, rpmsg_get_cpuname(rdev));
|
||||
|
||||
metal_log(METAL_LOG_EMERGENCY, "rpmsg vq RX:\n");
|
||||
virtqueue_dump(rvdev->rvq);
|
||||
metal_log(METAL_LOG_EMERGENCY, "rpmsg vq TX:\n");
|
||||
virtqueue_dump(rvdev->svq);
|
||||
|
||||
metal_log(METAL_LOG_EMERGENCY, " rpmsg ept list:\n");
|
||||
|
||||
metal_list_for_each(&rdev->endpoints, node)
|
||||
{
|
||||
ept = metal_container_of(node, struct rpmsg_endpoint, node);
|
||||
metal_log(METAL_LOG_EMERGENCY, " ept %s\n", ept->name);
|
||||
}
|
||||
|
||||
metal_log(METAL_LOG_EMERGENCY, " rpmsg buffer list:\n");
|
||||
|
||||
rpmsg_virtio_dump_buffer(rvdev, true);
|
||||
rpmsg_virtio_dump_buffer(rvdev, false);
|
||||
|
||||
if (needlock)
|
||||
{
|
||||
metal_mutex_release(&rdev->lock);
|
||||
}
|
||||
}
|
||||
#else
|
||||
static void rpmsg_virtio_dump(FAR struct rpmsg_s *rpmsg)
|
||||
{
|
||||
/* Nothing */
|
||||
}
|
||||
#endif
|
||||
|
||||
static FAR const char *
|
||||
rpmsg_virtio_get_local_cpuname(FAR struct rpmsg_s *rpmsg)
|
||||
{
|
||||
FAR struct rpmsg_virtio_priv_s *priv =
|
||||
(FAR struct rpmsg_virtio_priv_s *)rpmsg;
|
||||
|
||||
return RPMSG_VIRTIO_GET_LOCAL_CPUNAME(priv->dev);
|
||||
}
|
||||
|
||||
static FAR const char *rpmsg_virtio_get_cpuname(FAR struct rpmsg_s *rpmsg)
|
||||
{
|
||||
FAR struct rpmsg_virtio_priv_s *priv =
|
||||
(FAR struct rpmsg_virtio_priv_s *)rpmsg;
|
||||
|
||||
return RPMSG_VIRTIO_GET_CPUNAME(priv->dev);
|
||||
}
|
||||
|
||||
static void rpmsg_virtio_wakeup_rx(FAR struct rpmsg_virtio_priv_s *priv)
|
||||
{
|
||||
int semcount;
|
||||
|
||||
nxsem_get_value(&priv->semrx, &semcount);
|
||||
if (semcount < 1)
|
||||
{
|
||||
nxsem_post(&priv->semrx);
|
||||
}
|
||||
}
|
||||
|
||||
static void rpmsg_virtio_command(FAR struct rpmsg_virtio_priv_s *priv)
|
||||
{
|
||||
FAR struct rpmsg_virtio_cmd_s *rpmsg_virtio_cmd =
|
||||
RPMSG_VIRTIO_RSC2CMD(priv->rsc);
|
||||
uint32_t cmd;
|
||||
|
||||
if (RPMSG_VIRTIO_IS_MASTER(priv->dev))
|
||||
{
|
||||
cmd = rpmsg_virtio_cmd->cmd_slave;
|
||||
rpmsg_virtio_cmd->cmd_slave = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
cmd = rpmsg_virtio_cmd->cmd_master;
|
||||
rpmsg_virtio_cmd->cmd_master = 0;
|
||||
}
|
||||
|
||||
switch (RPMSG_VIRTIO_GET_CMD(cmd))
|
||||
{
|
||||
case RPMSG_VIRTIO_CMD_PANIC:
|
||||
PANIC();
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static int rpmsg_virtio_callback(FAR void *arg, uint32_t vqid)
|
||||
{
|
||||
FAR struct rpmsg_virtio_priv_s *priv = arg;
|
||||
FAR struct rpmsg_virtio_device *rvdev = &priv->rvdev;
|
||||
FAR struct virtio_device *vdev = rvdev->vdev;
|
||||
FAR struct virtqueue *rvq = rvdev->rvq;
|
||||
|
||||
rpmsg_virtio_command(priv);
|
||||
|
||||
if (vqid == RPMSG_VIRTIO_NOTIFY_ALL ||
|
||||
vqid == vdev->vrings_info[rvq->vq_queue_index].notifyid)
|
||||
{
|
||||
rpmsg_virtio_wakeup_rx(priv);
|
||||
}
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
static int rpmsg_virtio_notify_wait(FAR struct rpmsg_device *rdev,
|
||||
uint32_t id)
|
||||
{
|
||||
FAR struct rpmsg_virtio_priv_s *priv =
|
||||
metal_container_of(rdev, struct rpmsg_virtio_priv_s, rvdev.rdev);
|
||||
|
||||
if (!rpmsg_virtio_is_recursive(priv))
|
||||
{
|
||||
return -EAGAIN;
|
||||
}
|
||||
|
||||
/* Wait to wakeup */
|
||||
|
||||
nxsem_tickwait(&priv->semtx, MSEC2TICK(RPMSG_VIRTIO_TIMEOUT_MS));
|
||||
virtqueue_notification(priv->rvdev.rvq);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int rpmsg_virtio_start(FAR struct rpmsg_virtio_priv_s *priv)
|
||||
{
|
||||
FAR struct virtio_vring_info *rvrings = priv->rvrings;
|
||||
FAR struct virtio_device *vdev = &priv->vdev;
|
||||
FAR struct rpmsg_virtio_rsc_s *rsc;
|
||||
struct rpmsg_virtio_config config;
|
||||
FAR void *shbuf0;
|
||||
FAR void *shbuf1;
|
||||
uint32_t align0;
|
||||
uint32_t align1;
|
||||
uint32_t tbsz;
|
||||
uint32_t v0sz;
|
||||
uint32_t v1sz;
|
||||
uint32_t shbufsz0;
|
||||
uint32_t shbufsz1;
|
||||
int ret;
|
||||
|
||||
rsc = RPMSG_VIRTIO_GET_RESOURCE(priv->dev);
|
||||
if (!rsc)
|
||||
{
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
priv->rsc = rsc;
|
||||
|
||||
vdev->notifyid = RPMSG_VIRTIO_NOTIFYID;
|
||||
vdev->vrings_num = rsc->rpmsg_vdev.num_of_vrings;
|
||||
vdev->role = RPMSG_VIRTIO_IS_MASTER(priv->dev) ? RPMSG_HOST : RPMSG_REMOTE;
|
||||
vdev->func = &g_rpmsg_virtio_dispatch;
|
||||
|
||||
align0 = rsc->rpmsg_vring0.align;
|
||||
align1 = rsc->rpmsg_vring1.align;
|
||||
tbsz = ALIGN_UP(sizeof(struct rpmsg_virtio_rsc_s), MAX(align0, align1));
|
||||
v0sz = ALIGN_UP(vring_size(rsc->rpmsg_vring0.num, align0), align0);
|
||||
v1sz = ALIGN_UP(vring_size(rsc->rpmsg_vring1.num, align1), align1);
|
||||
|
||||
shbuf0 = (FAR char *)rsc + tbsz + v0sz + v1sz;
|
||||
shbufsz0 = rsc->config.r2h_buf_size * rsc->rpmsg_vring0.num;
|
||||
shbuf1 = shbuf0 + shbufsz0;
|
||||
shbufsz1 = rsc->config.h2r_buf_size * rsc->rpmsg_vring1.num;
|
||||
|
||||
rvrings[0].io = metal_io_get_region();
|
||||
rvrings[0].info.vaddr = (FAR char *)rsc + tbsz;
|
||||
rvrings[0].info.num_descs = rsc->rpmsg_vring0.num;
|
||||
rvrings[0].info.align = rsc->rpmsg_vring0.align;
|
||||
rvrings[0].vq = virtqueue_allocate(rsc->rpmsg_vring0.num);
|
||||
if (rvrings[0].vq == NULL)
|
||||
{
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
rvrings[1].io = metal_io_get_region();
|
||||
rvrings[1].info.vaddr = (FAR char *)rsc + tbsz + v0sz;
|
||||
rvrings[1].info.num_descs = rsc->rpmsg_vring1.num;
|
||||
rvrings[1].info.align = rsc->rpmsg_vring1.align;
|
||||
rvrings[1].vq = virtqueue_allocate(rsc->rpmsg_vring1.num);
|
||||
if (rvrings[1].vq == NULL)
|
||||
{
|
||||
ret = -ENOMEM;
|
||||
goto err_vq0;
|
||||
}
|
||||
|
||||
vdev->vrings_info = &rvrings[0];
|
||||
|
||||
rpmsg_virtio_init_shm_pool(&priv->pool[0], shbuf0, shbufsz0);
|
||||
rpmsg_virtio_init_shm_pool(&priv->pool[1], shbuf1, shbufsz1);
|
||||
|
||||
config.h2r_buf_size = rsc->config.h2r_buf_size;
|
||||
config.r2h_buf_size = rsc->config.r2h_buf_size;
|
||||
config.split_shpool = true;
|
||||
|
||||
ret = rpmsg_init_vdev_with_config(&priv->rvdev, vdev, rpmsg_ns_bind,
|
||||
metal_io_get_region(),
|
||||
priv->pool, &config);
|
||||
if (ret != 0)
|
||||
{
|
||||
rpmsgerr("rpmsg_init_vdev failed %d\n", ret);
|
||||
ret = -ENOMEM;
|
||||
goto err_vq1;
|
||||
}
|
||||
|
||||
priv->rvdev.rdev.ns_unbind_cb = rpmsg_ns_unbind;
|
||||
priv->rvdev.notify_wait_cb = rpmsg_virtio_notify_wait;
|
||||
|
||||
RPMSG_VIRTIO_REGISTER_CALLBACK(priv->dev, rpmsg_virtio_callback, priv);
|
||||
|
||||
rpmsg_virtio_wakeup_rx(priv);
|
||||
|
||||
/* Broadcast device_created to all registers */
|
||||
|
||||
rpmsg_device_created(&priv->rpmsg);
|
||||
|
||||
return 0;
|
||||
|
||||
err_vq1:
|
||||
virtqueue_free(rvrings[1].vq);
|
||||
err_vq0:
|
||||
virtqueue_free(rvrings[0].vq);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int rpmsg_virtio_thread(int argc, FAR char *argv[])
|
||||
{
|
||||
FAR struct rpmsg_virtio_priv_s *priv = (FAR struct rpmsg_virtio_priv_s *)
|
||||
((uintptr_t)strtoul(argv[2], NULL, 16));
|
||||
int ret;
|
||||
|
||||
priv->tid = nxsched_gettid();
|
||||
|
||||
ret = rpmsg_virtio_start(priv);
|
||||
if (ret < 0)
|
||||
{
|
||||
rpmsgerr("rpmsg virtio thread start failed %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
while (1)
|
||||
{
|
||||
nxsem_wait_uninterruptible(&priv->semrx);
|
||||
virtqueue_notification(priv->rvdev.rvq);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
****************************************************************************/
|
||||
|
||||
int rpmsg_virtio_initialize(FAR struct rpmsg_virtio_s *dev)
|
||||
{
|
||||
FAR struct rpmsg_virtio_priv_s *priv;
|
||||
FAR char *argv[3];
|
||||
char arg1[32];
|
||||
char name[32];
|
||||
int ret;
|
||||
|
||||
priv = kmm_zalloc(sizeof(struct rpmsg_virtio_priv_s));
|
||||
if (priv == NULL)
|
||||
{
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
priv->dev = dev;
|
||||
nxsem_init(&priv->semrx, 0, 0);
|
||||
nxsem_init(&priv->semtx, 0, 0);
|
||||
|
||||
snprintf(name, sizeof(name), "/dev/rpmsg/%s",
|
||||
RPMSG_VIRTIO_GET_CPUNAME(dev));
|
||||
ret = rpmsg_register(name, &priv->rpmsg, &g_rpmsg_virtio_ops);
|
||||
if (ret < 0)
|
||||
{
|
||||
goto err_driver;
|
||||
}
|
||||
|
||||
snprintf(arg1, sizeof(arg1), "%p", priv);
|
||||
argv[0] = (FAR char *)RPMSG_VIRTIO_GET_CPUNAME(dev);
|
||||
argv[1] = arg1;
|
||||
argv[2] = NULL;
|
||||
|
||||
ret = kthread_create("rpmsg_virtio", CONFIG_RPMSG_VIRTIO_PRIORITY,
|
||||
CONFIG_RPMSG_VIRTIO_STACKSIZE,
|
||||
rpmsg_virtio_thread, argv);
|
||||
if (ret < 0)
|
||||
{
|
||||
goto err_thread;
|
||||
}
|
||||
|
||||
return OK;
|
||||
|
||||
err_thread:
|
||||
rpmsg_unregister(name, &priv->rpmsg);
|
||||
|
||||
err_driver:
|
||||
nxsem_destroy(&priv->semrx);
|
||||
nxsem_destroy(&priv->semtx);
|
||||
kmm_free(priv);
|
||||
|
||||
return ret;
|
||||
}
|
|
@ -32,8 +32,8 @@
|
|||
|
||||
#include <nuttx/drivers/addrenv.h>
|
||||
#include <nuttx/pci/pci_ivshmem.h>
|
||||
#include <nuttx/rpmsg/rpmsg_virtio.h>
|
||||
#include <nuttx/rpmsg/rpmsg_virtio_ivshmem.h>
|
||||
#include <nuttx/rpmsg/rpmsg_virtio_lite.h>
|
||||
#include <nuttx/wdog.h>
|
||||
|
||||
/****************************************************************************
|
||||
|
@ -53,15 +53,15 @@
|
|||
|
||||
struct rpmsg_virtio_ivshmem_mem_s
|
||||
{
|
||||
volatile uint64_t basem;
|
||||
volatile uint32_t seqs;
|
||||
volatile uint32_t seqm;
|
||||
struct rpmsg_virtio_rsc_s rsc;
|
||||
volatile uint64_t basem;
|
||||
volatile uint32_t seqs;
|
||||
volatile uint32_t seqm;
|
||||
struct rpmsg_virtio_lite_rsc_s rsc;
|
||||
};
|
||||
|
||||
struct rpmsg_virtio_ivshmem_dev_s
|
||||
{
|
||||
struct rpmsg_virtio_s dev;
|
||||
struct rpmsg_virtio_lite_s dev;
|
||||
struct ivshmem_driver_s drv;
|
||||
FAR struct ivshmem_device_s *ivdev;
|
||||
rpmsg_virtio_callback_t callback;
|
||||
|
@ -84,15 +84,15 @@ struct rpmsg_virtio_ivshmem_dev_s
|
|||
****************************************************************************/
|
||||
|
||||
static const FAR char *
|
||||
rpmsg_virtio_ivshmem_get_cpuname(FAR struct rpmsg_virtio_s *dev);
|
||||
static FAR struct rpmsg_virtio_rsc_s *
|
||||
rpmsg_virtio_ivshmem_get_resource(FAR struct rpmsg_virtio_s *dev);
|
||||
rpmsg_virtio_ivshmem_get_cpuname(FAR struct rpmsg_virtio_lite_s *dev);
|
||||
static FAR struct rpmsg_virtio_lite_rsc_s *
|
||||
rpmsg_virtio_ivshmem_get_resource(FAR struct rpmsg_virtio_lite_s *dev);
|
||||
static int
|
||||
rpmsg_virtio_ivshmem_is_master(FAR struct rpmsg_virtio_s *dev);
|
||||
static int rpmsg_virtio_ivshmem_notify(FAR struct rpmsg_virtio_s *dev,
|
||||
rpmsg_virtio_ivshmem_is_master(FAR struct rpmsg_virtio_lite_s *dev);
|
||||
static int rpmsg_virtio_ivshmem_notify(FAR struct rpmsg_virtio_lite_s *dev,
|
||||
uint32_t notifyid);
|
||||
static int
|
||||
rpmsg_virtio_ivshmem_register_callback(FAR struct rpmsg_virtio_s *dev,
|
||||
rpmsg_virtio_ivshmem_register_callback(FAR struct rpmsg_virtio_lite_s *dev,
|
||||
rpmsg_virtio_callback_t callback,
|
||||
FAR void *arg);
|
||||
static int rpmsg_virtio_ivshmem_probe(FAR struct ivshmem_device_s *ivdev);
|
||||
|
@ -102,7 +102,7 @@ static void rpmsg_virtio_ivshmem_remove(FAR struct ivshmem_device_s *ivdev);
|
|||
* Private Data
|
||||
****************************************************************************/
|
||||
|
||||
static const struct rpmsg_virtio_ops_s g_rpmsg_virtio_ivshmem_ops =
|
||||
static const struct rpmsg_virtio_lite_ops_s g_rpmsg_virtio_ivshmem_ops =
|
||||
{
|
||||
.get_cpuname = rpmsg_virtio_ivshmem_get_cpuname,
|
||||
.get_resource = rpmsg_virtio_ivshmem_get_resource,
|
||||
|
@ -116,23 +116,23 @@ static const struct rpmsg_virtio_ops_s g_rpmsg_virtio_ivshmem_ops =
|
|||
****************************************************************************/
|
||||
|
||||
static const FAR char *
|
||||
rpmsg_virtio_ivshmem_get_cpuname(FAR struct rpmsg_virtio_s *dev)
|
||||
rpmsg_virtio_ivshmem_get_cpuname(FAR struct rpmsg_virtio_lite_s *dev)
|
||||
{
|
||||
FAR struct rpmsg_virtio_ivshmem_dev_s *priv =
|
||||
(FAR struct rpmsg_virtio_ivshmem_dev_s *)dev;
|
||||
return priv->cpuname;
|
||||
}
|
||||
|
||||
static FAR struct rpmsg_virtio_rsc_s *
|
||||
rpmsg_virtio_ivshmem_get_resource(FAR struct rpmsg_virtio_s *dev)
|
||||
static FAR struct rpmsg_virtio_lite_rsc_s *
|
||||
rpmsg_virtio_ivshmem_get_resource(FAR struct rpmsg_virtio_lite_s *dev)
|
||||
{
|
||||
FAR struct rpmsg_virtio_ivshmem_dev_s *priv =
|
||||
(FAR struct rpmsg_virtio_ivshmem_dev_s *)dev;
|
||||
FAR struct rpmsg_virtio_rsc_s *rsc;
|
||||
FAR struct rpmsg_virtio_cmd_s *cmd;
|
||||
FAR struct rpmsg_virtio_lite_rsc_s *rsc;
|
||||
FAR struct rpmsg_virtio_lite_cmd_s *cmd;
|
||||
|
||||
rsc = &priv->shmem->rsc;
|
||||
cmd = RPMSG_VIRTIO_RSC2CMD(rsc);
|
||||
cmd = RPMSG_VIRTIO_LITE_RSC2CMD(rsc);
|
||||
|
||||
if (priv->master)
|
||||
{
|
||||
|
@ -178,14 +178,15 @@ rpmsg_virtio_ivshmem_get_resource(FAR struct rpmsg_virtio_s *dev)
|
|||
return rsc;
|
||||
}
|
||||
|
||||
static int rpmsg_virtio_ivshmem_is_master(FAR struct rpmsg_virtio_s *dev)
|
||||
static int
|
||||
rpmsg_virtio_ivshmem_is_master(FAR struct rpmsg_virtio_lite_s *dev)
|
||||
{
|
||||
FAR struct rpmsg_virtio_ivshmem_dev_s *priv =
|
||||
(FAR struct rpmsg_virtio_ivshmem_dev_s *)dev;
|
||||
return priv->master;
|
||||
}
|
||||
|
||||
static int rpmsg_virtio_ivshmem_notify(FAR struct rpmsg_virtio_s *dev,
|
||||
static int rpmsg_virtio_ivshmem_notify(FAR struct rpmsg_virtio_lite_s *dev,
|
||||
uint32_t vqid)
|
||||
{
|
||||
FAR struct rpmsg_virtio_ivshmem_dev_s *priv =
|
||||
|
@ -208,7 +209,7 @@ static int rpmsg_virtio_ivshmem_notify(FAR struct rpmsg_virtio_s *dev,
|
|||
}
|
||||
|
||||
static int
|
||||
rpmsg_virtio_ivshmem_register_callback(FAR struct rpmsg_virtio_s *dev,
|
||||
rpmsg_virtio_ivshmem_register_callback(FAR struct rpmsg_virtio_lite_s *dev,
|
||||
rpmsg_virtio_callback_t callback,
|
||||
FAR void *arg)
|
||||
{
|
||||
|
@ -231,7 +232,7 @@ static int rpmsg_virtio_ivshmem_interrupt(int irq, FAR void *context,
|
|||
|
||||
if (priv->callback != NULL)
|
||||
{
|
||||
priv->callback(priv->arg, RPMSG_VIRTIO_NOTIFY_ALL);
|
||||
priv->callback(priv->arg, RPMSG_VIRTIO_LITE_NOTIFY_ALL);
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
@ -260,7 +261,7 @@ static void rpmsg_virtio_ivshmem_wdog(wdparm_t arg)
|
|||
|
||||
if (should_notify && priv->callback != NULL)
|
||||
{
|
||||
priv->callback(priv->arg, RPMSG_VIRTIO_NOTIFY_ALL);
|
||||
priv->callback(priv->arg, RPMSG_VIRTIO_LITE_NOTIFY_ALL);
|
||||
}
|
||||
|
||||
wd_start(&priv->wdog, RPMSG_VIRTIO_IVSHMEM_WDOG_DELAY,
|
||||
|
@ -288,7 +289,7 @@ static int rpmsg_virtio_ivshmem_probe(FAR struct ivshmem_device_s *ivdev)
|
|||
|
||||
/* Do rpmsg virtio initialize */
|
||||
|
||||
ret = rpmsg_virtio_initialize(&priv->dev);
|
||||
ret = rpmsg_virtio_lite_initialize(&priv->dev);
|
||||
if (ret < 0)
|
||||
{
|
||||
rpmsgerr("Rpmsg virtio initialize failed, ret=%d\n", ret);
|
||||
|
|
835
drivers/rpmsg/rpmsg_virtio_lite.c
Normal file
835
drivers/rpmsg/rpmsg_virtio_lite.c
Normal file
|
@ -0,0 +1,835 @@
|
|||
/****************************************************************************
|
||||
* drivers/rpmsg/rpmsg_virtio_lite.c
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* 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 <debug.h>
|
||||
#include <stdio.h>
|
||||
#include <sys/param.h>
|
||||
|
||||
#include <metal/cache.h>
|
||||
#include <nuttx/kmalloc.h>
|
||||
#include <nuttx/kthread.h>
|
||||
#include <nuttx/nuttx.h>
|
||||
#include <nuttx/power/pm.h>
|
||||
#include <nuttx/semaphore.h>
|
||||
#include <nuttx/rpmsg/rpmsg_virtio_lite.h>
|
||||
#include <rpmsg/rpmsg_internal.h>
|
||||
|
||||
/****************************************************************************
|
||||
* Pre-processor Definitions
|
||||
****************************************************************************/
|
||||
|
||||
#define RPMSG_VIRTIO_LITE_TIMEOUT_MS 20
|
||||
#define RPMSG_VIRTIO_LITE_NOTIFYID 0
|
||||
|
||||
#ifdef CONFIG_OPENAMP_CACHE
|
||||
# define RPMSG_VIRTIO_INVALIDATE(x) metal_cache_invalidate(&x, sizeof(x))
|
||||
#else
|
||||
# define RPMSG_VIRTIO_INVALIDATE(x)
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Private Types
|
||||
****************************************************************************/
|
||||
|
||||
struct rpmsg_virtio_lite_priv_s
|
||||
{
|
||||
struct rpmsg_s rpmsg;
|
||||
struct rpmsg_virtio_device rvdev;
|
||||
FAR struct rpmsg_virtio_lite_s *dev;
|
||||
FAR struct rpmsg_virtio_lite_rsc_s *rsc;
|
||||
struct virtio_device vdev;
|
||||
struct rpmsg_virtio_shm_pool pool[2];
|
||||
struct virtio_vring_info rvrings[2];
|
||||
sem_t semtx;
|
||||
sem_t semrx;
|
||||
pid_t tid;
|
||||
uint16_t headrx;
|
||||
#ifdef CONFIG_RPMSG_VIRTIO_LITE_PM
|
||||
struct pm_wakelock_s wakelock;
|
||||
struct wdog_s wdog;
|
||||
#endif
|
||||
};
|
||||
|
||||
/****************************************************************************
|
||||
* Private Function Prototypes
|
||||
****************************************************************************/
|
||||
|
||||
static int rpmsg_virtio_lite_wait(FAR struct rpmsg_s *rpmsg, FAR sem_t *sem);
|
||||
static int rpmsg_virtio_lite_post(FAR struct rpmsg_s *rpmsg, FAR sem_t *sem);
|
||||
static void rpmsg_virtio_lite_panic(FAR struct rpmsg_s *rpmsg);
|
||||
static void rpmsg_virtio_lite_dump(FAR struct rpmsg_s *rpmsg);
|
||||
static FAR const char *
|
||||
rpmsg_virtio_lite_get_local_cpuname(FAR struct rpmsg_s *rpmsg);
|
||||
static FAR const char *
|
||||
rpmsg_virtio_lite_get_cpuname(FAR struct rpmsg_s *rpmsg);
|
||||
|
||||
static int
|
||||
rpmsg_virtio_lite_create_virtqueues_(FAR struct virtio_device *vdev,
|
||||
unsigned int flags,
|
||||
unsigned int nvqs,
|
||||
FAR const char *names[],
|
||||
vq_callback callbacks[],
|
||||
FAR void *callback_args[]);
|
||||
static uint8_t rpmsg_virtio_lite_get_status_(FAR struct virtio_device *dev);
|
||||
static void rpmsg_virtio_lite_set_status_(FAR struct virtio_device *dev,
|
||||
uint8_t status);
|
||||
static uint64_t
|
||||
rpmsg_virtio_lite_get_features_(FAR struct virtio_device *dev);
|
||||
static void rpmsg_virtio_lite_set_features(FAR struct virtio_device *dev,
|
||||
uint64_t feature);
|
||||
static void rpmsg_virtio_lite_notify(FAR struct virtqueue *vq);
|
||||
|
||||
/****************************************************************************
|
||||
* Private Data
|
||||
****************************************************************************/
|
||||
|
||||
static const struct rpmsg_ops_s g_rpmsg_virtio_lite_ops =
|
||||
{
|
||||
.wait = rpmsg_virtio_lite_wait,
|
||||
.post = rpmsg_virtio_lite_post,
|
||||
.panic = rpmsg_virtio_lite_panic,
|
||||
.dump = rpmsg_virtio_lite_dump,
|
||||
.get_local_cpuname = rpmsg_virtio_lite_get_local_cpuname,
|
||||
.get_cpuname = rpmsg_virtio_lite_get_cpuname,
|
||||
};
|
||||
|
||||
static const struct virtio_dispatch g_rpmsg_virtio_lite_dispatch =
|
||||
{
|
||||
.create_virtqueues = rpmsg_virtio_lite_create_virtqueues_,
|
||||
.get_status = rpmsg_virtio_lite_get_status_,
|
||||
.set_status = rpmsg_virtio_lite_set_status_,
|
||||
.get_features = rpmsg_virtio_lite_get_features_,
|
||||
.set_features = rpmsg_virtio_lite_set_features,
|
||||
.notify = rpmsg_virtio_lite_notify,
|
||||
};
|
||||
|
||||
/****************************************************************************
|
||||
* Private Functions
|
||||
****************************************************************************/
|
||||
|
||||
#if defined(CONFIG_OPENAMP_DEBUG) || \
|
||||
defined(CONFIG_RPMSG_VIRTIO_LITE_PM_AUTORELAX)
|
||||
static int
|
||||
rpmsg_virtio_lite_buffer_nused(FAR struct rpmsg_virtio_device *rvdev,
|
||||
bool rx)
|
||||
{
|
||||
FAR struct virtqueue *vq = rx ? rvdev->rvq : rvdev->svq;
|
||||
uint16_t nused = vq->vq_ring.avail->idx - vq->vq_ring.used->idx;
|
||||
|
||||
if ((rpmsg_virtio_get_role(rvdev) == RPMSG_HOST) ^ rx)
|
||||
{
|
||||
return nused;
|
||||
}
|
||||
else
|
||||
{
|
||||
return vq->vq_nentries - nused;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
static void
|
||||
rpmsg_virtio_lite_wakeup_tx(FAR struct rpmsg_virtio_lite_priv_s *priv)
|
||||
{
|
||||
int semcount;
|
||||
|
||||
nxsem_get_value(&priv->semtx, &semcount);
|
||||
while (semcount++ < 1)
|
||||
{
|
||||
nxsem_post(&priv->semtx);
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef CONFIG_RPMSG_VIRTIO_LITE_PM
|
||||
|
||||
#ifdef CONFIG_RPMSG_VIRTIO_LITE_PM_AUTORELAX
|
||||
static void rpmsg_virtio_lite_pm_callback(wdparm_t arg)
|
||||
{
|
||||
FAR struct rpmsg_virtio_lite_priv_s *priv =
|
||||
(FAR struct rpmsg_virtio_lite_priv_s *)arg;
|
||||
|
||||
if (rpmsg_virtio_lite_buffer_nused(&priv->rvdev, false))
|
||||
{
|
||||
rpmsg_virtio_lite_wakeup_tx(priv);
|
||||
|
||||
wd_start(&priv->wdog, MSEC2TICK(RPMSG_VIRTIO_LITE_TIMEOUT_MS),
|
||||
rpmsg_virtio_lite_pm_callback, (wdparm_t)priv);
|
||||
}
|
||||
else
|
||||
{
|
||||
pm_wakelock_relax(&priv->wakelock);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
static inline void
|
||||
rpmsg_virtio_lite_pm_action(FAR struct rpmsg_virtio_lite_priv_s *priv,
|
||||
bool stay)
|
||||
{
|
||||
irqstate_t flags;
|
||||
int count;
|
||||
|
||||
flags = enter_critical_section();
|
||||
|
||||
count = pm_wakelock_staycount(&priv->wakelock);
|
||||
if (stay && count == 0)
|
||||
{
|
||||
pm_wakelock_stay(&priv->wakelock);
|
||||
#ifdef CONFIG_RPMSG_VIRTIO_LITE_PM_AUTORELAX
|
||||
wd_start(&priv->wdog, MSEC2TICK(RPMSG_VIRTIO_LITE_TIMEOUT_MS),
|
||||
rpmsg_virtio_lite_pm_callback, (wdparm_t)priv);
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifndef CONFIG_RPMSG_VIRTIO_LITE_PM_AUTORELAX
|
||||
if (!stay && count > 0 &&
|
||||
rpmsg_virtio_lite_buffer_nused(&priv->rvdev, false) == 0)
|
||||
{
|
||||
pm_wakelock_relax(&priv->wakelock);
|
||||
}
|
||||
#endif
|
||||
|
||||
leave_critical_section(flags);
|
||||
}
|
||||
|
||||
static inline bool
|
||||
rpmsg_virtio_lite_available_rx(FAR struct rpmsg_virtio_lite_priv_s *priv)
|
||||
{
|
||||
FAR struct rpmsg_virtio_device *rvdev = &priv->rvdev;
|
||||
FAR struct virtqueue *rvq = rvdev->rvq;
|
||||
|
||||
if (rpmsg_virtio_get_role(rvdev) == RPMSG_HOST)
|
||||
{
|
||||
return priv->headrx != rvq->vq_used_cons_idx;
|
||||
}
|
||||
else
|
||||
{
|
||||
return priv->headrx != rvq->vq_available_idx;
|
||||
}
|
||||
}
|
||||
|
||||
#else
|
||||
# define rpmsg_virtio_lite_pm_action(priv, stay)
|
||||
# define rpmsg_virtio_lite_available_rx(priv) true
|
||||
#endif
|
||||
|
||||
static inline void
|
||||
rpmsg_virtio_lite_update_rx(FAR struct rpmsg_virtio_lite_priv_s *priv)
|
||||
{
|
||||
FAR struct rpmsg_virtio_device *rvdev = &priv->rvdev;
|
||||
FAR struct virtqueue *rvq = rvdev->rvq;
|
||||
|
||||
if (rpmsg_virtio_get_role(rvdev) == RPMSG_HOST)
|
||||
{
|
||||
RPMSG_VIRTIO_INVALIDATE(rvq->vq_ring.used->idx);
|
||||
priv->headrx = rvq->vq_ring.used->idx;
|
||||
}
|
||||
else
|
||||
{
|
||||
RPMSG_VIRTIO_INVALIDATE(rvq->vq_ring.avail->idx);
|
||||
priv->headrx = rvq->vq_ring.avail->idx;
|
||||
}
|
||||
}
|
||||
|
||||
static FAR struct rpmsg_virtio_lite_priv_s *
|
||||
rpmsg_virtio_lite_get_priv(FAR struct virtio_device *vdev)
|
||||
{
|
||||
FAR struct rpmsg_virtio_device *rvdev = vdev->priv;
|
||||
|
||||
return metal_container_of(rvdev, struct rpmsg_virtio_lite_priv_s, rvdev);
|
||||
}
|
||||
|
||||
static int
|
||||
rpmsg_virtio_lite_create_virtqueues_(FAR struct virtio_device *vdev,
|
||||
unsigned int flags,
|
||||
unsigned int nvqs,
|
||||
FAR const char *names[],
|
||||
vq_callback callbacks[],
|
||||
FAR void *callback_args[])
|
||||
{
|
||||
int ret;
|
||||
int i;
|
||||
|
||||
if (nvqs > vdev->vrings_num)
|
||||
{
|
||||
return ERROR_VQUEUE_INVLD_PARAM;
|
||||
}
|
||||
|
||||
/* Initialize virtqueue for each vring */
|
||||
|
||||
for (i = 0; i < nvqs; i++)
|
||||
{
|
||||
FAR struct virtio_vring_info *vinfo = &vdev->vrings_info[i];
|
||||
FAR struct vring_alloc_info *valloc = &vinfo->info;
|
||||
#ifndef CONFIG_OPENAMP_VIRTIO_DEVICE_ONLY
|
||||
if (vdev->role == VIRTIO_DEV_DRIVER)
|
||||
{
|
||||
size_t offset;
|
||||
|
||||
offset = metal_io_virt_to_offset(vinfo->io, valloc->vaddr);
|
||||
metal_io_block_set(vinfo->io, offset, 0,
|
||||
vring_size(valloc->num_descs, valloc->align));
|
||||
}
|
||||
#endif
|
||||
|
||||
ret = virtqueue_create(vdev, i, names[i], valloc,
|
||||
callbacks[i], vdev->func->notify,
|
||||
vinfo->vq);
|
||||
if (ret < 0)
|
||||
{
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static uint8_t rpmsg_virtio_lite_get_status_(FAR struct virtio_device *vdev)
|
||||
{
|
||||
FAR struct rpmsg_virtio_lite_priv_s *priv =
|
||||
rpmsg_virtio_lite_get_priv(vdev);
|
||||
|
||||
return priv->rsc->rpmsg_vdev.status;
|
||||
}
|
||||
|
||||
static void rpmsg_virtio_lite_set_status_(FAR struct virtio_device *vdev,
|
||||
uint8_t status)
|
||||
{
|
||||
FAR struct rpmsg_virtio_lite_priv_s *priv =
|
||||
rpmsg_virtio_lite_get_priv(vdev);
|
||||
|
||||
priv->rsc->rpmsg_vdev.status = status;
|
||||
}
|
||||
|
||||
static uint64_t
|
||||
rpmsg_virtio_lite_get_features_(FAR struct virtio_device *vdev)
|
||||
{
|
||||
FAR struct rpmsg_virtio_lite_priv_s *priv =
|
||||
rpmsg_virtio_lite_get_priv(vdev);
|
||||
|
||||
return priv->rsc->rpmsg_vdev.dfeatures;
|
||||
}
|
||||
|
||||
static void rpmsg_virtio_lite_set_features(FAR struct virtio_device *vdev,
|
||||
uint64_t features)
|
||||
{
|
||||
FAR struct rpmsg_virtio_lite_priv_s *priv =
|
||||
rpmsg_virtio_lite_get_priv(vdev);
|
||||
|
||||
priv->rsc->rpmsg_vdev.gfeatures = features;
|
||||
}
|
||||
|
||||
static void rpmsg_virtio_lite_notify(FAR struct virtqueue *vq)
|
||||
{
|
||||
FAR struct virtio_device *vdev = vq->vq_dev;
|
||||
FAR struct rpmsg_virtio_lite_priv_s *priv =
|
||||
rpmsg_virtio_lite_get_priv(vdev);
|
||||
FAR struct virtqueue *svq = priv->rvdev.svq;
|
||||
|
||||
if (vdev->vrings_info->notifyid ==
|
||||
vdev->vrings_info[svq->vq_queue_index].notifyid)
|
||||
{
|
||||
rpmsg_virtio_lite_pm_action(priv, true);
|
||||
}
|
||||
|
||||
RPMSG_VIRTIO_LITE_NOTIFY(priv->dev, vdev->vrings_info->notifyid);
|
||||
}
|
||||
|
||||
static bool
|
||||
rpmsg_virtio_lite_is_recursive(FAR struct rpmsg_virtio_lite_priv_s *priv)
|
||||
{
|
||||
return nxsched_gettid() == priv->tid;
|
||||
}
|
||||
|
||||
static int rpmsg_virtio_lite_wait(FAR struct rpmsg_s *rpmsg, FAR sem_t *sem)
|
||||
{
|
||||
FAR struct rpmsg_virtio_lite_priv_s *priv =
|
||||
(FAR struct rpmsg_virtio_lite_priv_s *)rpmsg;
|
||||
int ret;
|
||||
|
||||
if (!rpmsg_virtio_lite_is_recursive(priv))
|
||||
{
|
||||
return nxsem_wait_uninterruptible(sem);
|
||||
}
|
||||
|
||||
while (1)
|
||||
{
|
||||
ret = nxsem_trywait(sem);
|
||||
if (ret >= 0)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
nxsem_wait(&priv->semtx);
|
||||
virtqueue_notification(priv->rvdev.rvq);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int rpmsg_virtio_lite_post(FAR struct rpmsg_s *rpmsg, FAR sem_t *sem)
|
||||
{
|
||||
FAR struct rpmsg_virtio_lite_priv_s *priv =
|
||||
(FAR struct rpmsg_virtio_lite_priv_s *)rpmsg;
|
||||
int semcount;
|
||||
int ret;
|
||||
|
||||
nxsem_get_value(sem, &semcount);
|
||||
ret = nxsem_post(sem);
|
||||
|
||||
if (priv && semcount >= 0)
|
||||
{
|
||||
rpmsg_virtio_lite_wakeup_tx(priv);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void rpmsg_virtio_lite_panic(FAR struct rpmsg_s *rpmsg)
|
||||
{
|
||||
FAR struct rpmsg_virtio_lite_priv_s *priv =
|
||||
(FAR struct rpmsg_virtio_lite_priv_s *)rpmsg;
|
||||
FAR struct rpmsg_virtio_lite_cmd_s *cmd =
|
||||
RPMSG_VIRTIO_LITE_RSC2CMD(priv->rsc);
|
||||
|
||||
if (RPMSG_VIRTIO_LITE_IS_MASTER(priv->dev))
|
||||
{
|
||||
cmd->cmd_master = RPMSG_VIRTIO_LITE_CMD(
|
||||
RPMSG_VIRTIO_LITE_CMD_PANIC, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
cmd->cmd_slave = RPMSG_VIRTIO_LITE_CMD(
|
||||
RPMSG_VIRTIO_LITE_CMD_PANIC, 0);
|
||||
}
|
||||
|
||||
rpmsg_virtio_lite_notify(priv->vdev.vrings_info->vq);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_OPENAMP_DEBUG
|
||||
static void
|
||||
rpmsg_virtio_lite_dump_buffer(FAR struct rpmsg_virtio_device *rvdev, bool rx)
|
||||
{
|
||||
FAR struct virtqueue *vq = rx ? rvdev->rvq : rvdev->svq;
|
||||
int num;
|
||||
int i;
|
||||
|
||||
num = rpmsg_virtio_lite_buffer_nused(rvdev, rx);
|
||||
metal_log(METAL_LOG_EMERGENCY,
|
||||
" %s buffer, total %d, pending %d\n",
|
||||
rx ? "RX" : "TX", vq->vq_nentries, num);
|
||||
|
||||
for (i = 0; i < num; i++)
|
||||
{
|
||||
FAR void *addr;
|
||||
int desc_idx;
|
||||
|
||||
if ((rpmsg_virtio_get_role(rvdev) == RPMSG_HOST) ^ rx)
|
||||
{
|
||||
desc_idx = (vq->vq_ring.used->idx + i) & (vq->vq_nentries - 1);
|
||||
desc_idx = vq->vq_ring.avail->ring[desc_idx];
|
||||
}
|
||||
else
|
||||
{
|
||||
desc_idx = (vq->vq_ring.avail->idx + i) & (vq->vq_nentries - 1);
|
||||
desc_idx = vq->vq_ring.used->ring[desc_idx].id;
|
||||
}
|
||||
|
||||
addr = metal_io_phys_to_virt(vq->shm_io,
|
||||
vq->vq_ring.desc[desc_idx].addr);
|
||||
if (addr)
|
||||
{
|
||||
FAR struct rpmsg_hdr *hdr = addr;
|
||||
FAR struct rpmsg_endpoint *ept;
|
||||
|
||||
ept = rpmsg_get_ept_from_addr(&rvdev->rdev,
|
||||
rx ? hdr->dst : hdr->src);
|
||||
if (ept)
|
||||
{
|
||||
metal_log(METAL_LOG_EMERGENCY,
|
||||
" %s buffer %p hold by %s\n",
|
||||
rx ? "RX" : "TX", hdr, ept->name);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void rpmsg_virtio_lite_dump(FAR struct rpmsg_s *rpmsg)
|
||||
{
|
||||
FAR struct rpmsg_virtio_lite_priv_s *priv =
|
||||
(FAR struct rpmsg_virtio_lite_priv_s *)rpmsg;
|
||||
FAR struct rpmsg_virtio_device *rvdev = &priv->rvdev;
|
||||
FAR struct rpmsg_device *rdev = rpmsg->rdev;
|
||||
FAR struct rpmsg_endpoint *ept;
|
||||
FAR struct metal_list *node;
|
||||
bool needlock = true;
|
||||
|
||||
metal_log(METAL_LOG_EMERGENCY, "Remote: %s headrx %d\n",
|
||||
RPMSG_VIRTIO_LITE_GET_CPUNAME(priv->dev), priv->headrx);
|
||||
|
||||
if (!rvdev->vdev)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (up_interrupt_context() || sched_idletask() ||
|
||||
nxmutex_is_hold(&rdev->lock))
|
||||
{
|
||||
needlock = false;
|
||||
}
|
||||
|
||||
if (needlock)
|
||||
{
|
||||
metal_mutex_acquire(&rdev->lock);
|
||||
}
|
||||
|
||||
metal_log(METAL_LOG_EMERGENCY,
|
||||
"Dump rpmsg info between cpu (master: %s)%s <==> %s:\n",
|
||||
rpmsg_virtio_get_role(rvdev) == RPMSG_HOST ? "yes" : "no",
|
||||
CONFIG_RPMSG_LOCAL_CPUNAME, rpmsg_get_cpuname(rdev));
|
||||
|
||||
metal_log(METAL_LOG_EMERGENCY, "rpmsg vq RX:\n");
|
||||
virtqueue_dump(rvdev->rvq);
|
||||
metal_log(METAL_LOG_EMERGENCY, "rpmsg vq TX:\n");
|
||||
virtqueue_dump(rvdev->svq);
|
||||
|
||||
metal_log(METAL_LOG_EMERGENCY, " rpmsg ept list:\n");
|
||||
|
||||
metal_list_for_each(&rdev->endpoints, node)
|
||||
{
|
||||
ept = metal_container_of(node, struct rpmsg_endpoint, node);
|
||||
metal_log(METAL_LOG_EMERGENCY, " ept %s\n", ept->name);
|
||||
}
|
||||
|
||||
metal_log(METAL_LOG_EMERGENCY, " rpmsg buffer list:\n");
|
||||
|
||||
rpmsg_virtio_lite_dump_buffer(rvdev, true);
|
||||
rpmsg_virtio_lite_dump_buffer(rvdev, false);
|
||||
|
||||
if (needlock)
|
||||
{
|
||||
metal_mutex_release(&rdev->lock);
|
||||
}
|
||||
}
|
||||
#else
|
||||
static void rpmsg_virtio_lite_dump(FAR struct rpmsg_s *rpmsg)
|
||||
{
|
||||
/* Nothing */
|
||||
}
|
||||
#endif
|
||||
|
||||
static FAR const char *
|
||||
rpmsg_virtio_lite_get_local_cpuname(FAR struct rpmsg_s *rpmsg)
|
||||
{
|
||||
FAR struct rpmsg_virtio_lite_priv_s *priv =
|
||||
(FAR struct rpmsg_virtio_lite_priv_s *)rpmsg;
|
||||
|
||||
return RPMSG_VIRTIO_LITE_GET_LOCAL_CPUNAME(priv->dev);
|
||||
}
|
||||
|
||||
static FAR const char *
|
||||
rpmsg_virtio_lite_get_cpuname(FAR struct rpmsg_s *rpmsg)
|
||||
{
|
||||
FAR struct rpmsg_virtio_lite_priv_s *priv =
|
||||
(FAR struct rpmsg_virtio_lite_priv_s *)rpmsg;
|
||||
|
||||
return RPMSG_VIRTIO_LITE_GET_CPUNAME(priv->dev);
|
||||
}
|
||||
|
||||
static void
|
||||
rpmsg_virtio_lite_wakeup_rx(FAR struct rpmsg_virtio_lite_priv_s *priv)
|
||||
{
|
||||
int semcount;
|
||||
|
||||
nxsem_get_value(&priv->semrx, &semcount);
|
||||
if (semcount < 1)
|
||||
{
|
||||
nxsem_post(&priv->semrx);
|
||||
}
|
||||
}
|
||||
|
||||
static void rpmsg_virtio_lite_command(struct rpmsg_virtio_lite_priv_s *priv)
|
||||
{
|
||||
FAR struct rpmsg_virtio_lite_cmd_s *rpmsg_virtio_cmd =
|
||||
RPMSG_VIRTIO_LITE_RSC2CMD(priv->rsc);
|
||||
uint32_t cmd;
|
||||
|
||||
if (RPMSG_VIRTIO_LITE_IS_MASTER(priv->dev))
|
||||
{
|
||||
cmd = rpmsg_virtio_cmd->cmd_slave;
|
||||
rpmsg_virtio_cmd->cmd_slave = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
cmd = rpmsg_virtio_cmd->cmd_master;
|
||||
rpmsg_virtio_cmd->cmd_master = 0;
|
||||
}
|
||||
|
||||
switch (RPMSG_VIRTIO_LITE_GET_CMD(cmd))
|
||||
{
|
||||
case RPMSG_VIRTIO_LITE_CMD_PANIC:
|
||||
PANIC();
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static int rpmsg_virtio_lite_callback(FAR void *arg, uint32_t vqid)
|
||||
{
|
||||
FAR struct rpmsg_virtio_lite_priv_s *priv = arg;
|
||||
FAR struct rpmsg_virtio_device *rvdev = &priv->rvdev;
|
||||
FAR struct virtio_device *vdev = rvdev->vdev;
|
||||
FAR struct virtqueue *rvq = rvdev->rvq;
|
||||
FAR struct virtqueue *svq = rvdev->svq;
|
||||
|
||||
rpmsg_virtio_lite_command(priv);
|
||||
|
||||
if (vqid == RPMSG_VIRTIO_LITE_NOTIFY_ALL ||
|
||||
vqid == vdev->vrings_info[rvq->vq_queue_index].notifyid)
|
||||
{
|
||||
rpmsg_virtio_lite_update_rx(priv);
|
||||
rpmsg_virtio_lite_wakeup_rx(priv);
|
||||
}
|
||||
|
||||
if (vqid == RPMSG_VIRTIO_LITE_NOTIFY_ALL ||
|
||||
vqid == vdev->vrings_info[svq->vq_queue_index].notifyid)
|
||||
{
|
||||
rpmsg_virtio_lite_wakeup_tx(priv);
|
||||
rpmsg_virtio_lite_pm_action(priv, false);
|
||||
}
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
static int rpmsg_virtio_lite_notify_wait(FAR struct rpmsg_device *rdev,
|
||||
uint32_t id)
|
||||
{
|
||||
FAR struct rpmsg_virtio_lite_priv_s *priv =
|
||||
metal_container_of(rdev, struct rpmsg_virtio_lite_priv_s, rvdev.rdev);
|
||||
|
||||
if (!rpmsg_virtio_lite_is_recursive(priv))
|
||||
{
|
||||
return -EAGAIN;
|
||||
}
|
||||
|
||||
/* Wait to wakeup */
|
||||
|
||||
nxsem_tickwait(&priv->semtx, MSEC2TICK(RPMSG_VIRTIO_LITE_TIMEOUT_MS));
|
||||
virtqueue_notification(priv->rvdev.rvq);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int rpmsg_virtio_lite_start(FAR struct rpmsg_virtio_lite_priv_s *priv)
|
||||
{
|
||||
FAR struct virtio_vring_info *rvrings = priv->rvrings;
|
||||
FAR struct virtio_device *vdev = &priv->vdev;
|
||||
FAR struct rpmsg_virtio_lite_rsc_s *rsc;
|
||||
struct rpmsg_virtio_config config;
|
||||
FAR void *shbuf0;
|
||||
FAR void *shbuf1;
|
||||
uint32_t align0;
|
||||
uint32_t align1;
|
||||
uint32_t tbsz;
|
||||
uint32_t v0sz;
|
||||
uint32_t v1sz;
|
||||
uint32_t shbufsz0;
|
||||
uint32_t shbufsz1;
|
||||
int ret;
|
||||
|
||||
rsc = RPMSG_VIRTIO_LITE_GET_RESOURCE(priv->dev);
|
||||
if (!rsc)
|
||||
{
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
priv->rsc = rsc;
|
||||
|
||||
vdev->notifyid = RPMSG_VIRTIO_LITE_NOTIFYID;
|
||||
vdev->vrings_num = rsc->rpmsg_vdev.num_of_vrings;
|
||||
vdev->role = RPMSG_VIRTIO_LITE_IS_MASTER(priv->dev) ?
|
||||
RPMSG_HOST : RPMSG_REMOTE;
|
||||
vdev->func = &g_rpmsg_virtio_lite_dispatch;
|
||||
|
||||
align0 = rsc->rpmsg_vring0.align;
|
||||
align1 = rsc->rpmsg_vring1.align;
|
||||
tbsz = ALIGN_UP(sizeof(*rsc), MAX(align0, align1));
|
||||
v0sz = ALIGN_UP(vring_size(rsc->rpmsg_vring0.num, align0), align0);
|
||||
v1sz = ALIGN_UP(vring_size(rsc->rpmsg_vring1.num, align1), align1);
|
||||
|
||||
shbuf0 = (FAR char *)rsc + tbsz + v0sz + v1sz;
|
||||
shbufsz0 = rsc->config.r2h_buf_size * rsc->rpmsg_vring0.num;
|
||||
shbuf1 = shbuf0 + shbufsz0;
|
||||
shbufsz1 = rsc->config.h2r_buf_size * rsc->rpmsg_vring1.num;
|
||||
|
||||
rvrings[0].io = metal_io_get_region();
|
||||
rvrings[0].info.vaddr = (FAR char *)rsc + tbsz;
|
||||
rvrings[0].info.num_descs = rsc->rpmsg_vring0.num;
|
||||
rvrings[0].info.align = rsc->rpmsg_vring0.align;
|
||||
rvrings[0].vq = virtqueue_allocate(rsc->rpmsg_vring0.num);
|
||||
if (rvrings[0].vq == NULL)
|
||||
{
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
rvrings[1].io = metal_io_get_region();
|
||||
rvrings[1].info.vaddr = (FAR char *)rsc + tbsz + v0sz;
|
||||
rvrings[1].info.num_descs = rsc->rpmsg_vring1.num;
|
||||
rvrings[1].info.align = rsc->rpmsg_vring1.align;
|
||||
rvrings[1].vq = virtqueue_allocate(rsc->rpmsg_vring1.num);
|
||||
if (rvrings[1].vq == NULL)
|
||||
{
|
||||
ret = -ENOMEM;
|
||||
goto err_vq0;
|
||||
}
|
||||
|
||||
vdev->vrings_info = &rvrings[0];
|
||||
|
||||
rpmsg_virtio_init_shm_pool(&priv->pool[0], shbuf0, shbufsz0);
|
||||
rpmsg_virtio_init_shm_pool(&priv->pool[1], shbuf1, shbufsz1);
|
||||
|
||||
config.h2r_buf_size = rsc->config.h2r_buf_size;
|
||||
config.r2h_buf_size = rsc->config.r2h_buf_size;
|
||||
config.split_shpool = true;
|
||||
|
||||
ret = rpmsg_init_vdev_with_config(&priv->rvdev, vdev, rpmsg_ns_bind,
|
||||
metal_io_get_region(),
|
||||
priv->pool, &config);
|
||||
if (ret != 0)
|
||||
{
|
||||
rpmsgerr("rpmsg_init_vdev failed %d\n", ret);
|
||||
ret = -ENOMEM;
|
||||
goto err_vq1;
|
||||
}
|
||||
|
||||
priv->rvdev.rdev.ns_unbind_cb = rpmsg_ns_unbind;
|
||||
priv->rvdev.notify_wait_cb = rpmsg_virtio_lite_notify_wait;
|
||||
|
||||
RPMSG_VIRTIO_LITE_REGISTER_CALLBACK(priv->dev, rpmsg_virtio_lite_callback,
|
||||
priv);
|
||||
|
||||
rpmsg_virtio_lite_update_rx(priv);
|
||||
rpmsg_virtio_lite_wakeup_rx(priv);
|
||||
|
||||
/* Broadcast device_created to all registers */
|
||||
|
||||
rpmsg_device_created(&priv->rpmsg);
|
||||
|
||||
return 0;
|
||||
|
||||
err_vq1:
|
||||
virtqueue_free(rvrings[1].vq);
|
||||
err_vq0:
|
||||
virtqueue_free(rvrings[0].vq);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int rpmsg_virtio_lite_thread(int argc, FAR char *argv[])
|
||||
{
|
||||
FAR struct rpmsg_virtio_lite_priv_s *priv =
|
||||
(FAR struct rpmsg_virtio_lite_priv_s *)
|
||||
((uintptr_t)strtoul(argv[2], NULL, 16));
|
||||
int ret;
|
||||
|
||||
priv->tid = nxsched_gettid();
|
||||
|
||||
ret = rpmsg_virtio_lite_start(priv);
|
||||
if (ret < 0)
|
||||
{
|
||||
rpmsgerr("rpmsg virtio thread start failed %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
while (1)
|
||||
{
|
||||
nxsem_wait_uninterruptible(&priv->semrx);
|
||||
if (rpmsg_virtio_lite_available_rx(priv))
|
||||
{
|
||||
virtqueue_notification(priv->rvdev.rvq);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
****************************************************************************/
|
||||
|
||||
int rpmsg_virtio_lite_initialize(FAR struct rpmsg_virtio_lite_s *dev)
|
||||
{
|
||||
FAR struct rpmsg_virtio_lite_priv_s *priv;
|
||||
FAR char *argv[3];
|
||||
char arg1[32];
|
||||
char name[32];
|
||||
int ret;
|
||||
|
||||
priv = kmm_zalloc(sizeof(struct rpmsg_virtio_lite_priv_s));
|
||||
if (priv == NULL)
|
||||
{
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
priv->dev = dev;
|
||||
nxsem_init(&priv->semrx, 0, 0);
|
||||
nxsem_init(&priv->semtx, 0, 0);
|
||||
|
||||
snprintf(name, sizeof(name), "/dev/rpmsg/%s",
|
||||
RPMSG_VIRTIO_LITE_GET_CPUNAME(dev));
|
||||
ret = rpmsg_register(name, &priv->rpmsg, &g_rpmsg_virtio_lite_ops);
|
||||
if (ret < 0)
|
||||
{
|
||||
goto err_driver;
|
||||
}
|
||||
|
||||
snprintf(arg1, sizeof(arg1), "%p", priv);
|
||||
argv[0] = (FAR char *)RPMSG_VIRTIO_LITE_GET_CPUNAME(dev);
|
||||
argv[1] = arg1;
|
||||
argv[2] = NULL;
|
||||
|
||||
ret = kthread_create("rpmsg_virtio", CONFIG_RPMSG_VIRTIO_LITE_PRIORITY,
|
||||
CONFIG_RPMSG_VIRTIO_LITE_STACKSIZE,
|
||||
rpmsg_virtio_lite_thread, argv);
|
||||
if (ret < 0)
|
||||
{
|
||||
goto err_thread;
|
||||
}
|
||||
|
||||
return OK;
|
||||
|
||||
err_thread:
|
||||
rpmsg_unregister(name, &priv->rpmsg);
|
||||
|
||||
err_driver:
|
||||
nxsem_destroy(&priv->semrx);
|
||||
nxsem_destroy(&priv->semtx);
|
||||
kmm_free(priv);
|
||||
|
||||
return ret;
|
||||
}
|
|
@ -1,5 +1,5 @@
|
|||
/****************************************************************************
|
||||
* include/nuttx/rpmsg/rpmsg_virtio.h
|
||||
* include/nuttx/rpmsg/rpmsg_virtio_lite.h
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
|
@ -20,8 +20,8 @@
|
|||
*
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef __INCLUDE_NUTTX_RPMSG_RPMSG_VIRTIO_H
|
||||
#define __INCLUDE_NUTTX_RPMSG_RPMSG_VIRTIO_H
|
||||
#ifndef __INCLUDE_NUTTX_RPMSG_RPMSG_VIRTIO_LITE_H
|
||||
#define __INCLUDE_NUTTX_RPMSG_RPMSG_VIRTIO_LITE_H
|
||||
|
||||
/****************************************************************************
|
||||
* Included Files
|
||||
|
@ -29,7 +29,7 @@
|
|||
|
||||
#include <nuttx/config.h>
|
||||
|
||||
#ifdef CONFIG_RPMSG_VIRTIO
|
||||
#ifdef CONFIG_RPMSG_VIRTIO_LITE
|
||||
|
||||
#include <nuttx/rpmsg/rpmsg.h>
|
||||
#include <openamp/rpmsg_virtio.h>
|
||||
|
@ -39,24 +39,24 @@
|
|||
* Pre-processor Definitions
|
||||
****************************************************************************/
|
||||
|
||||
#define RPMSG_VIRTIO_NOTIFY_ALL UINT32_MAX
|
||||
#define RPMSG_VIRTIO_LITE_NOTIFY_ALL UINT32_MAX
|
||||
|
||||
#define RPMSG_VIRTIO_CMD_PANIC 0x1
|
||||
#define RPMSG_VIRTIO_CMD_MASK 0xffff
|
||||
#define RPMSG_VIRTIO_CMD_SHIFT 16
|
||||
#define RPMSG_VIRTIO_LITE_CMD_PANIC 0x1
|
||||
#define RPMSG_VIRTIO_LITE_CMD_MASK 0xffff
|
||||
#define RPMSG_VIRTIO_LITE_CMD_SHIFT 16
|
||||
|
||||
#define RPMSG_VIRTIO_CMD(c,v) (((c) << RPMSG_VIRTIO_CMD_SHIFT) | \
|
||||
((v) & RPMSG_VIRTIO_CMD_MASK))
|
||||
#define RPMSG_VIRTIO_GET_CMD(c) ((c) >> RPMSG_VIRTIO_CMD_SHIFT)
|
||||
#define RPMSG_VIRTIO_LITE_CMD(c,v) (((c) << RPMSG_VIRTIO_LITE_CMD_SHIFT) | \
|
||||
((v) & RPMSG_VIRTIO_LITE_CMD_MASK))
|
||||
#define RPMSG_VIRTIO_LITE_GET_CMD(c) ((c) >> RPMSG_VIRTIO_LITE_CMD_SHIFT)
|
||||
|
||||
#define RPMSG_VIRTIO_RSC2CMD(r) \
|
||||
((FAR struct rpmsg_virtio_cmd_s *) \
|
||||
&((FAR struct resource_table *)(r))->reserved[0])
|
||||
#define RPMSG_VIRTIO_LITE_RSC2CMD(r) \
|
||||
((FAR struct rpmsg_virtio_lite_cmd_s *) \
|
||||
&((FAR struct resource_table *)(r))->reserved[0])
|
||||
|
||||
/* Access macros ************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: RPMSG_VIRTIO_GET_LOCAL_CPUNAME
|
||||
* Name: RPMSG_VIRTIO_LITE_GET_LOCAL_CPUNAME
|
||||
*
|
||||
* Description:
|
||||
* Get remote cpu name
|
||||
|
@ -69,11 +69,11 @@
|
|||
*
|
||||
****************************************************************************/
|
||||
|
||||
#define RPMSG_VIRTIO_GET_LOCAL_CPUNAME(d) \
|
||||
#define RPMSG_VIRTIO_LITE_GET_LOCAL_CPUNAME(d) \
|
||||
((d)->ops->get_local_cpuname ? (d)->ops->get_local_cpuname(d) : "")
|
||||
|
||||
/****************************************************************************
|
||||
* Name: RPMSG_VIRTIO_GET_CPUNAME
|
||||
* Name: RPMSG_VIRTIO_LITE_GET_CPUNAME
|
||||
*
|
||||
* Description:
|
||||
* Get remote cpu name
|
||||
|
@ -86,11 +86,11 @@
|
|||
*
|
||||
****************************************************************************/
|
||||
|
||||
#define RPMSG_VIRTIO_GET_CPUNAME(d) \
|
||||
#define RPMSG_VIRTIO_LITE_GET_CPUNAME(d) \
|
||||
((d)->ops->get_cpuname ? (d)->ops->get_cpuname(d) : "")
|
||||
|
||||
/****************************************************************************
|
||||
* Name: RPMSG_VIRTIO_GET_RESOURCE
|
||||
* Name: RPMSG_VIRTIO_LITE_GET_RESOURCE
|
||||
*
|
||||
* Description:
|
||||
* Get rpmsg virtio resource
|
||||
|
@ -103,11 +103,11 @@
|
|||
*
|
||||
****************************************************************************/
|
||||
|
||||
#define RPMSG_VIRTIO_GET_RESOURCE(d) \
|
||||
#define RPMSG_VIRTIO_LITE_GET_RESOURCE(d) \
|
||||
((d)->ops->get_resource ? (d)->ops->get_resource(d) : NULL)
|
||||
|
||||
/****************************************************************************
|
||||
* Name: RPMSG_VIRTIO_IS_MASTER
|
||||
* Name: RPMSG_VIRTIO_LITE_IS_MASTER
|
||||
*
|
||||
* Description:
|
||||
* Is master or not
|
||||
|
@ -120,11 +120,11 @@
|
|||
*
|
||||
****************************************************************************/
|
||||
|
||||
#define RPMSG_VIRTIO_IS_MASTER(d) \
|
||||
#define RPMSG_VIRTIO_LITE_IS_MASTER(d) \
|
||||
((d)->ops->is_master ? (d)->ops->is_master(d) : false)
|
||||
|
||||
/****************************************************************************
|
||||
* Name: RPMSG_VIRTIO_REGISTER_CALLBACK
|
||||
* Name: RPMSG_VIRTIO_LITE_REGISTER_CALLBACK
|
||||
*
|
||||
* Description:
|
||||
* Attach to receive a callback when something is received on RPTUN
|
||||
|
@ -139,11 +139,11 @@
|
|||
*
|
||||
****************************************************************************/
|
||||
|
||||
#define RPMSG_VIRTIO_REGISTER_CALLBACK(d,c,a) \
|
||||
#define RPMSG_VIRTIO_LITE_REGISTER_CALLBACK(d,c,a) \
|
||||
((d)->ops->register_callback ? (d)->ops->register_callback(d,c,a) : -ENOSYS)
|
||||
|
||||
/****************************************************************************
|
||||
* Name: RPMSG_VIRTIO_NOTIFY
|
||||
* Name: RPMSG_VIRTIO_LITE_NOTIFY
|
||||
*
|
||||
* Description:
|
||||
* Notify remote core there is a message to get.
|
||||
|
@ -157,7 +157,7 @@
|
|||
*
|
||||
****************************************************************************/
|
||||
|
||||
#define RPMSG_VIRTIO_NOTIFY(d,v) \
|
||||
#define RPMSG_VIRTIO_LITE_NOTIFY(d,v) \
|
||||
((d)->ops->notify ? (d)->ops->notify(d,v) : -ENOSYS)
|
||||
|
||||
/****************************************************************************
|
||||
|
@ -166,13 +166,13 @@
|
|||
|
||||
typedef CODE int (*rpmsg_virtio_callback_t)(FAR void *arg, uint32_t vqid);
|
||||
|
||||
begin_packed_struct struct rpmsg_virtio_cmd_s
|
||||
begin_packed_struct struct rpmsg_virtio_lite_cmd_s
|
||||
{
|
||||
uint32_t cmd_master;
|
||||
uint32_t cmd_slave;
|
||||
} end_packed_struct;
|
||||
|
||||
struct aligned_data(8) rpmsg_virtio_rsc_s
|
||||
struct aligned_data(8) rpmsg_virtio_lite_rsc_s
|
||||
{
|
||||
struct resource_table rsc_tbl_hdr;
|
||||
uint32_t offset[2];
|
||||
|
@ -183,23 +183,24 @@ struct aligned_data(8) rpmsg_virtio_rsc_s
|
|||
struct fw_rsc_config config;
|
||||
};
|
||||
|
||||
struct rpmsg_virtio_s;
|
||||
struct rpmsg_virtio_ops_s
|
||||
struct rpmsg_virtio_lite_s;
|
||||
struct rpmsg_virtio_lite_ops_s
|
||||
{
|
||||
CODE FAR const char *(*get_local_cpuname)(FAR struct rpmsg_virtio_s *dev);
|
||||
CODE FAR const char *(*get_cpuname)(FAR struct rpmsg_virtio_s *dev);
|
||||
CODE FAR struct rpmsg_virtio_rsc_s *
|
||||
(*get_resource)(FAR struct rpmsg_virtio_s *dev);
|
||||
CODE int (*is_master)(FAR struct rpmsg_virtio_s *dev);
|
||||
CODE int (*notify)(FAR struct rpmsg_virtio_s *dev, uint32_t vqid);
|
||||
CODE int (*register_callback)(FAR struct rpmsg_virtio_s *dev,
|
||||
CODE FAR const char *
|
||||
(*get_local_cpuname)(FAR struct rpmsg_virtio_lite_s *dev);
|
||||
CODE FAR const char *(*get_cpuname)(FAR struct rpmsg_virtio_lite_s *dev);
|
||||
CODE FAR struct rpmsg_virtio_lite_rsc_s *
|
||||
(*get_resource)(FAR struct rpmsg_virtio_lite_s *dev);
|
||||
CODE int (*is_master)(FAR struct rpmsg_virtio_lite_s *dev);
|
||||
CODE int (*notify)(FAR struct rpmsg_virtio_lite_s *dev, uint32_t vqid);
|
||||
CODE int (*register_callback)(FAR struct rpmsg_virtio_lite_s *dev,
|
||||
rpmsg_virtio_callback_t callback,
|
||||
FAR void *arg);
|
||||
};
|
||||
|
||||
struct rpmsg_virtio_s
|
||||
struct rpmsg_virtio_lite_s
|
||||
{
|
||||
FAR const struct rpmsg_virtio_ops_s *ops;
|
||||
FAR const struct rpmsg_virtio_lite_ops_s *ops;
|
||||
};
|
||||
|
||||
/****************************************************************************
|
||||
|
@ -214,12 +215,12 @@ extern "C"
|
|||
#define EXTERN extern
|
||||
#endif
|
||||
|
||||
int rpmsg_virtio_initialize(FAR struct rpmsg_virtio_s *dev);
|
||||
int rpmsg_virtio_lite_initialize(FAR struct rpmsg_virtio_lite_s *dev);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* CONFIG_RPTUN */
|
||||
#endif /* CONFIG_RPMSG_VIRTIO_LITE */
|
||||
|
||||
#endif /* __INCLUDE_NUTTX_RPMSG_RPMSG_VIRTIO_H */
|
||||
#endif /* __INCLUDE_NUTTX_RPMSG_RPMSG_VIRTIO_LITE_H */
|
Loading…
Reference in a new issue