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 at 6wind.com>
---
 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(-)

Hi Thomas,

Thanks for your comment, I moved the option help above.

diff --git a/lib/librte_eal/linuxapp/eal/eal.c 
b/lib/librte_eal/linuxapp/eal/eal.c
index bd20331..e402fee 100644
--- a/lib/librte_eal/linuxapp/eal/eal.c
+++ b/lib/librte_eal/linuxapp/eal/eal.c
@@ -94,6 +94,7 @@
 #define OPT_SOCKET_MEM  "socket-mem"
 #define OPT_USE_DEVICE  "use-device"
 #define OPT_SYSLOG      "syslog"
+#define OPT_CREATE_UIO_DEV "create-uio-dev"

 #define RTE_EAL_BLACKLIST_SIZE 0x100

@@ -352,6 +353,7 @@ eal_usage(const char *prgname)
               "               [NOTE: Cannot be used with -b option]\n"
               "  --"OPT_VMWARE_TSC_MAP": use VMware TSC map instead of "
                           "native RDTSC\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"
@@ -608,6 +610,7 @@ eal_parse_args(int argc, char **argv)
                {OPT_SOCKET_MEM, 1, 0, 0},
                {OPT_USE_DEVICE, 1, 0, 0},
                {OPT_SYSLOG, 1, NULL, 0},
+               {OPT_CREATE_UIO_DEV, 1, NULL, 0},
                {0, 0, 0, 0}
        };
        struct shared_driver *solib;
@@ -747,6 +750,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 1039777..af5a8b9 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 45ec058..649bd2b 100644
--- a/lib/librte_eal/linuxapp/eal/include/eal_internal_cfg.h
+++ b/lib/librte_eal/linuxapp/eal/include/eal_internal_cfg.h
@@ -68,6 +68,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;
-- 
1.8.4.rc3

Reply via email to