From f7f97c16048e0b2f9c766bf33ad994c55e02f8a2 Mon Sep 17 00:00:00 2001 From: Olivier Matz Date: Tue, 28 Jan 2014 15:26:00 +0100 Subject: [PATCH] pci: add option --create-uio-dev to run without hotplug When the user specifies --create-uio-dev in dpdk eal start options, the DPDK will create the /dev/uioX instead of waiting that a program does it (which is usually hotplug). This option is useful in embedded environments where there is no hotplug to do the work. Signed-off-by: Olivier Matz Acked-by: Thomas Monjalon --- lib/librte_eal/linuxapp/eal/eal.c | 6 +++ lib/librte_eal/linuxapp/eal/eal_pci.c | 47 ++++++++++++++++++- .../linuxapp/eal/include/eal_internal_cfg.h | 1 + 3 files changed, 53 insertions(+), 1 deletion(-) diff --git a/lib/librte_eal/linuxapp/eal/eal.c b/lib/librte_eal/linuxapp/eal/eal.c index 08a96f126e..db0e15cf98 100644 --- a/lib/librte_eal/linuxapp/eal/eal.c +++ b/lib/librte_eal/linuxapp/eal/eal.c @@ -94,6 +94,7 @@ #define OPT_SYSLOG "syslog" #define OPT_BASE_VIRTADDR "base-virtaddr" #define OPT_XEN_DOM0 "xen-dom0" +#define OPT_CREATE_UIO_DEV "create-uio-dev" #define RTE_EAL_BLACKLIST_SIZE 0x100 @@ -355,6 +356,7 @@ eal_usage(const char *prgname) " --"OPT_VMWARE_TSC_MAP": use VMware TSC map instead of " "native RDTSC\n" " --"OPT_BASE_VIRTADDR": specify base virtual address\n" + " --"OPT_CREATE_UIO_DEV": create /dev/uioX (usually done by hotplug)\n" "\nEAL options for DEBUG use only:\n" " --"OPT_NO_HUGE" : use malloc instead of hugetlbfs\n" " --"OPT_NO_PCI" : disable pci\n" @@ -638,6 +640,7 @@ eal_parse_args(int argc, char **argv) {OPT_SYSLOG, 1, NULL, 0}, {OPT_BASE_VIRTADDR, 1, 0, 0}, {OPT_XEN_DOM0, 0, 0, 0}, + {OPT_CREATE_UIO_DEV, 1, NULL, 0}, {0, 0, 0, 0} }; struct shared_driver *solib; @@ -797,6 +800,9 @@ eal_parse_args(int argc, char **argv) return -1; } } + else if (!strcmp(lgopts[option_index].name, OPT_CREATE_UIO_DEV)) { + internal_config.create_uio_dev = 1; + } break; default: diff --git a/lib/librte_eal/linuxapp/eal/eal_pci.c b/lib/librte_eal/linuxapp/eal/eal_pci.c index e6216c5eee..5fa466ef88 100644 --- a/lib/librte_eal/linuxapp/eal/eal_pci.c +++ b/lib/librte_eal/linuxapp/eal/eal_pci.c @@ -460,6 +460,47 @@ pci_uio_map_secondary(struct rte_pci_device *dev) return -1; } +static int pci_mknod_uio_dev(const char *sysfs_uio_path, unsigned uio_num) +{ + FILE *f; + char filename[PATH_MAX]; + int ret; + unsigned major, minor; + dev_t dev; + + /* get the name of the sysfs file that contains the major and minor + * of the uio device and read its content */ + rte_snprintf(filename, sizeof(filename), "%s/dev", sysfs_uio_path); + + f = fopen(filename, "r"); + if (f == NULL) { + RTE_LOG(ERR, EAL, "%s(): cannot open sysfs to get major:minor\n", + __func__); + return -1; + } + + ret = fscanf(f, "%d:%d", &major, &minor); + if (ret != 2) { + RTE_LOG(ERR, EAL, "%s(): cannot parse sysfs to get major:minor\n", + __func__); + fclose(f); + return -1; + } + fclose(f); + + /* create the char device "mknod /dev/uioX c major minor" */ + rte_snprintf(filename, sizeof(filename), "/dev/uio%u", uio_num); + dev = makedev(major, minor); + ret = mknod(filename, S_IFCHR | S_IRUSR | S_IWUSR, dev); + if (f == NULL) { + RTE_LOG(ERR, EAL, "%s(): mknod() failed %s\n", + __func__, strerror(errno)); + return -1; + } + + return ret; +} + /* * Return the uioX char device used for a pci device. On success, return * the UIO number and fill dstbuf string with the path of the device in @@ -529,7 +570,11 @@ static int pci_get_uio_dev(struct rte_pci_device *dev, char *dstbuf, if (e == NULL) return -1; - return 0; + /* create uio device if we've been asked to */ + if (internal_config.create_uio_dev && pci_mknod_uio_dev(dstbuf, uio_num) < 0) + RTE_LOG(WARNING, EAL, "Cannot create /dev/uio%u\n", uio_num); + + return uio_num; } /* map the PCI resource of a PCI device in virtual memory */ diff --git a/lib/librte_eal/linuxapp/eal/include/eal_internal_cfg.h b/lib/librte_eal/linuxapp/eal/include/eal_internal_cfg.h index a274995202..92e3065c7f 100644 --- a/lib/librte_eal/linuxapp/eal/include/eal_internal_cfg.h +++ b/lib/librte_eal/linuxapp/eal/include/eal_internal_cfg.h @@ -69,6 +69,7 @@ struct internal_config { volatile unsigned vmware_tsc_map; /**< true to use VMware TSC mapping * instead of native TSC */ volatile unsigned no_shconf; /**< true if there is no shared config */ + volatile unsigned create_uio_dev; /**< true to create /dev/uioX devices */ volatile enum rte_proc_type_t process_type; /**< multi-process proc type */ /** true to try allocating memory on specific sockets */ volatile unsigned force_sockets; -- 2.20.1