linux-cp: populate mapping vif-sw_if_index only for default-ns
[vpp.git] / src / vlib / linux / pci.c
index 1e5ab67..29ca3d9 100644 (file)
@@ -38,6 +38,8 @@
  */
 
 #include <vppinfra/linux/sysfs.h>
+#include <vppinfra/bitmap.h>
+#include <vppinfra/unix.h>
 
 #include <vlib/vlib.h>
 #include <vlib/pci/pci.h>
 #include <linux/ethtool.h>
 #include <linux/sockios.h>
 #include <linux/vfio.h>
+#include <limits.h>
 #include <sys/eventfd.h>
 
+#define SYSFS_DEVICES_PCI "/sys/devices/pci"
 static const char *sysfs_pci_dev_path = "/sys/bus/pci/devices";
 static const char *sysfs_pci_drv_path = "/sys/bus/pci/drivers";
 static char *sysfs_mod_vfio_noiommu =
   "/sys/module/vfio/parameters/enable_unsafe_noiommu_mode";
 
-#define pci_log_debug(vm, dev, f, ...) \
-  vlib_log(VLIB_LOG_LEVEL_DEBUG, pci_main.log_default, "%U: " f, \
-           format_vlib_pci_addr, vlib_pci_get_addr(vm, dev->handle), ## __VA_ARGS__)
-#define pci_log_err(vm, dev, f, ...) \
-  vlib_log(VLIB_LOG_LEVEL_ERR, pci_main.log_default, "%U: " f, \
-           format_vlib_pci_addr, vlib_pci_get_addr(vm, dev->handle), ## __VA_ARGS__)
+VLIB_REGISTER_LOG_CLASS (pci_log, static) = {
+  .class_name = "pci",
+  .subclass_name = "linux",
+};
+
+#define log_debug(p, f, ...)                                                  \
+  vlib_log (VLIB_LOG_LEVEL_DEBUG, pci_log.class, "%U: " f,                    \
+           format_vlib_pci_log, p->handle, ##__VA_ARGS__)
+#define log_err(p, f, ...)                                                    \
+  vlib_log (VLIB_LOG_LEVEL_ERR, pci_log.class, "%U: " f, format_vlib_pci_log, \
+           p->handle, ##__VA_ARGS__)
 
 typedef struct
 {
@@ -232,32 +241,14 @@ vlib_pci_get_device_info (vlib_main_t * vm, vlib_pci_addr_t * addr,
 
   /* You can only read more that 64 bytes of config space as root; so we try to
      read the full space but fall back to just the first 64 bytes. */
-  if (read (fd, &di->config_data, sizeof (di->config_data)) <
-      sizeof (di->config0))
+  if (read (fd, &di->config, sizeof (di->config)) <
+      sizeof (vlib_pci_config_hdr_t))
     {
       err = clib_error_return_unix (0, "read `%s'", f);
       close (fd);
       goto error;
     }
 
-  {
-    static pci_config_header_t all_ones;
-    if (all_ones.vendor_id == 0)
-      clib_memset (&all_ones, ~0, sizeof (all_ones));
-
-    if (!memcmp (&di->config0.header, &all_ones, sizeof (all_ones)))
-      {
-       err = clib_error_return (0, "invalid PCI config for `%s'", f);
-       close (fd);
-       goto error;
-      }
-  }
-
-  if (di->config0.header.header_type == 0)
-    pci_config_type0_little_to_host (&di->config0);
-  else
-    pci_config_type1_little_to_host (&di->config1);
-
   di->numa_node = -1;
   vec_reset_length (f);
   f = format (f, "%v/numa_node%c", dev_dir_name, 0);
@@ -269,11 +260,7 @@ vlib_pci_get_device_info (vlib_main_t * vm, vlib_pci_addr_t * addr,
     }
   if (di->numa_node == -1)
     {
-      /* if '/sys/bus/pci/devices/<device id>/numa_node' returns -1 and
-         it is a SMP system, set numa_node to 0. */
-      if ((err = clib_sysfs_read ("/sys/devices/system/node/online", "%U",
-                                 unformat_bitmap_list, &bmp)))
-       clib_error_free (err);
+      bmp = os_get_online_cpu_node_bitmap ();
       if (clib_bitmap_count_set_bits (bmp) == 1)
        di->numa_node = 0;
     }
@@ -300,15 +287,19 @@ vlib_pci_get_device_info (vlib_main_t * vm, vlib_pci_addr_t * addr,
   di->device_id = tmp;
 
   vec_reset_length (f);
-  f = format (f, "%v/driver%c", dev_dir_name, 0);
-  di->driver_name = clib_sysfs_link_to_name ((char *) f);
+  f = format (f, "%v/revision%c", dev_dir_name, 0);
+  err = clib_sysfs_read ((char *) f, "0x%x", &tmp);
+  if (err)
+    goto error;
+  di->revision = tmp;
+
+  di->driver_name =
+    clib_file_get_resolved_basename ("%v/driver", dev_dir_name);
   if (!di->driver_name)
     di->driver_name = format (0, "<NONE>%c", 0);
 
   di->iommu_group = -1;
-  vec_reset_length (f);
-  f = format (f, "%v/iommu_group%c", dev_dir_name, 0);
-  tmpstr = clib_sysfs_link_to_name ((char *) f);
+  tmpstr = clib_file_get_resolved_basename ("%v/iommu_group", dev_dir_name);
   if (tmpstr)
     {
       di->iommu_group = atoi ((char *) tmpstr);
@@ -347,7 +338,7 @@ vlib_pci_get_device_info (vlib_main_t * vm, vlib_pci_addr_t * addr,
            break;
 
          len = (tag[2] << 8) | tag[1];
-         vec_alloc (data, len);
+         vec_validate (data, len - 1);
 
          if (read (fd, data, len) != len)
            {
@@ -383,6 +374,64 @@ done:
   return di;
 }
 
+clib_error_t *__attribute__ ((weak))
+vlib_pci_get_device_root_bus (vlib_pci_addr_t *addr, vlib_pci_addr_t *root_bus)
+{
+  u8 *rel_path = 0, *abs_path = 0, *link_path = 0;
+  unformat_input_t input;
+  int fd = open (sysfs_pci_dev_path, O_RDONLY);
+  ssize_t size = 0;
+  u32 domain = 0, bus;
+  clib_error_t *err = NULL;
+
+  if (fd < 0)
+    return clib_error_return_unix (0, "failed to open %s", sysfs_pci_dev_path);
+
+  vec_alloc (rel_path, PATH_MAX);
+  vec_alloc (abs_path, PATH_MAX);
+
+  link_path =
+    format (0, "%s/%U", sysfs_pci_dev_path, format_vlib_pci_addr, addr);
+  size = readlinkat (fd, (char *) link_path, (char *) rel_path, PATH_MAX);
+  if (size < 0)
+    {
+      err = clib_error_return_unix (0, "failed to read %s", rel_path);
+      goto done;
+    }
+
+  rel_path[size] = '\0';
+  vec_free (link_path);
+
+  link_path = format (0, "%s/%s", sysfs_pci_dev_path, rel_path);
+  if (!realpath ((char *) link_path, (char *) abs_path))
+    {
+      err = clib_error_return_unix (0, "failed to resolve %s", link_path);
+      goto done;
+    }
+
+  unformat_init_string (&input, (char *) abs_path,
+                       clib_strnlen ((char *) abs_path, PATH_MAX));
+
+  if (!unformat (&input, SYSFS_DEVICES_PCI "%x:%x/%s", &domain, &bus,
+                link_path))
+    {
+      err = clib_error_return (0, "unknown input '%U'", format_unformat_error,
+                              input);
+      goto done;
+    }
+
+  root_bus->domain = domain;
+  root_bus->bus = bus;
+
+done:
+  vec_free (abs_path);
+  vec_free (link_path);
+  vec_free (rel_path);
+  close (fd);
+
+  return err;
+}
+
 static int
 directory_exists (char *path)
 {
@@ -394,8 +443,8 @@ directory_exists (char *path)
 }
 
 clib_error_t *
-vlib_pci_bind_to_uio (vlib_main_t * vm, vlib_pci_addr_t * addr,
-                     char *uio_drv_name)
+vlib_pci_bind_to_uio (vlib_main_t *vm, vlib_pci_addr_t *addr,
+                     char *uio_drv_name, int force)
 {
   clib_error_t *error = 0;
   u8 *s = 0, *driver_name = 0;
@@ -427,7 +476,7 @@ vlib_pci_bind_to_uio (vlib_main_t * vm, vlib_pci_addr_t * addr,
                                         "is bound to IOMMU group and "
                                         "vfio-pci driver is not loaded",
                                         format_vlib_pci_addr, addr);
-             goto done;
+             goto err0;
            }
          else
            uio_drv_name = "vfio-pci";
@@ -448,92 +497,94 @@ vlib_pci_bind_to_uio (vlib_main_t * vm, vlib_pci_addr_t * addr,
              error = clib_error_return (0, "Skipping PCI device %U: missing "
                                         "kernel VFIO or UIO driver",
                                         format_vlib_pci_addr, addr);
-             goto done;
+             goto err0;
            }
          clib_error_free (error);
        }
     }
 
-  s = format (s, "%v/driver%c", dev_dir_name, 0);
-  driver_name = clib_sysfs_link_to_name ((char *) s);
-  vec_reset_length (s);
+  driver_name = clib_file_get_resolved_basename ("%v/driver", dev_dir_name);
 
   if (driver_name &&
       ((strcmp ("vfio-pci", (char *) driver_name) == 0) ||
        (strcmp ("uio_pci_generic", (char *) driver_name) == 0) ||
        (strcmp ("igb_uio", (char *) driver_name) == 0)))
-    goto done;
-
-  /* walk trough all linux interfaces and if interface belonging to
-     this device is founf check if interface is admin up  */
-  dir = opendir ("/sys/class/net");
-  s = format (s, "%U%c", format_vlib_pci_addr, addr, 0);
+    goto err0;
 
-  if (!dir)
+  if (!force)
     {
-      error = clib_error_return (0, "Skipping PCI device %U: failed to "
-                                "read /sys/class/net",
-                                format_vlib_pci_addr, addr);
-      goto done;
-    }
+      /* walk trough all linux interfaces and if interface belonging to
+        this device is found check if interface is admin up  */
+      dir = opendir ("/sys/class/net");
+      s = format (s, "%U%c", format_vlib_pci_addr, addr, 0);
 
-  fd = socket (PF_INET, SOCK_DGRAM, 0);
-  if (fd < 0)
-    {
-      error = clib_error_return_unix (0, "socket");
-      goto done;
-    }
+      if (!dir)
+       {
+         error = clib_error_return (0,
+                                    "Skipping PCI device %U: failed to "
+                                    "read /sys/class/net",
+                                    format_vlib_pci_addr, addr);
+         goto err0;
+       }
 
-  while ((e = readdir (dir)))
-    {
-      struct ifreq ifr;
-      struct ethtool_drvinfo drvinfo;
+      fd = socket (PF_INET, SOCK_DGRAM, 0);
+      if (fd < 0)
+       {
+         error = clib_error_return_unix (0, "socket");
+         goto err1;
+       }
 
-      if (e->d_name[0] == '.') /* skip . and .. */
-       continue;
+      while ((e = readdir (dir)))
+       {
+         struct ifreq ifr;
+         struct ethtool_drvinfo drvinfo;
 
-      clib_memset (&ifr, 0, sizeof ifr);
-      clib_memset (&drvinfo, 0, sizeof drvinfo);
-      ifr.ifr_data = (char *) &drvinfo;
-      clib_strncpy (ifr.ifr_name, e->d_name, sizeof (ifr.ifr_name) - 1);
+         if (e->d_name[0] == '.') /* skip . and .. */
+           continue;
 
-      drvinfo.cmd = ETHTOOL_GDRVINFO;
-      if (ioctl (fd, SIOCETHTOOL, &ifr) < 0)
-       {
-         /* Some interfaces (eg "lo") don't support this ioctl */
-         if ((errno != ENOTSUP) && (errno != ENODEV))
-           clib_unix_warning ("ioctl fetch intf %s bus info error",
-                              e->d_name);
-         continue;
-       }
+         clib_memset (&ifr, 0, sizeof ifr);
+         clib_memset (&drvinfo, 0, sizeof drvinfo);
+         ifr.ifr_data = (char *) &drvinfo;
+         clib_strncpy (ifr.ifr_name, e->d_name, sizeof (ifr.ifr_name) - 1);
 
-      if (strcmp ((char *) s, drvinfo.bus_info))
-       continue;
+         drvinfo.cmd = ETHTOOL_GDRVINFO;
+         if (ioctl (fd, SIOCETHTOOL, &ifr) < 0)
+           {
+             /* Some interfaces (eg "lo") don't support this ioctl */
+             if ((errno != ENOTSUP) && (errno != ENODEV))
+               clib_unix_warning ("ioctl fetch intf %s bus info error",
+                                  e->d_name);
+             continue;
+           }
 
-      clib_memset (&ifr, 0, sizeof (ifr));
-      clib_strncpy (ifr.ifr_name, e->d_name, sizeof (ifr.ifr_name) - 1);
+         if (strcmp ((char *) s, drvinfo.bus_info))
+           continue;
 
-      if (ioctl (fd, SIOCGIFFLAGS, &ifr) < 0)
-       {
-         error = clib_error_return_unix (0, "ioctl fetch intf %s flags",
-                                         e->d_name);
-         close (fd);
-         goto done;
-       }
+         clib_memset (&ifr, 0, sizeof (ifr));
+         clib_strncpy (ifr.ifr_name, e->d_name, sizeof (ifr.ifr_name) - 1);
 
-      if (ifr.ifr_flags & IFF_UP)
-       {
-         vlib_log (VLIB_LOG_LEVEL_WARNING, pci_main.log_default,
-                   "Skipping PCI device %U as host "
-                   "interface %s is up", format_vlib_pci_addr, addr,
-                   e->d_name);
-         close (fd);
-         goto done;
+         if (ioctl (fd, SIOCGIFFLAGS, &ifr) < 0)
+           {
+             error = clib_error_return_unix (0, "ioctl fetch intf %s flags",
+                                             e->d_name);
+             close (fd);
+             goto err1;
+           }
+
+         if (ifr.ifr_flags & IFF_UP)
+           {
+             vlib_log (VLIB_LOG_LEVEL_WARNING, pci_main.log_default,
+                       "Skipping PCI device %U as host "
+                       "interface %s is up",
+                       format_vlib_pci_addr, addr, e->d_name);
+             close (fd);
+             goto err1;
+           }
        }
-    }
 
-  close (fd);
-  vec_reset_length (s);
+      close (fd);
+      vec_reset_length (s);
+    }
 
   s = format (s, "%v/driver/unbind%c", dev_dir_name, 0);
   clib_sysfs_write ((char *) s, "%U", format_vlib_pci_addr, addr);
@@ -565,8 +616,9 @@ vlib_pci_bind_to_uio (vlib_main_t * vm, vlib_pci_addr_t * addr,
       vec_reset_length (s);
     }
 
-done:
+err1:
   closedir (dir);
+err0:
   vec_free (s);
   vec_free (dev_dir_name);
   vec_free (driver_name);
@@ -595,34 +647,14 @@ vfio_set_irqs (vlib_main_t * vm, linux_pci_device_t * p, u32 index, u32 start,
 {
   int data_len = efds ? count * sizeof (int) : 0;
   u8 buf[sizeof (struct vfio_irq_set) + data_len];
-  struct vfio_irq_info ii = { 0 };
   struct vfio_irq_set *irq_set = (struct vfio_irq_set *) buf;
 
-
-  ii.argsz = sizeof (struct vfio_irq_info);
-  ii.index = index;
-
-  if (ioctl (p->fd, VFIO_DEVICE_GET_IRQ_INFO, &ii) < 0)
-    return clib_error_return_unix (0, "ioctl(VFIO_DEVICE_GET_IRQ_INFO) "
-                                  "'%U'", format_vlib_pci_addr, &p->addr);
-
-  pci_log_debug (vm, p, "%s index:%u count:%u flags: %s%s%s%s(0x%x)",
-                __func__, ii.index, ii.count,
-                ii.flags & VFIO_IRQ_INFO_EVENTFD ? "eventfd " : "",
-                ii.flags & VFIO_IRQ_INFO_MASKABLE ? "maskable " : "",
-                ii.flags & VFIO_IRQ_INFO_AUTOMASKED ? "automasked " : "",
-                ii.flags & VFIO_IRQ_INFO_NORESIZE ? "noresize " : "",
-                ii.flags);
-
-  if (ii.count < start + count)
-    return clib_error_return_unix (0, "vfio_set_irq: unexistng interrupt on "
-                                  "'%U'", format_vlib_pci_addr, &p->addr);
-
-
   if (efds)
     {
+      int *data = (int *) irq_set->data;
       flags |= VFIO_IRQ_SET_DATA_EVENTFD;
-      clib_memcpy_fast (&irq_set->data, efds, data_len);
+      for (u32 i = 0; i < count; i++)
+       data[i] = efds[i];
     }
   else
     flags |= VFIO_IRQ_SET_DATA_NONE;
@@ -637,11 +669,11 @@ vfio_set_irqs (vlib_main_t * vm, linux_pci_device_t * p, u32 index, u32 start,
   irq_set->flags = flags;
 
   if (ioctl (p->fd, VFIO_DEVICE_SET_IRQS, irq_set) < 0)
-    return clib_error_return_unix (0, "%U:ioctl(VFIO_DEVICE_SET_IRQS) "
-                                  "[index = %u, start = %u, count = %u, "
-                                  "flags = 0x%x]",
+    return clib_error_return_unix (0, "%U:ioctl(VFIO_DEVICE_SET_IRQS)\n%U",
                                   format_vlib_pci_addr, &p->addr,
-                                  index, start, count, flags);
+                                  format_vfio_irq_set, irq_set);
+
+  log_debug (p, "%s:\n%U", __func__, format_vfio_irq_set, irq_set);
   return 0;
 }
 
@@ -800,13 +832,12 @@ vlib_pci_register_intx_handler (vlib_main_t * vm, vlib_pci_dev_handle_t h,
       if (ioctl (p->fd, VFIO_DEVICE_GET_IRQ_INFO, &ii) < 0)
        return clib_error_return_unix (0, "ioctl(VFIO_DEVICE_GET_IRQ_INFO) '"
                                       "%U'", format_vlib_pci_addr, &p->addr);
-      pci_log_debug (vm, p, "%s index:%u count:%u flags: %s%s%s%s(0x%x)",
-                    __func__, ii.index, ii.count,
-                    ii.flags & VFIO_IRQ_INFO_EVENTFD ? "eventfd " : "",
-                    ii.flags & VFIO_IRQ_INFO_MASKABLE ? "maskable " : "",
-                    ii.flags & VFIO_IRQ_INFO_AUTOMASKED ? "automasked " : "",
-                    ii.flags & VFIO_IRQ_INFO_NORESIZE ? "noresize " : "",
-                    ii.flags);
+      log_debug (
+       p, "%s index:%u count:%u flags: %s%s%s%s(0x%x)", __func__, ii.index,
+       ii.count, ii.flags & VFIO_IRQ_INFO_EVENTFD ? "eventfd " : "",
+       ii.flags & VFIO_IRQ_INFO_MASKABLE ? "maskable " : "",
+       ii.flags & VFIO_IRQ_INFO_AUTOMASKED ? "automasked " : "",
+       ii.flags & VFIO_IRQ_INFO_NORESIZE ? "noresize " : "", ii.flags);
       if (ii.count != 1)
        return clib_error_return (0, "INTx interrupt does not exist on device"
                                  "'%U'", format_vlib_pci_addr, &p->addr);
@@ -834,6 +865,27 @@ vlib_pci_register_intx_handler (vlib_main_t * vm, vlib_pci_dev_handle_t h,
   return 0;
 }
 
+clib_error_t *
+vlib_pci_unregister_intx_handler (vlib_main_t *vm, vlib_pci_dev_handle_t h)
+{
+  linux_pci_device_t *p = linux_pci_get_device (h);
+  linux_pci_irq_t *irq = &p->intx_irq;
+
+  if (irq->intx_handler == 0)
+    return 0;
+
+  clib_file_del_by_index (&file_main, irq->clib_file_index);
+  if (p->type == LINUX_PCI_DEVICE_TYPE_VFIO)
+    {
+      close (irq->fd);
+      irq->fd = -1;
+    }
+
+  irq->intx_handler = 0;
+
+  return 0;
+}
+
 clib_error_t *
 vlib_pci_register_msix_handler (vlib_main_t * vm, vlib_pci_dev_handle_t h,
                                u32 start, u32 count,
@@ -847,10 +899,8 @@ vlib_pci_register_msix_handler (vlib_main_t * vm, vlib_pci_dev_handle_t h,
     return clib_error_return (0, "vfio driver is needed for MSI-X interrupt "
                              "support");
 
-  /* *INDENT-OFF* */
   vec_validate_init_empty (p->msix_irqs, start + count - 1, (linux_pci_irq_t)
                           { .fd = -1});
-  /* *INDENT-ON* */
 
   for (i = start; i < start + count; i++)
     {
@@ -891,6 +941,33 @@ error:
   return err;
 }
 
+clib_error_t *
+vlib_pci_unregister_msix_handler (vlib_main_t *vm, vlib_pci_dev_handle_t h,
+                                 u32 start, u32 count)
+{
+  clib_error_t *err = 0;
+  linux_pci_device_t *p = linux_pci_get_device (h);
+  u32 i;
+
+  if (p->type != LINUX_PCI_DEVICE_TYPE_VFIO)
+    return clib_error_return (0, "vfio driver is needed for MSI-X interrupt "
+                                "support");
+
+  for (i = start; i < start + count; i++)
+    {
+      linux_pci_irq_t *irq = vec_elt_at_index (p->msix_irqs, i);
+
+      if (irq->fd != -1)
+       {
+         clib_file_del_by_index (&file_main, irq->clib_file_index);
+         close (irq->fd);
+         irq->fd = -1;
+       }
+    }
+
+  return err;
+}
+
 clib_error_t *
 vlib_pci_enable_msix_irq (vlib_main_t * vm, vlib_pci_dev_handle_t h,
                          u16 start, u16 count)
@@ -903,9 +980,9 @@ vlib_pci_enable_msix_irq (vlib_main_t * vm, vlib_pci_dev_handle_t h,
     return clib_error_return (0, "vfio driver is needed for MSI-X interrupt "
                              "support");
 
-  for (i = start; i < start + count; i++)
+  for (i = 0; i < count; i++)
     {
-      linux_pci_irq_t *irq = vec_elt_at_index (p->msix_irqs, i);
+      linux_pci_irq_t *irq = vec_elt_at_index (p->msix_irqs, start + i);
       fds[i] = irq->fd;
     }
 
@@ -978,7 +1055,7 @@ add_device_vfio (vlib_main_t * vm, linux_pci_device_t * p,
       goto error;
     }
 
-  pci_log_debug (vm, p, "%s %U", __func__, format_vfio_region_info, &reg);
+  log_debug (p, "%s %U", __func__, format_vfio_region_info, &reg);
 
   p->config_offset = reg.offset;
   p->config_fd = p->fd;
@@ -1001,7 +1078,6 @@ add_device_vfio (vlib_main_t * vm, linux_pci_device_t * p,
   if (p->supports_va_dma)
     {
       vlib_buffer_pool_t *bp;
-      /* *INDENT-OFF* */
       vec_foreach (bp, vm->buffer_main->buffer_pools)
        {
          u32 i;
@@ -1010,7 +1086,6 @@ add_device_vfio (vlib_main_t * vm, linux_pci_device_t * p,
          for (i = 0; i < pm->n_pages; i++)
            vfio_map_physmem_page (vm, pm->base + (i << pm->log2_page_size));
        }
-      /* *INDENT-ON* */
     }
 
   if (r && r->init_function)
@@ -1113,7 +1188,7 @@ vlib_pci_region (vlib_main_t * vm, vlib_pci_dev_handle_t h, u32 bar, int *fd,
       _fd = p->fd;
       _size = r->size;
       _offset = r->offset;
-      pci_log_debug (vm, p, "%s %U", __func__, format_vfio_region_info, r);
+      log_debug (p, "%s %U", __func__, format_vfio_region_info, r);
       clib_mem_free (r);
     }
   else
@@ -1133,29 +1208,25 @@ vlib_pci_map_region_int (vlib_main_t * vm, vlib_pci_dev_handle_t h,
   linux_pci_device_t *p = linux_pci_get_device (h);
   int fd = -1;
   clib_error_t *error;
-  int flags = MAP_SHARED;
   u64 size = 0, offset = 0;
-  u16 command;
+  vlib_pci_config_reg_command_t command;
 
-  pci_log_debug (vm, p, "map region %u to va %p", bar, addr);
+  log_debug (p, "map region %u to va %p", bar, addr);
 
-  if ((error = vlib_pci_read_config_u16 (vm, h, 4, &command)))
+  if ((error = vlib_pci_read_config_u16 (vm, h, 4, &command.as_u16)))
     return error;
 
-  if (!(command & PCI_COMMAND_MEMORY))
+  if (!(command.mem_space))
     {
-      pci_log_debug (vm, p, "setting memory enable bit");
-      command |= PCI_COMMAND_MEMORY;
-      if ((error = vlib_pci_write_config_u16 (vm, h, 4, &command)))
+      log_debug (p, "setting memory enable bit");
+      command.mem_space = 1;
+      if ((error = vlib_pci_write_config_u16 (vm, h, 4, &command.as_u16)))
        return error;
     }
 
   if ((error = vlib_pci_region (vm, h, bar, &fd, &size, &offset)))
     return error;
 
-  if (p->type == LINUX_PCI_DEVICE_TYPE_UIO && addr != 0)
-    flags |= MAP_FIXED;
-
   *result = clib_mem_vm_map_shared (addr, size, fd, offset,
                                    "PCIe %U region %u", format_vlib_pci_addr,
                                    vlib_pci_get_addr (vm, h), bar);
@@ -1167,10 +1238,8 @@ vlib_pci_map_region_int (vlib_main_t * vm, vlib_pci_dev_handle_t h,
       return error;
     }
 
-  /* *INDENT-OFF* */
   vec_validate_init_empty (p->regions, bar,
                           (linux_pci_region_t) { .fd = -1});
-  /* *INDENT-ON* */
   if (p->type == LINUX_PCI_DEVICE_TYPE_UIO)
     p->regions[bar].fd = fd;
   p->regions[bar].addr = *result;
@@ -1261,12 +1330,19 @@ vlib_pci_device_open (vlib_main_t * vm, vlib_pci_addr_t * addr,
 
   if (err)
     return err;
-  for (i = ids; i->vendor_id != 0; i++)
-    if (i->vendor_id == di->vendor_id && i->device_id == di->device_id)
-      break;
 
-  if (i->vendor_id == 0)
-    return clib_error_return (0, "Wrong vendor or device id");
+  if (ids)
+    {
+      for (i = ids; i->vendor_id != 0; i++)
+       if (i->vendor_id == di->vendor_id && i->device_id == di->device_id)
+         break;
+
+      if (i->vendor_id == 0)
+       {
+         vlib_pci_free_device_info (di);
+         return clib_error_return (0, "Wrong vendor or device id");
+       }
+    }
 
   pool_get (lpm->linux_pci_devices, p);
   p->handle = p - lpm->linux_pci_devices;
@@ -1279,9 +1355,8 @@ vlib_pci_device_open (vlib_main_t * vm, vlib_pci_addr_t * addr,
    */
   p->io_fd = -1;
 
-  pci_log_debug (vm, p, "open vid:0x%04x did:0x%04x driver:%s iommu_group:%d",
-                di->vendor_id, di->device_id, di->driver_name,
-                di->iommu_group);
+  log_debug (p, "open vid:0x%04x did:0x%04x driver:%s iommu_group:%d",
+            di->vendor_id, di->device_id, di->driver_name, di->iommu_group);
 
   if (clib_strncmp ("vfio-pci", (char *) di->driver_name, 8) == 0)
     err = add_device_vfio (vm, p, di, 0);
@@ -1299,7 +1374,7 @@ error:
   vlib_pci_free_device_info (di);
   if (err)
     {
-      pci_log_err (vm, p, "%U", format_clib_error, err);
+      log_err (p, "%U", format_clib_error, err);
       clib_memset (p, 0, sizeof (linux_pci_device_t));
       pool_put (lpm->linux_pci_devices, p);
     }
@@ -1345,7 +1420,6 @@ vlib_pci_device_close (vlib_main_t * vm, vlib_pci_dev_handle_t h)
          err = vfio_set_irqs (vm, p, VFIO_PCI_MSIX_IRQ_INDEX, 0, 0,
                               VFIO_IRQ_SET_ACTION_TRIGGER, 0);
          clib_error_free (err);
-          /* *INDENT-OFF* */
          vec_foreach (irq, p->msix_irqs)
            {
              if (irq->fd == -1)
@@ -1353,12 +1427,10 @@ vlib_pci_device_close (vlib_main_t * vm, vlib_pci_dev_handle_t h)
              clib_file_del_by_index (&file_main, irq->clib_file_index);
              close (irq->fd);
            }
-          /* *INDENT-ON* */
          vec_free (p->msix_irqs);
        }
     }
 
-  /* *INDENT-OFF* */
   vec_foreach (res, p->regions)
     {
       if (res->size == 0)
@@ -1367,7 +1439,6 @@ vlib_pci_device_close (vlib_main_t * vm, vlib_pci_dev_handle_t h)
       if (res->fd != -1)
         close (res->fd);
     }
-  /* *INDENT-ON* */
   vec_free (p->regions);
 
   close (p->fd);
@@ -1490,28 +1561,27 @@ linux_pci_init (vlib_main_t * vm)
 
   ASSERT (sizeof (vlib_pci_addr_t) == sizeof (u32));
 
-  addrs = vlib_pci_get_all_dev_addrs ();
-  /* *INDENT-OFF* */
-  vec_foreach (addr, addrs)
+  if (pm->pci_device_registrations)
     {
-      vlib_pci_device_info_t *d;
-      if ((d = vlib_pci_get_device_info (vm, addr, 0)))
+      addrs = vlib_pci_get_all_dev_addrs ();
+      vec_foreach (addr, addrs)
        {
-         init_device_from_registered (vm, d);
-         vlib_pci_free_device_info (d);
+         vlib_pci_device_info_t *d;
+         if ((d = vlib_pci_get_device_info (vm, addr, 0)))
+           {
+             init_device_from_registered (vm, d);
+             vlib_pci_free_device_info (d);
+           }
        }
     }
-  /* *INDENT-ON* */
 
   return 0;
 }
 
-/* *INDENT-OFF* */
 VLIB_INIT_FUNCTION (linux_pci_init) =
 {
   .runs_after = VLIB_INITS("unix_input_init"),
 };
-/* *INDENT-ON* */
 
 /*
  * fd.io coding-style-patch-verification: ON