You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@nuttx.apache.org by xi...@apache.org on 2024/09/10 06:34:44 UTC
(nuttx) 07/10: pci/pci_uio_ivshmem: add pci uio ivshmem driver support
This is an automated email from the ASF dual-hosted git repository.
xiaoxiang pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/nuttx.git
commit ccb17f2bb4a6c59800b7fa462e2a6522f048f6bc
Author: Bowen Wang <wa...@xiaomi.com>
AuthorDate: Wed Feb 28 21:14:01 2024 +0800
pci/pci_uio_ivshmem: add pci uio ivshmem driver support
Application can open "/dev/uioX" and use `mmap()` to get the
memory provided by ivshmem device.
Signed-off-by: Bowen Wang <wa...@xiaomi.com>
---
drivers/pci/Kconfig | 9 +
drivers/pci/Make.defs | 4 +
drivers/pci/pci_drivers.c | 10 +
drivers/pci/{pci_drivers.c => pci_drivers.h} | 60 +-----
drivers/pci/pci_uio_ivshmem.c | 310 +++++++++++++++++++++++++++
5 files changed, 342 insertions(+), 51 deletions(-)
diff --git a/drivers/pci/Kconfig b/drivers/pci/Kconfig
index f6396b2e81..b100b19ec1 100644
--- a/drivers/pci/Kconfig
+++ b/drivers/pci/Kconfig
@@ -31,4 +31,13 @@ config PCI_QEMU_EDU
---help---
Driver for QEMU EDU test device
+config PCI_UIO_IVSHMEM
+ bool "Enable uio ivshmem driver support"
+ default n
+ ---help---
+ When this option is enabled, char ivshmem driver will register
+ char device with name: "/dev/uioX" to the VFS, then
+ application can open this device and use `mmap()` to get the
+ share memory provided by ivshmem device.
+
endif # PCI
diff --git a/drivers/pci/Make.defs b/drivers/pci/Make.defs
index efdfd66082..7b3b665859 100644
--- a/drivers/pci/Make.defs
+++ b/drivers/pci/Make.defs
@@ -29,6 +29,10 @@ ifeq ($(CONFIG_PCI_QEMU_EDU),y)
CSRCS += pci_qemu_edu.c
endif
+ifeq ($(CONFIG_PCI_UIO_IVSHMEM),y)
+CSRCS += pci_uio_ivshmem.c
+endif
+
# Include PCI device driver build support
DEPPATH += --dep-path pci
diff --git a/drivers/pci/pci_drivers.c b/drivers/pci/pci_drivers.c
index c7010b4179..454d51677a 100644
--- a/drivers/pci/pci_drivers.c
+++ b/drivers/pci/pci_drivers.c
@@ -29,6 +29,8 @@
#include <nuttx/pci/pci_qemu_test.h>
#include <nuttx/rptun/rptun_ivshmem.h>
+#include "pci_drivers.h"
+
/****************************************************************************
* Public Functions
****************************************************************************/
@@ -45,6 +47,14 @@ int pci_register_drivers(void)
{
int ret;
+#ifdef CONFIG_PCI_UIO_IVSHMEM
+ ret = pci_register_uio_ivshmem_driver();
+ if (ret < 0)
+ {
+ pcierr("pci_register_uio_ivshmem_driver failed, ret=%d\n", ret);
+ }
+#endif
+
/* Initialization pci qemu test driver */
#ifdef CONFIG_PCI_QEMU_TEST
diff --git a/drivers/pci/pci_drivers.c b/drivers/pci/pci_drivers.h
similarity index 52%
copy from drivers/pci/pci_drivers.c
copy to drivers/pci/pci_drivers.h
index c7010b4179..f989c671cd 100644
--- a/drivers/pci/pci_drivers.c
+++ b/drivers/pci/pci_drivers.h
@@ -1,5 +1,5 @@
/****************************************************************************
- * drivers/pci/pci_drivers.c
+ * drivers/pci/pci_drivers.h
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
@@ -18,63 +18,21 @@
*
****************************************************************************/
+#ifndef __DRIVERS_PCI_PCI_DRIVERS_H
+#define __DRIVERS_PCI_PCI_DRIVERS_H
+
/****************************************************************************
* Included Files
****************************************************************************/
-#include <debug.h>
-
-#include <nuttx/pci/pci.h>
-#include <nuttx/pci/pci_qemu_edu.h>
-#include <nuttx/pci/pci_qemu_test.h>
-#include <nuttx/rptun/rptun_ivshmem.h>
-
-/****************************************************************************
- * Public Functions
- ****************************************************************************/
+#include <nuttx/config.h>
/****************************************************************************
- * Name: pci_register_drivers
- *
- * Description:
- * Register all the pci drivers to pci bus
- *
+ * Public Function Prototypes
****************************************************************************/
-int pci_register_drivers(void)
-{
- int ret;
-
- /* Initialization pci qemu test driver */
-
-#ifdef CONFIG_PCI_QEMU_TEST
- ret = pci_register_qemu_test_driver();
- if (ret < 0)
- {
- pcierr("pci_register_qemu_test_driver failed, ret=%d\n", ret);
- }
-#endif
-
- /* Initialization qemu edu driver */
-
-#ifdef CONFIG_PCI_QEMU_EDU
- ret = pci_register_qemu_edu_driver();
- if (ret < 0)
- {
- pcierr("pci_register_qemu_edu_driver failed, ret=%d\n", ret);
- }
-#endif
-
- /* Initialization rptun ivshmem driver */
-
-#ifdef CONFIG_RPTUN_IVSHMEM
- ret = pci_register_rptun_ivshmem_driver();
- if (ret < 0)
- {
- pcierr("pci_register_rptun_ivshmem_driver failed, ret=%d\n", ret);
- }
+#ifdef CONFIG_PCI_UIO_IVSHMEM
+int pci_register_uio_ivshmem_driver(void);
#endif
- UNUSED(ret);
- return ret;
-}
+#endif /* __DRIVERS_PCI_PCI_DRIVERS_H */
diff --git a/drivers/pci/pci_uio_ivshmem.c b/drivers/pci/pci_uio_ivshmem.c
new file mode 100644
index 0000000000..2fa855f3f5
--- /dev/null
+++ b/drivers/pci/pci_uio_ivshmem.c
@@ -0,0 +1,310 @@
+/****************************************************************************
+ * drivers/pci/pci_uio_ivshmem.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 <debug.h>
+#include <errno.h>
+#include <stdio.h>
+
+#include <nuttx/fs/fs.h>
+#include <nuttx/mm/map.h>
+#include <nuttx/pci/pci.h>
+
+#include "pci_drivers.h"
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+#define UIO_IVSHMEM_SHMEM_BAR 2
+
+/****************************************************************************
+ * Private Types
+ ****************************************************************************/
+
+struct uio_ivshmem_dev_s
+{
+ FAR void *shmem;
+ size_t shmem_size;
+ char name[32];
+};
+
+/****************************************************************************
+ * Private Function Prototypes
+ ****************************************************************************/
+
+static int uio_ivshmem_open(FAR struct file *filep);
+static int uio_ivshmem_close(FAR struct file *filep);
+static ssize_t uio_ivshmem_read(FAR struct file *filep, FAR char *buffer,
+ size_t buflen);
+static ssize_t uio_ivshmem_write(FAR struct file *filep,
+ FAR const char *buffer, size_t buflen);
+static int uio_ivshmem_unmap(FAR struct task_group_s *group,
+ FAR struct mm_map_entry_s *entry,
+ FAR void *start, size_t length);
+static int uio_ivshmem_mmap(FAR struct file *filep,
+ FAR struct mm_map_entry_s *map);
+
+static int uio_ivshmem_probe(FAR struct pci_device_s *dev);
+static void uio_ivshmem_remove(FAR struct pci_device_s *dev);
+
+/****************************************************************************
+ * Private Data
+ ****************************************************************************/
+
+static const struct file_operations g_uio_ivshmem_fops =
+{
+ uio_ivshmem_open, /* open */
+ uio_ivshmem_close, /* close */
+ uio_ivshmem_read, /* read */
+ uio_ivshmem_write, /* write */
+ NULL, /* seek */
+ NULL, /* ioctl */
+ uio_ivshmem_mmap, /* mmap */
+ NULL, /* truncate */
+ NULL /* poll */
+#ifndef CONFIG_DISABLE_PSEUDOFS_OPERATIONS
+ , NULL /* unlink */
+#endif
+};
+
+static const struct pci_device_id_s g_uio_ivshmem_ids[] =
+{
+ { PCI_DEVICE(0x1af4, 0x1110) },
+ { 0, }
+};
+
+static struct pci_driver_s g_uio_ivshmem_drv =
+{
+ g_uio_ivshmem_ids, /* PCI id_tables */
+ uio_ivshmem_probe, /* Probe function */
+ uio_ivshmem_remove, /* Remove function */
+};
+
+static int g_uio_ivshmem_idx = 0;
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: uio_ivshmem_open
+ ****************************************************************************/
+
+static int uio_ivshmem_open(FAR struct file *filep)
+{
+ UNUSED(filep);
+ return 0;
+}
+
+/****************************************************************************
+ * Name: uio_ivshmem_close
+ ****************************************************************************/
+
+static int uio_ivshmem_close(FAR struct file *filep)
+{
+ UNUSED(filep);
+ return 0;
+}
+
+/****************************************************************************
+ * Name: uio_ivshmem_read
+ ****************************************************************************/
+
+static ssize_t uio_ivshmem_read(FAR struct file *filep, FAR char *buffer,
+ size_t buflen)
+{
+ UNUSED(filep);
+ UNUSED(buffer);
+ return buflen;
+}
+
+/****************************************************************************
+ * Name: uio_ivshmem_write
+ ****************************************************************************/
+
+static ssize_t uio_ivshmem_write(FAR struct file *filep,
+ FAR const char *buffer, size_t buflen)
+{
+ UNUSED(filep);
+ UNUSED(buffer);
+ return buflen;
+}
+
+/****************************************************************************
+ * Name: uio_ivshmem_unmap
+ ****************************************************************************/
+
+static int uio_ivshmem_unmap(FAR struct task_group_s *group,
+ FAR struct mm_map_entry_s *entry,
+ FAR void *start, size_t length)
+{
+ off_t offset;
+ int ret;
+
+ offset = (uintptr_t)start - (uintptr_t)entry->vaddr;
+ if (offset + length < entry->length)
+ {
+ pcierr("ERROR: Cannot umap without unmapping to the end\n");
+ return -ENOSYS;
+ }
+
+ /* Okay.. the region is being unmapped to the end. Make sure the length
+ * indicates the unmap length.
+ */
+
+ length = entry->length - offset;
+ if (length < entry->length)
+ {
+ pcierr("ERROR: Cannot umap portion of the memory\n");
+ return -ENOSYS;
+ }
+
+ ret = mm_map_remove(get_group_mm(group), entry);
+ if (ret < 0)
+ {
+ pcierr("ERROR: mm_map_remove failed, ret=%d\n", ret);
+ return ret;
+ }
+
+ return ret;
+}
+
+/****************************************************************************
+ * Name: uio_ivshmem_mmap
+ ****************************************************************************/
+
+static int uio_ivshmem_mmap(FAR struct file *filep,
+ FAR struct mm_map_entry_s *map)
+{
+ FAR struct uio_ivshmem_dev_s *priv;
+
+ DEBUGASSERT(filep->f_inode != NULL && filep->f_inode->i_private != NULL);
+
+ /* Recover our private data from the struct file instance */
+
+ priv = filep->f_inode->i_private;
+
+ if (map->offset < 0 || map->offset >= priv->shmem_size ||
+ map->length == 0 || map->offset + map->length > priv->shmem_size)
+ {
+ return -EINVAL;
+ }
+
+ map->vaddr = (FAR char *)priv->shmem + map->offset;
+ map->priv.p = priv;
+ map->munmap = uio_ivshmem_unmap;
+
+ /* Not allow mapped memory overlap */
+
+ if (mm_map_find(get_current_mm(), map->vaddr, map->length) != NULL)
+ {
+ return -EINVAL;
+ }
+
+ return mm_map_add(get_current_mm(), map);
+}
+
+/****************************************************************************
+ * Name: uio_ivshmem_probe
+ ****************************************************************************/
+
+static int uio_ivshmem_probe(FAR struct pci_device_s *dev)
+{
+ FAR struct uio_ivshmem_dev_s *priv;
+ int ret;
+
+ priv = kmm_zalloc(sizeof(*priv));
+ if (priv == NULL)
+ {
+ return -ENOMEM;
+ }
+
+ /* Configure the ivshmem device and get share memory address */
+
+ ret = pci_enable_device(dev);
+ if (ret < 0)
+ {
+ pcierr("ERROR: Enable device failed, ret=%d\n", ret);
+ goto err_priv;
+ }
+
+ pci_set_master(dev);
+
+ priv->shmem = pci_map_bar(dev, UIO_IVSHMEM_SHMEM_BAR);
+ if (priv->shmem == NULL)
+ {
+ ret = -ENOTSUP;
+ pcierr("ERROR: Device not support share memory bar\n");
+ goto err_master;
+ }
+
+ priv->shmem_size = pci_resource_len(dev, UIO_IVSHMEM_SHMEM_BAR);
+
+ pciinfo("shmem addr=%p size=%zu\n", priv->shmem, priv->shmem_size);
+
+ snprintf(priv->name, sizeof(priv->name), "/dev/uio%d", g_uio_ivshmem_idx);
+ ret = register_driver(priv->name, &g_uio_ivshmem_fops, 0666, priv);
+ if (ret < 0)
+ {
+ pcierr("ERROR: Ivshmem register_driver failed, ret=%d\n", ret);
+ goto err_master;
+ }
+
+ g_uio_ivshmem_idx++;
+ return ret;
+
+err_master:
+ pci_clear_master(dev);
+ pci_disable_device(dev);
+err_priv:
+ kmm_free(priv);
+ return ret;
+}
+
+/****************************************************************************
+ * Name: uio_ivshmem_remove
+ ****************************************************************************/
+
+static void uio_ivshmem_remove(FAR struct pci_device_s *dev)
+{
+ FAR struct uio_ivshmem_dev_s *priv = dev->priv;
+
+ dev->priv = NULL;
+ unregister_driver(priv->name);
+ pci_clear_master(dev);
+ pci_disable_device(dev);
+ kmm_free(priv);
+}
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+int pci_register_uio_ivshmem_driver(void)
+{
+ return pci_register_driver(&g_uio_ivshmem_drv);
+}
+