[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