rpmsg_virtio_ivshmem.c: rpmsg virtio ivshmem msix interrupt support
Change the rpmsg_virtio_ivshmem from pci bus based to pci-ivshmem bus based, so rpmsg_virtio_ivshmem can support interrupt mode and also support the multi instance. Signed-off-by: wangyongrong <wangyongrong@xiaomi.com> Signed-off-by: Bowen Wang <wangbowen6@xiaomi.com>
This commit is contained in:
parent
3ca717ef4a
commit
57cb0cb66f
@ -41,7 +41,7 @@ config RPMSG_VIRTIO_STACKSIZE
|
|||||||
config RPMSG_VIRTIO_IVSHMEM
|
config RPMSG_VIRTIO_IVSHMEM
|
||||||
bool "rpmsg virtio ivshmem support"
|
bool "rpmsg virtio ivshmem support"
|
||||||
default n
|
default n
|
||||||
depends on PCI
|
depends on PCI_IVSHMEM
|
||||||
---help---
|
---help---
|
||||||
This is rpmsg virtio driver based on pci ivshmem.
|
This is rpmsg virtio driver based on pci ivshmem.
|
||||||
|
|
||||||
@ -50,11 +50,11 @@ if RPMSG_VIRTIO_IVSHMEM
|
|||||||
config RPMSG_VIRTIO_IVSHMEM_NAME
|
config RPMSG_VIRTIO_IVSHMEM_NAME
|
||||||
string "rpmsg virtio ivshmem name"
|
string "rpmsg virtio ivshmem name"
|
||||||
---help---
|
---help---
|
||||||
Using this config to custom the rpmsg virtio ivshmem cpuname and role,
|
Using this config to custom the rpmsg virtio ivshmem id, cpuname and role,
|
||||||
using ";" to split the names.
|
using ";" to split the names.
|
||||||
For example, if RPMSG_VIRTIO_IVSHMEM_CPUNAME = "cpu1:m;cpu2:s" and pass
|
For example, if RPMSG_VIRTIO_IVSHMEM_CPUNAME = "0:cpu1:m;1:cpu2:s" and pass
|
||||||
two ivshmem devices to the qemu, we will get two rpmsg virtio ivshmem drivers
|
two ivshmem devices to the qemu, we will get two rpmsg virtio ivshmem drivers
|
||||||
with remote cpu names: "cpu1", "cpu2", and roles: "master", "slave"
|
with remote cpu ids: "0","1", names: "cpu1", "cpu2", and roles: "master", "slave"
|
||||||
|
|
||||||
config RPMSG_VIRTIO_IVSHMEM_BUFFSIZE
|
config RPMSG_VIRTIO_IVSHMEM_BUFFSIZE
|
||||||
int "rpmsg virtio ivshmem rpmsg buffer size"
|
int "rpmsg virtio ivshmem rpmsg buffer size"
|
||||||
|
@ -29,7 +29,7 @@
|
|||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
|
||||||
#include <nuttx/drivers/addrenv.h>
|
#include <nuttx/drivers/addrenv.h>
|
||||||
#include <nuttx/pci/pci.h>
|
#include <nuttx/pci/pci_ivshmem.h>
|
||||||
#include <nuttx/rpmsg/rpmsg_virtio.h>
|
#include <nuttx/rpmsg/rpmsg_virtio.h>
|
||||||
#include <nuttx/rpmsg/rpmsg_virtio_ivshmem.h>
|
#include <nuttx/rpmsg/rpmsg_virtio_ivshmem.h>
|
||||||
|
|
||||||
@ -37,8 +37,9 @@
|
|||||||
* Pre-processor Definitions
|
* Pre-processor Definitions
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
#define RPMSG_VIRTIO_IVSHMEM_SHMEM_BAR 2
|
#define rpmsg_virtio_ivshmem_from(dev) \
|
||||||
#define RPMSG_VIRTIO_IVSHMEM_READY 0x1
|
container_of(ivshmem_get_driver(dev), struct rpmsg_virtio_ivshmem_dev_s, drv)
|
||||||
|
|
||||||
#define RPMSG_VIRTIO_IVSHMEM_WORK_DELAY 1
|
#define RPMSG_VIRTIO_IVSHMEM_WORK_DELAY 1
|
||||||
|
|
||||||
#define RPMSG_VIRTIO_VRING_ALIGNMENT 8
|
#define RPMSG_VIRTIO_VRING_ALIGNMENT 8
|
||||||
@ -60,6 +61,8 @@ struct rpmsg_virtio_ivshmem_mem_s
|
|||||||
struct rpmsg_virtio_ivshmem_dev_s
|
struct rpmsg_virtio_ivshmem_dev_s
|
||||||
{
|
{
|
||||||
struct rpmsg_virtio_s dev;
|
struct rpmsg_virtio_s dev;
|
||||||
|
struct ivshmem_driver_s drv;
|
||||||
|
FAR struct ivshmem_device_s *ivdev;
|
||||||
rpmsg_virtio_callback_t callback;
|
rpmsg_virtio_callback_t callback;
|
||||||
FAR void *arg;
|
FAR void *arg;
|
||||||
uint32_t seq;
|
uint32_t seq;
|
||||||
@ -91,9 +94,8 @@ static int
|
|||||||
rpmsg_virtio_ivshmem_register_callback(FAR struct rpmsg_virtio_s *dev,
|
rpmsg_virtio_ivshmem_register_callback(FAR struct rpmsg_virtio_s *dev,
|
||||||
rpmsg_virtio_callback_t callback,
|
rpmsg_virtio_callback_t callback,
|
||||||
FAR void *arg);
|
FAR void *arg);
|
||||||
|
static int rpmsg_virtio_ivshmem_probe(FAR struct ivshmem_device_s *ivdev);
|
||||||
static int rpmsg_virtio_ivshmem_probe(FAR struct pci_device_s *dev);
|
static void rpmsg_virtio_ivshmem_remove(FAR struct ivshmem_device_s *ivdev);
|
||||||
static void rpmsg_virtio_ivshmem_remove(FAR struct pci_device_s *dev);
|
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* Private Data
|
* Private Data
|
||||||
@ -108,21 +110,6 @@ static const struct rpmsg_virtio_ops_s g_rpmsg_virtio_ivshmem_ops =
|
|||||||
.register_callback = rpmsg_virtio_ivshmem_register_callback,
|
.register_callback = rpmsg_virtio_ivshmem_register_callback,
|
||||||
};
|
};
|
||||||
|
|
||||||
static const struct pci_device_id_s g_rpmsg_virtio_ivshmem_ids[] =
|
|
||||||
{
|
|
||||||
{ PCI_DEVICE(0x1af4, 0x1110) },
|
|
||||||
{ 0, }
|
|
||||||
};
|
|
||||||
|
|
||||||
static struct pci_driver_s g_rpmsg_virtio_ivshmem_drv =
|
|
||||||
{
|
|
||||||
g_rpmsg_virtio_ivshmem_ids, /* PCI id_tables */
|
|
||||||
rpmsg_virtio_ivshmem_probe, /* Probe function */
|
|
||||||
rpmsg_virtio_ivshmem_remove, /* Remove function */
|
|
||||||
};
|
|
||||||
|
|
||||||
static int g_rpmsg_virtio_ivshmem_idx = 0;
|
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* Private Functions
|
* Private Functions
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
@ -199,7 +186,11 @@ static int rpmsg_virtio_ivshmem_notify(FAR struct rpmsg_virtio_s *dev,
|
|||||||
FAR struct rpmsg_virtio_ivshmem_dev_s *priv =
|
FAR struct rpmsg_virtio_ivshmem_dev_s *priv =
|
||||||
(FAR struct rpmsg_virtio_ivshmem_dev_s *)dev;
|
(FAR struct rpmsg_virtio_ivshmem_dev_s *)dev;
|
||||||
|
|
||||||
if (priv->master)
|
if (ivshmem_support_irq(priv->ivdev))
|
||||||
|
{
|
||||||
|
ivshmem_kick_peer(priv->ivdev);
|
||||||
|
}
|
||||||
|
else if (priv->master)
|
||||||
{
|
{
|
||||||
priv->shmem->seqm++;
|
priv->shmem->seqm++;
|
||||||
}
|
}
|
||||||
@ -224,6 +215,23 @@ rpmsg_virtio_ivshmem_register_callback(FAR struct rpmsg_virtio_s *dev,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Name: rpmsg_virtio_ivshmem_interrupt
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
static int rpmsg_virtio_ivshmem_interrupt(int irq, FAR void *context,
|
||||||
|
FAR void *arg)
|
||||||
|
{
|
||||||
|
FAR struct rpmsg_virtio_ivshmem_dev_s *priv = arg;
|
||||||
|
|
||||||
|
if (priv->callback != NULL)
|
||||||
|
{
|
||||||
|
priv->callback(priv->arg, RPMSG_VIRTIO_NOTIFY_ALL);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* Name: rpmsg_virtio_ivshmem_work
|
* Name: rpmsg_virtio_ivshmem_work
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
@ -253,84 +261,24 @@ static void rpmsg_virtio_ivshmem_work(FAR void *arg)
|
|||||||
RPMSG_VIRTIO_IVSHMEM_WORK_DELAY);
|
RPMSG_VIRTIO_IVSHMEM_WORK_DELAY);
|
||||||
}
|
}
|
||||||
|
|
||||||
/****************************************************************************
|
|
||||||
* Name: rpmsg_virtio_ivshmem_get_info
|
|
||||||
****************************************************************************/
|
|
||||||
|
|
||||||
static int rpmsg_virtio_ivshmem_get_info(FAR char *cpuname, FAR int *master)
|
|
||||||
{
|
|
||||||
FAR const char *name = CONFIG_RPMSG_VIRTIO_IVSHMEM_NAME;
|
|
||||||
int start = 0;
|
|
||||||
int i;
|
|
||||||
int j;
|
|
||||||
|
|
||||||
for (i = 0, j = 0; name[start] != '\0'; i++)
|
|
||||||
{
|
|
||||||
if (name[i] == ';' || name[i] == '\0')
|
|
||||||
{
|
|
||||||
if (j++ == g_rpmsg_virtio_ivshmem_idx)
|
|
||||||
{
|
|
||||||
snprintf(cpuname, RPMSG_NAME_SIZE, "%.*s", i - start - 2,
|
|
||||||
&name[start]);
|
|
||||||
*master = name[i - 1] == 'm';
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
start = i + 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return -ENODEV;
|
|
||||||
}
|
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* Name: rpmsg_virtio_ivshmem_probe
|
* Name: rpmsg_virtio_ivshmem_probe
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
static int rpmsg_virtio_ivshmem_probe(FAR struct pci_device_s *dev)
|
static int rpmsg_virtio_ivshmem_probe(FAR struct ivshmem_device_s *ivdev)
|
||||||
{
|
{
|
||||||
FAR struct rpmsg_virtio_ivshmem_dev_s *priv;
|
FAR struct rpmsg_virtio_ivshmem_dev_s *priv =
|
||||||
|
rpmsg_virtio_ivshmem_from(ivdev);
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
priv = kmm_zalloc(sizeof(*priv));
|
|
||||||
if (priv == NULL)
|
|
||||||
{
|
|
||||||
return -ENOMEM;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Do the rpmsg virtio ivshmem init */
|
/* Do the rpmsg virtio ivshmem init */
|
||||||
|
|
||||||
|
priv->ivdev = ivdev;
|
||||||
priv->dev.ops = &g_rpmsg_virtio_ivshmem_ops;
|
priv->dev.ops = &g_rpmsg_virtio_ivshmem_ops;
|
||||||
priv->ivshmem = dev;
|
priv->shmem = ivshmem_get_shmem(ivdev, &priv->shmem_size);
|
||||||
ret = rpmsg_virtio_ivshmem_get_info(priv->cpuname, &priv->master);
|
|
||||||
if (ret < 0)
|
|
||||||
{
|
|
||||||
goto err_priv;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Configure the ivshmem device and get share memory address */
|
ivshmem_attach_irq(ivdev, rpmsg_virtio_ivshmem_interrupt, priv);
|
||||||
|
ivshmem_control_irq(ivdev, true);
|
||||||
ret = pci_enable_device(dev);
|
|
||||||
if (ret < 0)
|
|
||||||
{
|
|
||||||
pcierr("Enable device failed, ret=%d\n", ret);
|
|
||||||
goto err_priv;
|
|
||||||
}
|
|
||||||
|
|
||||||
pci_set_master(dev);
|
|
||||||
|
|
||||||
priv->shmem = (FAR struct rpmsg_virtio_ivshmem_mem_s *)
|
|
||||||
pci_map_bar(dev, RPMSG_VIRTIO_IVSHMEM_SHMEM_BAR);
|
|
||||||
if (priv->shmem == NULL)
|
|
||||||
{
|
|
||||||
ret = -ENOTSUP;
|
|
||||||
pcierr("Device not support share memory bar\n");
|
|
||||||
goto err_master;
|
|
||||||
}
|
|
||||||
|
|
||||||
priv->shmem_size = pci_resource_len(dev, RPMSG_VIRTIO_IVSHMEM_SHMEM_BAR);
|
|
||||||
|
|
||||||
pciinfo("shmem addr=%p size=%zu\n", priv->shmem, priv->shmem_size);
|
|
||||||
|
|
||||||
/* Do rpmsg virtio initialize */
|
/* Do rpmsg virtio initialize */
|
||||||
|
|
||||||
@ -338,18 +286,20 @@ static int rpmsg_virtio_ivshmem_probe(FAR struct pci_device_s *dev)
|
|||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
{
|
{
|
||||||
pcierr("rpmsg virtio intialize failed, ret=%d\n", ret);
|
pcierr("rpmsg virtio intialize failed, ret=%d\n", ret);
|
||||||
goto err_master;
|
goto err;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!ivshmem_support_irq(ivdev))
|
||||||
|
{
|
||||||
|
work_queue(HPWORK, &priv->worker, rpmsg_virtio_ivshmem_work, priv, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
work_queue(HPWORK, &priv->worker, rpmsg_virtio_ivshmem_work, priv, 0);
|
|
||||||
g_rpmsg_virtio_ivshmem_idx++;
|
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
err_master:
|
err:
|
||||||
pci_clear_master(dev);
|
ivshmem_unregister_driver(&priv->drv);
|
||||||
pci_disable_device(dev);
|
ivshmem_control_irq(ivdev, false);
|
||||||
err_priv:
|
ivshmem_detach_irq(ivdev);
|
||||||
kmm_free(priv);
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -357,9 +307,15 @@ err_priv:
|
|||||||
* Name: rpmsg_virtio_ivshmem_remove
|
* Name: rpmsg_virtio_ivshmem_remove
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
static void rpmsg_virtio_ivshmem_remove(FAR struct pci_device_s *dev)
|
static void rpmsg_virtio_ivshmem_remove(FAR struct ivshmem_device_s *ivdev)
|
||||||
{
|
{
|
||||||
pciwarn("Not support remove for now\n");
|
FAR struct rpmsg_virtio_ivshmem_dev_s *priv =
|
||||||
|
rpmsg_virtio_ivshmem_from(ivdev);
|
||||||
|
|
||||||
|
work_cancel_sync(HPWORK, &priv->worker);
|
||||||
|
ivshmem_control_irq(ivdev, false);
|
||||||
|
ivshmem_detach_irq(ivdev);
|
||||||
|
kmm_free(priv);
|
||||||
}
|
}
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
@ -368,5 +324,41 @@ static void rpmsg_virtio_ivshmem_remove(FAR struct pci_device_s *dev)
|
|||||||
|
|
||||||
int pci_register_rpmsg_virtio_ivshmem_driver(void)
|
int pci_register_rpmsg_virtio_ivshmem_driver(void)
|
||||||
{
|
{
|
||||||
return pci_register_driver(&g_rpmsg_virtio_ivshmem_drv);
|
FAR char *name = CONFIG_RPMSG_VIRTIO_IVSHMEM_NAME;
|
||||||
|
|
||||||
|
while (name != NULL)
|
||||||
|
{
|
||||||
|
FAR const char *str;
|
||||||
|
|
||||||
|
FAR struct rpmsg_virtio_ivshmem_dev_s * priv =
|
||||||
|
kmm_zalloc(sizeof(*priv));
|
||||||
|
if (priv == NULL)
|
||||||
|
{
|
||||||
|
return -ENOMEM;
|
||||||
|
}
|
||||||
|
|
||||||
|
priv->drv.id = strtoul(name, &name, 0);
|
||||||
|
str = strchr(++name, ':');
|
||||||
|
snprintf(priv->cpuname, RPMSG_NAME_SIZE, "%.*s", (int)(str - name),
|
||||||
|
name);
|
||||||
|
priv->master = *(str + 1) == 'm';
|
||||||
|
|
||||||
|
pciinfo("Register ivshmem driver, id=%d, cpuname=%s, master=%d\n",
|
||||||
|
priv->drv.id, priv->cpuname, priv->master);
|
||||||
|
|
||||||
|
priv->drv.probe = rpmsg_virtio_ivshmem_probe;
|
||||||
|
priv->drv.remove = rpmsg_virtio_ivshmem_remove;
|
||||||
|
if (ivshmem_register_driver(&priv->drv) < 0)
|
||||||
|
{
|
||||||
|
kmm_free(priv);
|
||||||
|
}
|
||||||
|
|
||||||
|
name = strchr(str, ';');
|
||||||
|
if (name != NULL)
|
||||||
|
{
|
||||||
|
name++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user