[dpdk-dev] [PATCH 2/4] [PATCH 2/4] eal_pci: Add interrupt mode to rte_pci_device and parsing to eal_pci

Alan Carew alan.carew at intel.com
Thu Jun 5 16:39:17 CEST 2014


This patch adds a shared enum between user and kernel space to rte_pci_device.
The value of intr_mode is parsed by eal_pci during pci_uio_map_resource

Signed-off-by: Alan Carew <alan.carew at intel.com>
---
 lib/librte_eal/common/Makefile          |    1 +
 lib/librte_eal/common/include/rte_pci.h |    2 +
 lib/librte_eal/linuxapp/eal/eal_pci.c   |   78 +++++++++++++++++++++++++++++++
 3 files changed, 81 insertions(+), 0 deletions(-)

diff --git a/lib/librte_eal/common/Makefile b/lib/librte_eal/common/Makefile
index 0016fc5..52d46f3 100644
--- a/lib/librte_eal/common/Makefile
+++ b/lib/librte_eal/common/Makefile
@@ -35,6 +35,7 @@ INC := rte_atomic.h rte_branch_prediction.h rte_byteorder.h rte_common.h
 INC += rte_cycles.h rte_debug.h rte_eal.h rte_errno.h rte_launch.h rte_lcore.h
 INC += rte_log.h rte_memcpy.h rte_memory.h rte_memzone.h rte_pci.h
 INC += rte_pci_dev_ids.h rte_per_lcore.h rte_prefetch.h rte_random.h
+INC += rte_pci_dev_feature_defs.h rte_pci_dev_features.h
 INC += rte_rwlock.h rte_spinlock.h rte_tailq.h rte_interrupts.h rte_alarm.h
 INC += rte_string_fns.h rte_cpuflags.h rte_version.h rte_tailq_elem.h
 INC += rte_eal_memconfig.h rte_malloc_heap.h
diff --git a/lib/librte_eal/common/include/rte_pci.h b/lib/librte_eal/common/include/rte_pci.h
index c793773..5883cd9 100644
--- a/lib/librte_eal/common/include/rte_pci.h
+++ b/lib/librte_eal/common/include/rte_pci.h
@@ -81,6 +81,7 @@ extern "C" {
 #include <stdint.h>
 #include <inttypes.h>
 #include <rte_interrupts.h>
+#include <rte_pci_dev_feature_defs.h>
 
 TAILQ_HEAD(pci_device_list, rte_pci_device); /**< PCI devices in D-linked Q. */
 TAILQ_HEAD(pci_driver_list, rte_pci_driver); /**< PCI drivers in D-linked Q. */
@@ -150,6 +151,7 @@ struct rte_pci_device {
 	const struct rte_pci_driver *driver;    /**< Associated driver */
 	uint16_t max_vfs;                       /**< sriov enable if not zero */
 	int numa_node;                          /**< NUMA node connection */
+	enum igbuio_intr_mode intr_mode;        /**< Interrupt mode */
 	struct rte_devargs *devargs;            /**< Device user arguments */
 };
 
diff --git a/lib/librte_eal/linuxapp/eal/eal_pci.c b/lib/librte_eal/linuxapp/eal/eal_pci.c
index ac2c1fe..7dba446 100644
--- a/lib/librte_eal/linuxapp/eal/eal_pci.c
+++ b/lib/librte_eal/linuxapp/eal/eal_pci.c
@@ -67,6 +67,7 @@
 #include <rte_devargs.h>
 
 #include "rte_pci_dev_ids.h"
+#include "rte_pci_dev_feature_defs.h"
 #include "eal_filesystem.h"
 #include "eal_private.h"
 
@@ -89,6 +90,17 @@ struct uio_map {
 	uint64_t phaddr;
 };
 
+struct rte_pci_dev_intr_mode {
+	enum igbuio_intr_mode mode;
+	const char *name;
+};
+
+/* Table of interrupt modes */
+const struct rte_pci_dev_intr_mode interrupt_modes[] = {
+#define RTE_PCI_DEV_INTR_MODE(id, mode_name) {INTR_MODE(id, mode_name)},
+#include <rte_pci_dev_features.h>
+};
+
 /*
  * For multi-process we need to reproduce all PCI mappings in secondary
  * processes, so save them in a tailq.
@@ -106,6 +118,7 @@ TAILQ_HEAD(uio_res_list, uio_resource);
 
 static struct uio_res_list *uio_res_list = NULL;
 static int pci_parse_sysfs_value(const char *filename, uint64_t *val);
+static int pci_parse_sysfs_intr_mode(const char *filename, struct rte_pci_device *dev);
 
 /* unbind kernel driver for this device */
 static int
@@ -400,6 +413,7 @@ pci_uio_map_resource(struct rte_pci_device *dev)
 	int i, j;
 	char dirname[PATH_MAX];
 	char devname[PATH_MAX]; /* contains the /dev/uioX */
+    char filename[PATH_MAX];
 	void *mapaddr;
 	int uio_num;
 	uint64_t phaddr;
@@ -435,6 +449,18 @@ pci_uio_map_resource(struct rte_pci_device *dev)
 	}
 	dev->intr_handle.type = RTE_INTR_HANDLE_UIO;
 
+	rte_snprintf(filename, sizeof(filename),
+	         	SYSFS_PCI_DEVICES "/" PCI_PRI_FMT
+	         	"/"RTE_PCI_DEV_FEATURE_INTR_MODE,
+	         	loc->domain, loc->bus, loc->devid, loc->function);
+
+    /* Get the kernel configured interrupt mode */
+	if (pci_parse_sysfs_intr_mode(filename, dev) < 0) {
+		RTE_LOG(ERR, EAL, "%s(): cannot determine interrupt_mode\n",
+				__func__);
+		return -1;
+	}
+
 	/* allocate the mapping details for secondary processes*/
 	if ((uio_res = rte_zmalloc("UIO_RES", sizeof (*uio_res), 0)) == NULL) {
 		RTE_LOG(ERR, EAL,
@@ -591,6 +617,58 @@ pci_parse_sysfs_value(const char *filename, uint64_t *val)
         return 0;
 }
 
+/* 
+ * Parse a sysfs file containing a string
+ */ 
+static int
+pci_parse_sysfs_string(const char *filename, char *result_str, int max_len)
+{
+	FILE *f;
+	size_t len;
+
+	f = fopen(filename, "r");
+	if (f == NULL) {
+		RTE_LOG(ERR, EAL, "%s(): cannot open sysfs value %s\n",
+				__func__, filename);
+		return -1;
+	}
+	if (fgets(result_str, max_len, f) == NULL) {
+		RTE_LOG(ERR, EAL, "%s(): cannot read sysfs value %s\n",
+				__func__, filename);
+		fclose(f);
+		return -1;
+	}
+	len = strnlen(result_str, max_len) -1;
+	if (result_str[len] == '\n')
+		result_str[len] = '\0';
+
+	fclose(f);
+	return 0;
+}
+
+/*
+ * Determine the kernel configured interrupt mode
+ */
+static int
+pci_parse_sysfs_intr_mode(const char *filename, struct rte_pci_device *dev)
+{
+	char intr_mode[INTR_NAME_LEN];
+	unsigned int i, num_intr_modes = RTE_DIM(interrupt_modes);
+
+	if (pci_parse_sysfs_string(filename, intr_mode, RTE_DIM(intr_mode)) < 0) {
+		RTE_LOG(ERR, EAL, "%s(): cannot parse interrupt_mode\n",
+			__func__);
+		return -1;
+	}
+
+	for (i = 0; i < num_intr_modes; i++)
+		if (!strncmp(intr_mode, interrupt_modes[i].name, INTR_NAME_LEN)) {
+			dev->intr_mode = interrupt_modes[i].mode;
+			return 0;
+		}
+	return -1;
+}
+
 /* Compare two PCI device addresses. */
 static int
 pci_addr_comparison(struct rte_pci_addr *addr, struct rte_pci_addr *addr2)
-- 
1.7.0.7



More information about the dev mailing list