[dpdk-dev] [ [PATCH v2] 09/13] igb_uio: ioport: map iopci region for armv7/v8
Santosh Shukla
sshukla at mvista.com
Mon Dec 14 14:00:28 CET 2015
Module maps iopci region by creating misc device file /dev/igb_ioport.
Applicable for non-x86 arch, tested for arm64/ThuderX platform.
Including three api to register/unregister ioport misc device
- igbuio_ioport_register
- igbuio_ioport_unregister
- igbuio_iomap
Signed-off-by: Santosh Shukla <sshukla at mvista.com>
Signed-off-by: Rizwan Ansari <ransari at mvista.com>
Signed-off-by: Rakesh Krishnamurthy <rakeshk at mvista.com>
---
lib/librte_eal/linuxapp/igb_uio/igb_uio.c | 8 +-
.../linuxapp/igb_uio/igbuio_ioport_misc.h | 133 ++++++++++++++++++++
2 files changed, 140 insertions(+), 1 deletion(-)
create mode 100644 lib/librte_eal/linuxapp/igb_uio/igbuio_ioport_misc.h
diff --git a/lib/librte_eal/linuxapp/igb_uio/igb_uio.c b/lib/librte_eal/linuxapp/igb_uio/igb_uio.c
index f5617d2..155bf39 100644
--- a/lib/librte_eal/linuxapp/igb_uio/igb_uio.c
+++ b/lib/librte_eal/linuxapp/igb_uio/igb_uio.c
@@ -39,6 +39,7 @@
#include <rte_pci_dev_features.h>
#include "compat.h"
+#include "igbuio_ioport_misc.h"
#ifdef RTE_PCI_CONFIG
#define PCI_SYS_FILE_BUF_SIZE 10
@@ -366,7 +367,7 @@ igbuio_pci_setup_ioport(struct pci_dev *dev, struct uio_info *info,
return -EINVAL;
info->port[n].name = name;
- info->port[n].start = addr;
+ info->port[n].start = igbuio_iomap(addr);
info->port[n].size = len;
info->port[n].porttype = UIO_PORT_X86;
@@ -615,6 +616,10 @@ igbuio_pci_init_module(void)
{
int ret;
+ ret = igbuio_ioport_register();
+ if (ret < 0)
+ return ret;
+
ret = igbuio_config_intr_mode(intr_mode);
if (ret < 0)
return ret;
@@ -625,6 +630,7 @@ igbuio_pci_init_module(void)
static void __exit
igbuio_pci_exit_module(void)
{
+ igbuio_ioport_unregister();
pci_unregister_driver(&igbuio_pci_driver);
}
diff --git a/lib/librte_eal/linuxapp/igb_uio/igbuio_ioport_misc.h b/lib/librte_eal/linuxapp/igb_uio/igbuio_ioport_misc.h
new file mode 100644
index 0000000..04e2c28
--- /dev/null
+++ b/lib/librte_eal/linuxapp/igb_uio/igbuio_ioport_misc.h
@@ -0,0 +1,133 @@
+/*-
+ * GPL LICENSE SUMMARY
+ *
+ * Copyright(c) 2015 Cavium Networks. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ * The full GNU General Public License is included in this distribution
+ * in the file called LICENSE.GPL.
+ *
+ * Contact Information:
+ * Cavium Networks
+ */
+
+#ifndef _IGBUIO_IOPORT_MISC_H_
+#define _IGBUIO_IOPORT_MISC_H_
+
+unsigned long igbuio_iomap(unsigned long addr);
+int igbuio_ioport_register(void);
+void igbuio_ioport_unregister(void);
+
+#if defined(RTE_ARCH_ARM) || defined(RTE_ARCH_ARM64)
+#ifdef CONFIG_HAS_IOPORT_MAP
+/*
+ * mmap driver to map x86-style PCI_IOBAR (i.e..cat /proc/ioport pci-bar-memory)
+ * from kernel-space virtual address to user-space virtual address. This module
+ * required for non-x86 archs example arm/arm64, as those archs donot do
+ * IO_MAP_IO types access, Infact supports memory-mapped-IO. That is because
+ * arm/arm64 doesn't support direct IO instruction, so the design approach is to
+ * map `cat /proc/ioport` PCI_IOBAR's kernel-space virtual-addr to user-space
+ * virtual-addr. Therefore the need for mmap-driver.
+ */
+#include <linux/fs.h> /* file_operations */
+#include <linux/miscdevice.h>
+#include <linux/mm.h> /* VM_IO */
+#include <linux/uaccess.h>
+#include <asm/page.h>
+#include <asm/io.h>
+#include <linux/sched.h>
+#include <linux/pid.h>
+
+void *__iomem mapped_io; /* ioport addr of `cat /proc/ioport` */
+
+static int igbuio_ioport_mmap(struct file *file, struct vm_area_struct *vma)
+{
+ struct page *npage;
+ int ret = 0;
+
+ vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
+ npage = vmalloc_to_page(mapped_io);
+ ret = remap_pfn_range(vma, vma->vm_start,
+ page_to_pfn(npage),
+ vma->vm_end - vma->vm_start,
+ vma->vm_page_prot);
+ if (ret) {
+ pr_info("Error: Failed to remap pfn=%lu error=%d\n",
+ page_to_pfn(npage), ret);
+ }
+ return 0;
+}
+
+static const struct file_operations igbuio_ioport_fops = {
+ .mmap = igbuio_ioport_mmap,
+};
+
+static struct miscdevice igbuio_ioport_dev = {
+ .minor = MISC_DYNAMIC_MINOR,
+ .name = "igb_ioport",
+ .fops = &igbuio_ioport_fops
+};
+
+unsigned long igbuio_iomap(unsigned long addr)
+{
+ mapped_io = ioport_map(addr, 0);
+ return (unsigned long)(uintptr_t)mapped_io;
+}
+
+int igbuio_ioport_register(void)
+{
+ int ret;
+ ret = misc_register(&igbuio_ioport_dev);
+ if (ret < 0) {
+ pr_info("Error: failed to register ioport map driver (%d)\n",
+ ret);
+ return ret;
+ }
+ return ret;
+}
+
+void igbuio_ioport_unregister(void)
+{
+ misc_deregister(&igbuio_ioport_dev);
+}
+
+#else /* !CONFIG_HAS_IOPORT_MAP */
+
+#error "CONFIG_HAS_IOPORT_MAP not supported for $RTE_ARCH"
+
+#endif /* CONFIG_HAS_IOPORT_MAP */
+
+#else /* !RTE_ARCH_ARM, !RTE_ARCH_ARM64 */
+
+unsigned long igbuio_iomap(unsigned long addr)
+{
+ /* non-arm case : simply return addr */
+ return addr;
+}
+
+int igbuio_ioport_register(void)
+{
+ /* non-arm case : do nothing */
+ return 0;
+}
+
+void igbuio_ioport_unregister(void)
+{
+ /* non-arm case : do nothing */
+ return;
+}
+
+#endif /* RTE_ARCH_ARM , RTE_ARCH_ARM64 */
+
+#endif /* _IGBUIO_IOPORT_MISC_H_ */
--
1.7.9.5
More information about the dev
mailing list