perfmon: fix iio-bw coverity issues
[vpp.git] / src / vlib / linux / pci.c
index 1caf0c9..e049b23 100644 (file)
@@ -55,6 +55,7 @@
 #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 =
@@ -347,7 +348,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 +384,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);
+  u32 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)
 {
@@ -523,9 +582,10 @@ vlib_pci_bind_to_uio (vlib_main_t * vm, vlib_pci_addr_t * addr,
 
       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);
+         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;
        }
@@ -1132,7 +1192,6 @@ 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;
 
@@ -1152,9 +1211,6 @@ vlib_pci_map_region_int (vlib_main_t * vm, vlib_pci_dev_handle_t h,
   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);