nic_uio: fix device binding at boot
authorBruce Richardson <bruce.richardson@intel.com>
Fri, 24 Mar 2017 14:30:11 +0000 (14:30 +0000)
committerThomas Monjalon <thomas.monjalon@6wind.com>
Tue, 4 Apr 2017 10:28:03 +0000 (12:28 +0200)
When loading nic_uio from /boot/loader.conf as specified in the Getting
Started Guide doc, the NIC devices were not bound at boot. Unloading the
nic_uio driver and reloading it would cause them to be bound, however.

The root cause appears to be the fact that when the module is loaded at
boot, the call to find the pci device when parsing the b:d:f parameter
fails to return the device. That means that later on when the device
is probed as part of a PCI scan, no action is taken as it's not recorded
as a device to be used.

We fix this by having the b:d:f string parsed again on probe if the
initial check to see if it's an already-known device fails. In my tests,
this causes the NIC devices to be successfully bound at boot time, as
well as leaving things working as before in the case the module is loaded
post-boot.

Fixes: 764bf26873b9 ("add FreeBSD support")
Cc: stable@dpdk.org
Signed-off-by: Bruce Richardson <bruce.richardson@intel.com>
lib/librte_eal/bsdapp/nic_uio/nic_uio.c

index 99a4975..4bd7545 100644 (file)
@@ -180,6 +180,10 @@ nic_uio_probe (device_t dev)
        unsigned int device = pci_get_slot(dev);
        unsigned int function = pci_get_function(dev);
 
+       char bdf_str[256];
+       char *token, *remaining;
+
+       /* First check if we found this on load */
        for (i = 0; i < num_detached; i++)
                if (bus == pci_get_bus(detached_devices[i]) &&
                    device == pci_get_slot(detached_devices[i]) &&
@@ -188,6 +192,45 @@ nic_uio_probe (device_t dev)
                        return BUS_PROBE_SPECIFIC;
                }
 
+       /* otherwise check if it's a new device and if it matches the BDF */
+       memset(bdf_str, 0, sizeof(bdf_str));
+       TUNABLE_STR_FETCH("hw.nic_uio.bdfs", bdf_str, sizeof(bdf_str));
+       remaining = bdf_str;
+       while (1) {
+               if (remaining == NULL || remaining[0] == '\0')
+                       break;
+               token = strsep(&remaining, ",:");
+               if (token == NULL)
+                       break;
+               bus = strtol(token, NULL, 10);
+               token = strsep(&remaining, ",:");
+               if (token == NULL)
+                       break;
+               device = strtol(token, NULL, 10);
+               token = strsep(&remaining, ",:");
+               if (token == NULL)
+                       break;
+               function = strtol(token, NULL, 10);
+
+               if (bus == pci_get_bus(dev) &&
+                               device == pci_get_slot(dev) &&
+                               function == pci_get_function(dev)) {
+
+                       if (num_detached < MAX_DETACHED_DEVICES) {
+                               printf("%s: probed dev=%p\n",
+                                              __func__, dev);
+                               detached_devices[num_detached++] = dev;
+                               device_set_desc(dev, "DPDK PCI Device");
+                               return BUS_PROBE_SPECIFIC;
+                       } else {
+                               printf("%s: reached MAX_DETACHED_DEVICES=%d. dev=%p won't be reattached\n",
+                                               __func__, MAX_DETACHED_DEVICES,
+                                               dev);
+                               break;
+                       }
+               }
+       }
+
        return ENXIO;
 }
 
@@ -248,6 +291,7 @@ nic_uio_load(void)
        memset(bdf_str, 0, sizeof(bdf_str));
        TUNABLE_STR_FETCH("hw.nic_uio.bdfs", bdf_str, sizeof(bdf_str));
        remaining = bdf_str;
+       printf("nic_uio: hw.nic_uio.bdfs = '%s'\n", bdf_str);
        /*
         * Users should specify PCI BDFs in the format "b:d:f,b:d:f,b:d:f".
         *  But the code below does not try differentiate between : and ,