pci: add option --create-uio-dev to run without hotplug
authorOlivier Matz <olivier.matz@6wind.com>
Tue, 28 Jan 2014 14:26:00 +0000 (15:26 +0100)
committerDavid Marchand <david.marchand@6wind.com>
Wed, 26 Feb 2014 10:07:28 +0000 (11:07 +0100)
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 <olivier.matz@6wind.com>
Acked-by: Thomas Monjalon <thomas.monjalon@6wind.com>
lib/librte_eal/linuxapp/eal/eal.c
lib/librte_eal/linuxapp/eal/eal_pci.c
lib/librte_eal/linuxapp/eal/include/eal_internal_cfg.h

index 08a96f1..db0e15c 100644 (file)
@@ -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:
index e6216c5..5fa466e 100644 (file)
@@ -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 */
index a274995..92e3065 100644 (file)
@@ -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;