dev: new device driver infra
[vpp.git] / src / vlib / linux / pci.c
index 8af1cda..69d26fd 100644 (file)
 #include <linux/vfio.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 +238,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);
@@ -300,15 +288,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 +339,7 @@ vlib_pci_get_device_info (vlib_main_t * vm, vlib_pci_addr_t * addr,
            break;
 
          len = (tag[2] << 8) | tag[1];
-         vec_validate (data, len);
+         vec_validate (data, len - 1);
 
          if (read (fd, data, len) != len)
            {
@@ -383,6 +375,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 +444,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 +477,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,91 +498,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)
-       {
-         error = clib_error_return (0, "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);
@@ -564,8 +617,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);
@@ -605,13 +659,12 @@ vfio_set_irqs (vlib_main_t * vm, linux_pci_device_t * p, u32 index, u32 start,
     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 < start + count)
     return clib_error_return_unix (0, "vfio_set_irq: unexistng interrupt on "
@@ -799,13 +852,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);
@@ -833,6 +885,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,
@@ -890,6 +963,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)
@@ -912,6 +1012,17 @@ vlib_pci_enable_msix_irq (vlib_main_t * vm, vlib_pci_dev_handle_t h,
                        VFIO_IRQ_SET_ACTION_TRIGGER, fds);
 }
 
+uword
+vlib_pci_get_msix_file_index (vlib_main_t * vm, vlib_pci_dev_handle_t h,
+                             u16 index)
+{
+  linux_pci_device_t *p = linux_pci_get_device (h);
+  linux_pci_irq_t *irq = vec_elt_at_index (p->msix_irqs, index);
+  if (irq->fd == -1)
+    return ~0;
+  return irq->clib_file_index;
+}
+
 clib_error_t *
 vlib_pci_disable_msix_irq (vlib_main_t * vm, vlib_pci_dev_handle_t h,
                           u16 start, u16 count)
@@ -966,13 +1077,7 @@ add_device_vfio (vlib_main_t * vm, linux_pci_device_t * p,
       goto error;
     }
 
-  pci_log_debug (vm, p, "%s region_info index:%u size:0x%lx offset:0x%lx "
-                "flags: %s%s%s(0x%x)", __func__,
-                reg.index, reg.size, reg.offset,
-                reg.flags & VFIO_REGION_INFO_FLAG_READ ? "rd " : "",
-                reg.flags & VFIO_REGION_INFO_FLAG_WRITE ? "wr " : "",
-                reg.flags & VFIO_REGION_INFO_FLAG_MMAP ? "mmap " : "",
-                reg.flags);
+  log_debug (p, "%s %U", __func__, format_vfio_region_info, &reg);
 
   p->config_offset = reg.offset;
   p->config_fd = p->fd;
@@ -1087,23 +1192,28 @@ vlib_pci_region (vlib_main_t * vm, vlib_pci_dev_handle_t h, u32 bar, int *fd,
     }
   else if (p->type == LINUX_PCI_DEVICE_TYPE_VFIO)
     {
-      struct vfio_region_info reg = { 0 };
-      reg.argsz = sizeof (struct vfio_region_info);
-      reg.index = bar;
-      if (ioctl (p->fd, VFIO_DEVICE_GET_REGION_INFO, &reg) < 0)
+      struct vfio_region_info *r;
+      u32 sz = sizeof (struct vfio_region_info);
+    again:
+      r = clib_mem_alloc (sz);
+      clib_memset (r, 0, sz);
+      r->argsz = sz;
+      r->index = bar;
+      if (ioctl (p->fd, VFIO_DEVICE_GET_REGION_INFO, r) < 0)
        return clib_error_return_unix (0, "ioctl(VFIO_DEVICE_GET_INFO) "
                                       "'%U'", format_vlib_pci_addr,
                                       &p->addr);
+      if (sz != r->argsz)
+       {
+         sz = r->argsz;
+         clib_mem_free (r);
+         goto again;
+       }
       _fd = p->fd;
-      _size = reg.size;
-      _offset = reg.offset;
-      pci_log_debug (vm, p, "%s region_info index:%u size:0x%lx offset:0x%lx "
-                    "flags: %s%s%s(0x%x)", __func__,
-                    reg.index, reg.size, reg.offset,
-                    reg.flags & VFIO_REGION_INFO_FLAG_READ ? "rd " : "",
-                    reg.flags & VFIO_REGION_INFO_FLAG_WRITE ? "wr " : "",
-                    reg.flags & VFIO_REGION_INFO_FLAG_MMAP ? "mmap " : "",
-                    reg.flags);
+      _size = r->size;
+      _offset = r->offset;
+      log_debug (p, "%s %U", __func__, format_vfio_region_info, r);
+      clib_mem_free (r);
     }
   else
     ASSERT (0);
@@ -1122,22 +1232,32 @@ 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;
+  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_region (vm, h, bar, &fd, &size, &offset)))
+  if ((error = vlib_pci_read_config_u16 (vm, h, 4, &command.as_u16)))
     return error;
 
-  if (p->type == LINUX_PCI_DEVICE_TYPE_UIO && addr != 0)
-    flags |= MAP_FIXED;
+  if (!(command.mem_space))
+    {
+      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;
+    }
 
-  *result = mmap (addr, size, PROT_READ | PROT_WRITE, flags, fd, offset);
-  if (*result == (void *) -1)
+  if ((error = vlib_pci_region (vm, h, bar, &fd, &size, &offset)))
+    return error;
+
+  *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);
+  if (*result == CLIB_MEM_VM_MAP_FAILED)
     {
       error = clib_error_return_unix (0, "mmap `BAR%u'", bar);
-      if (p->type == LINUX_PCI_DEVICE_TYPE_UIO)
+      if (p->type == LINUX_PCI_DEVICE_TYPE_UIO && (fd != -1))
        close (fd);
       return error;
     }
@@ -1236,12 +1356,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;
@@ -1254,9 +1381,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);
@@ -1274,7 +1400,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);
     }
@@ -1338,7 +1464,7 @@ vlib_pci_device_close (vlib_main_t * vm, vlib_pci_dev_handle_t h)
     {
       if (res->size == 0)
        continue;
-      munmap (res->addr, res->size);
+      clib_mem_vm_unmap (res->addr);
       if (res->fd != -1)
         close (res->fd);
     }