[dpdk-dev] [PATCH 1/4] Amazon ENA UIO driver

Jan Medala jan at semihalf.com
Thu Jan 28 16:20:10 CET 2016


Amazon ENA device doesn't implement legacy interrupt which is
required by default UIO. This driver introduces all necessary
memory mappings in order to use ENA device.

Signed-off-by: Evgeny Schemeilin <evgenys at amazon.com>
Signed-off-by: Jan Medala <jan at semihalf.com>
Signed-off-by: Jakub Palider <jpa at semihalf.com>
---
 config/common_linuxapp                           |   5 +
 lib/librte_eal/common/include/rte_pci.h          |   1 +
 lib/librte_eal/common/include/rte_pci_dev_ids.h  |  16 ++
 lib/librte_eal/linuxapp/Makefile                 |   3 +
 lib/librte_eal/linuxapp/eal/eal_pci.c            |   4 +
 lib/librte_eal/linuxapp/ena_uio/Makefile         |  55 +++++
 lib/librte_eal/linuxapp/ena_uio/ena_uio_driver.c | 276 +++++++++++++++++++++++
 7 files changed, 360 insertions(+)
 create mode 100644 lib/librte_eal/linuxapp/ena_uio/Makefile
 create mode 100644 lib/librte_eal/linuxapp/ena_uio/ena_uio_driver.c

diff --git a/config/common_linuxapp b/config/common_linuxapp
index 74bc515..1777c4e 100644
--- a/config/common_linuxapp
+++ b/config/common_linuxapp
@@ -249,6 +249,11 @@ CONFIG_RTE_LIBRTE_CXGBE_DEBUG_TX=n
 CONFIG_RTE_LIBRTE_CXGBE_DEBUG_RX=n
 
 #
+# Compile burst-oriented Amazon ENA PMD driver
+#
+CONFIG_RTE_EAL_ENA_UIO=y
+
+#
 # Compile burst-oriented Cisco ENIC PMD driver
 #
 CONFIG_RTE_LIBRTE_ENIC_PMD=y
diff --git a/lib/librte_eal/common/include/rte_pci.h b/lib/librte_eal/common/include/rte_pci.h
index 334c12e..201a5a7 100644
--- a/lib/librte_eal/common/include/rte_pci.h
+++ b/lib/librte_eal/common/include/rte_pci.h
@@ -149,6 +149,7 @@ enum rte_kernel_driver {
 	RTE_KDRV_VFIO,
 	RTE_KDRV_UIO_GENERIC,
 	RTE_KDRV_NIC_UIO,
+	RTE_KDRV_ENA_UIO,
 	RTE_KDRV_NONE,
 };
 
diff --git a/lib/librte_eal/common/include/rte_pci_dev_ids.h b/lib/librte_eal/common/include/rte_pci_dev_ids.h
index d088191..0600e03 100644
--- a/lib/librte_eal/common/include/rte_pci_dev_ids.h
+++ b/lib/librte_eal/common/include/rte_pci_dev_ids.h
@@ -152,6 +152,15 @@
 #define RTE_PCI_DEV_ID_DECL_BNX2XVF(vend, dev)
 #endif
 
+#ifndef RTE_PCI_DEV_ID_DECL_ENA
+#define RTE_PCI_DEV_ID_DECL_ENA(vend, dev)
+#endif
+
+#ifndef PCI_VENDOR_ID_AMAZON
+/** Vendor ID used by Amazon devices */
+#define PCI_VENDOR_ID_AMAZON 0x1D0F
+#endif
+
 #ifndef PCI_VENDOR_ID_INTEL
 /** Vendor ID used by Intel devices */
 #define PCI_VENDOR_ID_INTEL 0x8086
@@ -598,6 +607,12 @@ RTE_PCI_DEV_ID_DECL_VMXNET3(PCI_VENDOR_ID_VMWARE, VMWARE_DEV_ID_VMXNET3)
 
 RTE_PCI_DEV_ID_DECL_FM10KVF(PCI_VENDOR_ID_INTEL, FM10K_DEV_ID_VF)
 
+/****************** Amazon devices ******************/
+
+#define PCI_DEVICE_ID_ENA_VF	0xEC20
+
+RTE_PCI_DEV_ID_DECL_ENA(PCI_VENDOR_ID_AMAZON, PCI_DEVICE_ID_ENA_VF)
+
 /****************** Cisco VIC devices ******************/
 
 #define PCI_DEVICE_ID_CISCO_VIC_ENET         0x0043  /* ethernet vnic */
@@ -656,6 +671,7 @@ RTE_PCI_DEV_ID_DECL_BNX2X(PCI_VENDOR_ID_BROADCOM, BNX2X_DEV_ID_57840_MF)
  */
 #undef RTE_PCI_DEV_ID_DECL_BNX2X
 #undef RTE_PCI_DEV_ID_DECL_BNX2XVF
+#undef RTE_PCI_DEV_ID_DECL_ENA
 #undef RTE_PCI_DEV_ID_DECL_EM
 #undef RTE_PCI_DEV_ID_DECL_IGB
 #undef RTE_PCI_DEV_ID_DECL_IGBVF
diff --git a/lib/librte_eal/linuxapp/Makefile b/lib/librte_eal/linuxapp/Makefile
index d9c5233..b293b1c 100644
--- a/lib/librte_eal/linuxapp/Makefile
+++ b/lib/librte_eal/linuxapp/Makefile
@@ -31,6 +31,9 @@
 
 include $(RTE_SDK)/mk/rte.vars.mk
 
+ifeq ($(CONFIG_RTE_EAL_ENA_UIO),y)
+DIRS-$(CONFIG_RTE_LIBRTE_EAL_LINUXAPP) += ena_uio
+endif
 ifeq ($(CONFIG_RTE_EAL_IGB_UIO),y)
 DIRS-$(CONFIG_RTE_LIBRTE_EAL_LINUXAPP) += igb_uio
 endif
diff --git a/lib/librte_eal/linuxapp/eal/eal_pci.c b/lib/librte_eal/linuxapp/eal/eal_pci.c
index bc5b5be..b05a564 100644
--- a/lib/librte_eal/linuxapp/eal/eal_pci.c
+++ b/lib/librte_eal/linuxapp/eal/eal_pci.c
@@ -137,6 +137,7 @@ pci_map_device(struct rte_pci_device *dev)
 #endif
 		break;
 	case RTE_KDRV_IGB_UIO:
+	case RTE_KDRV_ENA_UIO:
 	case RTE_KDRV_UIO_GENERIC:
 		/* map resources for devices that use uio */
 		ret = pci_uio_map_resource(dev);
@@ -161,6 +162,7 @@ pci_unmap_device(struct rte_pci_device *dev)
 		RTE_LOG(ERR, EAL, "Hotplug doesn't support vfio yet\n");
 		break;
 	case RTE_KDRV_IGB_UIO:
+	case RTE_KDRV_ENA_UIO:
 	case RTE_KDRV_UIO_GENERIC:
 		/* unmap resources for devices that use uio */
 		pci_uio_unmap_resource(dev);
@@ -355,6 +357,8 @@ pci_scan_one(const char *dirname, uint16_t domain, uint8_t bus,
 	if (!ret) {
 		if (!strcmp(driver, "vfio-pci"))
 			dev->kdrv = RTE_KDRV_VFIO;
+		else if (!strcmp(driver, "ena_uio"))
+			dev->kdrv = RTE_KDRV_ENA_UIO;
 		else if (!strcmp(driver, "igb_uio"))
 			dev->kdrv = RTE_KDRV_IGB_UIO;
 		else if (!strcmp(driver, "uio_pci_generic"))
diff --git a/lib/librte_eal/linuxapp/ena_uio/Makefile b/lib/librte_eal/linuxapp/ena_uio/Makefile
new file mode 100644
index 0000000..10c4dc6
--- /dev/null
+++ b/lib/librte_eal/linuxapp/ena_uio/Makefile
@@ -0,0 +1,55 @@
+#
+# BSD LICENSE
+#
+# Copyright (c) 2015-2016 Amazon.com, Inc. or its affiliates.
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in
+# the documentation and/or other materials provided with the
+# distribution.
+# * Neither the name of copyright holder nor the names of its
+# contributors may be used to endorse or promote products derived
+# from this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+
+include $(RTE_SDK)/mk/rte.vars.mk
+
+#
+# module name and path
+#
+MODULE = ena_uio
+MODULE_PATH = drivers/net/ena_uio
+
+#
+# CFLAGS
+#
+MODULE_CFLAGS += -I$(SRCDIR) --param max-inline-insns-single=100
+MODULE_CFLAGS += -I$(RTE_OUTPUT)/include
+MODULE_CFLAGS += -Winline -Wall -Werror
+MODULE_CFLAGS += -include $(RTE_OUTPUT)/include/rte_config.h
+
+#
+# all source are stored in SRCS-y
+#
+SRCS-y += ena_uio_driver.c
+
+include $(RTE_SDK)/mk/rte.module.mk
diff --git a/lib/librte_eal/linuxapp/ena_uio/ena_uio_driver.c b/lib/librte_eal/linuxapp/ena_uio/ena_uio_driver.c
new file mode 100644
index 0000000..8bf8a9e
--- /dev/null
+++ b/lib/librte_eal/linuxapp/ena_uio/ena_uio_driver.c
@@ -0,0 +1,276 @@
+/*-
+* BSD LICENSE
+*
+* Copyright (c) 2015-2016 Amazon.com, Inc. or its affiliates.
+* All rights reserved.
+*
+* Redistribution and use in source and binary forms, with or without
+* modification, are permitted provided that the following conditions
+* are met:
+*
+* * Redistributions of source code must retain the above copyright
+* notice, this list of conditions and the following disclaimer.
+* * Redistributions in binary form must reproduce the above copyright
+* notice, this list of conditions and the following disclaimer in
+* the documentation and/or other materials provided with the
+* distribution.
+* * Neither the name of copyright holder nor the names of its
+* contributors may be used to endorse or promote products derived
+* from this software without specific prior written permission.
+*
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#include <linux/device.h>
+#include <linux/module.h>
+#include <linux/pci.h>
+#include <linux/uio_driver.h>
+#include <linux/io.h>
+#include <linux/msi.h>
+#include <linux/version.h>
+#include <linux/slab.h>
+
+#include "rte_pci_dev_ids.h"
+
+#define DRV_MODULE_NAME         "ena_uio"
+#define DRV_MODULE_VERSION      "1.0"
+#define DRV_MODULE_RELDATE      "January 14, 2016"
+
+/**
+	Defines from uio_driver.h
+*/
+
+/* defines for uio_info->irq */
+#define UIO_IRQ_CUSTOM  -1
+#define UIO_IRQ_NONE     0
+
+
+/* defines for uio_port->porttype */
+#define UIO_PORT_NONE   0
+#define UIO_PORT_X86    1
+#define UIO_PORT_GPIO   2
+#define UIO_PORT_OTHER  3
+
+/* defines for muio_mem->memtype */
+#define UIO_MEM_NONE           0
+#define UIO_MEM_PHYS           1
+#define UIO_MEM_LOGICAL        2
+#define UIO_MEM_VIRTUAL        3
+#define UIO_MEM_PHYS_CACHEABLE 4
+#define UIO_MEM_PHYS_WC        5
+
+#define UIO_MMAP_PHYSICAL_CACHE 0x1
+#define UIO_MMAP_PHYSICAL_WC    0x2
+
+
+MODULE_AUTHOR("Alex Matushevsky <alex at annapurnaLabs.com>");
+MODULE_DESCRIPTION("UIO driver for Amazon ENA PCI cards");
+MODULE_LICENSE("GPL");
+MODULE_VERSION(DRV_MODULE_VERSION);
+
+
+/* PCI BARs */
+#define ENA_REG_BAR		0
+
+
+typedef enum {
+	ENA = 0
+} board_t;
+
+static DEFINE_PCI_DEVICE_TABLE(ena_uio_pci_tbl) = {
+	{ PCI_VENDOR_ID_AMAZON, PCI_DEVICE_ID_ENA_VF,
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, ENA},
+	{ 0, }
+};
+
+MODULE_DEVICE_TABLE(pci, ena_uio_pci_tbl);
+
+
+/**
+ * A structure describing the private information for a uio device.
+ */
+struct rte_uio_pci_dev {
+	struct uio_info info;
+	struct pci_dev *pdev;
+	spinlock_t lock; /* spinlock for accessing PCI config space or msix data in multi tasks/isr */
+};
+
+
+static int
+ena_uio_pci_irqcontrol(struct uio_info *info, s32 irq_state)
+{
+	return -1;
+}
+
+static irqreturn_t
+ena_uio_pci_irqhandler(int irq, struct uio_info *info)
+{
+	return IRQ_NONE;
+}
+
+static int
+ena_uio_pci_setup_iomem(struct pci_dev *dev, struct uio_info *info,
+		       int n, int pci_bar, const char *name)
+{
+	unsigned long addr, len;
+	void *internal_addr;
+
+	addr = pci_resource_start(dev, pci_bar);
+	len = pci_resource_len(dev, pci_bar);
+
+	printk(KERN_INFO "addr len %lu f %lu\n", addr, len);
+	if (addr == 0 || len == 0)
+		return -1;
+
+	internal_addr = ioremap(addr, len);
+
+	printk(KERN_INFO "internal addr %p for %d len %lu \n", internal_addr, n, len);
+	if (internal_addr == NULL) {
+
+		return -1;
+	}
+	info->mem[n].name = name;
+	info->mem[n].addr = addr;
+	info->mem[n].internal_addr = internal_addr;
+	info->mem[n].size = len;
+	info->mem[n].memtype = UIO_MEM_PHYS;
+
+	return 0;
+}
+
+/* Unmap previously ioremap'd resources */
+static void
+ena_uio_pci_release_iomem(struct uio_info *info)
+{
+	int i;
+	for (i = 0; i < MAX_UIO_MAPS; i++) {
+		if (info->mem[i].internal_addr)
+			iounmap(info->mem[i].internal_addr);
+	}
+}
+
+static int
+ena_uio_pci_probe(struct pci_dev *dev, const struct pci_device_id *id)
+{
+	struct rte_uio_pci_dev *udev;
+
+	udev = kzalloc(sizeof(struct rte_uio_pci_dev), GFP_KERNEL);
+	if (!udev)
+		return -ENOMEM;
+
+	/*
+	 * enable device: ask low-level code to enable I/O and
+	 * memory
+	 */
+	if (pci_enable_device(dev)) {
+		printk(KERN_ERR "Cannot enable PCI device\n");
+		goto fail_free;
+	}
+
+	if (pci_set_dma_mask(dev, DMA_BIT_MASK(40))) {
+		printk(KERN_ERR "Cannot set DMA mask\n");
+		goto fail_disable;
+	}
+
+	if (pci_set_consistent_dma_mask(dev, DMA_BIT_MASK(40))) {
+		printk(KERN_ERR "Cannot set DMA mask\n");
+		goto fail_disable;
+	}
+
+	/*
+	 * reserve device's PCI memory regions for use by this
+	 * module
+	 */
+	if (pci_request_regions(dev, "ena_uio")) {
+		printk(KERN_ERR "Cannot request regions\n");
+		goto fail_disable;
+	}
+
+	/* enable bus mastering on the device */
+	pci_set_master(dev);
+
+	/* remap IO memory */
+	if (ena_uio_pci_setup_iomem(dev, &udev->info, 0, ENA_REG_BAR, "bar0"))
+		goto fail_release_iomem;
+
+	/* fill uio infos */
+	udev->info.name = "ENA UIO";
+	udev->info.version = "1.0";
+	udev->info.handler = ena_uio_pci_irqhandler;
+	udev->info.irqcontrol = ena_uio_pci_irqcontrol;
+	udev->info.priv = udev;
+	udev->pdev = dev;
+	spin_lock_init(&udev->lock);
+
+	/* irq is not supported */
+	udev->info.irq_flags = 0;
+	udev->info.irq = -1;
+
+	pci_set_drvdata(dev, udev);
+
+	/* register uio driver */
+	if (uio_register_device(&dev->dev, &udev->info))
+		goto fail_release_iomem;
+
+	return 0;
+
+fail_release_iomem:
+	ena_uio_pci_release_iomem(&udev->info);
+
+	pci_release_regions(dev);
+fail_disable:
+	pci_disable_device(dev);
+fail_free:
+	kfree(udev);
+
+	return -ENODEV;
+}
+
+
+static void
+ena_uio_pci_remove(struct pci_dev *dev)
+{
+	struct uio_info *info = pci_get_drvdata(dev);
+
+	if (info->priv == NULL) {
+		return;
+	}
+
+	uio_unregister_device(info);
+	ena_uio_pci_release_iomem(info);
+
+	pci_release_regions(dev);
+	pci_disable_device(dev);
+	pci_set_drvdata(dev, NULL);
+	kfree(info);
+}
+
+static struct pci_driver ena_uio_pci_driver = {
+        .name           = DRV_MODULE_NAME,
+        .id_table       = ena_uio_pci_tbl,
+        .probe          = ena_uio_pci_probe,
+        .remove         = ena_uio_pci_remove,
+};
+
+static int __init ena_uio_init(void)
+{
+	return pci_register_driver(&ena_uio_pci_driver);
+}
+
+static void __exit ena_uio_cleanup(void)
+{
+	pci_unregister_driver(&ena_uio_pci_driver);
+}
+
+module_init(ena_uio_init);
+module_exit(ena_uio_cleanup);
-- 
1.9.1



More information about the dev mailing list