New upstream version 17.11-rc3
[deb_dpdk.git] / drivers / bus / pci / linux / pci.c
similarity index 84%
rename from lib/librte_eal/linuxapp/eal/eal_pci.c
rename to drivers/bus/pci/linux/pci.c
index 8951ce7..5da6728 100644 (file)
 #include <rte_log.h>
 #include <rte_bus.h>
 #include <rte_pci.h>
+#include <rte_bus_pci.h>
 #include <rte_eal_memconfig.h>
 #include <rte_malloc.h>
 #include <rte_devargs.h>
 #include <rte_memcpy.h>
+#include <rte_vfio.h>
 
-#include "eal_filesystem.h"
 #include "eal_private.h"
-#include "eal_pci_init.h"
+#include "eal_filesystem.h"
+
+#include "private.h"
+#include "pci_init.h"
 
 /**
  * @file
@@ -362,7 +366,7 @@ pci_scan_one(const char *dirname, const struct rte_pci_addr *addr)
                int ret;
 
                TAILQ_FOREACH(dev2, &rte_pci_bus.device_list, next) {
-                       ret = rte_eal_compare_pci_addr(&dev->addr, &dev2->addr);
+                       ret = rte_pci_addr_cmp(&dev->addr, &dev2->addr);
                        if (ret > 0)
                                continue;
 
@@ -391,7 +395,7 @@ pci_update_device(const struct rte_pci_addr *addr)
        char filename[PATH_MAX];
 
        snprintf(filename, sizeof(filename), "%s/" PCI_PRI_FMT,
-                pci_get_sysfs_path(), addr->domain, addr->bus, addr->devid,
+                rte_pci_get_sysfs_path(), addr->domain, addr->bus, addr->devid,
                 addr->function);
 
        return pci_scan_one(filename, addr);
@@ -456,10 +460,15 @@ rte_pci_scan(void)
        struct rte_pci_addr addr;
 
        /* for debug purposes, PCI can be disabled */
-       if (internal_config.no_pci)
+       if (!rte_eal_has_pci())
                return 0;
 
-       dir = opendir(pci_get_sysfs_path());
+#ifdef VFIO_PRESENT
+       if (!pci_vfio_is_enabled())
+               RTE_LOG(DEBUG, EAL, "VFIO PCI modules not loaded\n");
+#endif
+
+       dir = opendir(rte_pci_get_sysfs_path());
        if (dir == NULL) {
                RTE_LOG(ERR, EAL, "%s(): opendir failed: %s\n",
                        __func__, strerror(errno));
@@ -474,7 +483,7 @@ rte_pci_scan(void)
                        continue;
 
                snprintf(dirname, sizeof(dirname), "%s/%s",
-                               pci_get_sysfs_path(), e->d_name);
+                               rte_pci_get_sysfs_path(), e->d_name);
 
                if (pci_scan_one(dirname, &addr) < 0)
                        goto error;
@@ -487,6 +496,131 @@ error:
        return -1;
 }
 
+/*
+ * Is pci device bound to any kdrv
+ */
+static inline int
+pci_one_device_is_bound(void)
+{
+       struct rte_pci_device *dev = NULL;
+       int ret = 0;
+
+       FOREACH_DEVICE_ON_PCIBUS(dev) {
+               if (dev->kdrv == RTE_KDRV_UNKNOWN ||
+                   dev->kdrv == RTE_KDRV_NONE) {
+                       continue;
+               } else {
+                       ret = 1;
+                       break;
+               }
+       }
+       return ret;
+}
+
+/*
+ * Any one of the device bound to uio
+ */
+static inline int
+pci_one_device_bound_uio(void)
+{
+       struct rte_pci_device *dev = NULL;
+       struct rte_devargs *devargs;
+       int need_check;
+
+       FOREACH_DEVICE_ON_PCIBUS(dev) {
+               devargs = dev->device.devargs;
+
+               need_check = 0;
+               switch (rte_pci_bus.bus.conf.scan_mode) {
+               case RTE_BUS_SCAN_WHITELIST:
+                       if (devargs && devargs->policy == RTE_DEV_WHITELISTED)
+                               need_check = 1;
+                       break;
+               case RTE_BUS_SCAN_UNDEFINED:
+               case RTE_BUS_SCAN_BLACKLIST:
+                       if (devargs == NULL ||
+                           devargs->policy != RTE_DEV_BLACKLISTED)
+                               need_check = 1;
+                       break;
+               }
+
+               if (!need_check)
+                       continue;
+
+               if (dev->kdrv == RTE_KDRV_IGB_UIO ||
+                  dev->kdrv == RTE_KDRV_UIO_GENERIC) {
+                       return 1;
+               }
+       }
+       return 0;
+}
+
+/*
+ * Any one of the device has iova as va
+ */
+static inline int
+pci_one_device_has_iova_va(void)
+{
+       struct rte_pci_device *dev = NULL;
+       struct rte_pci_driver *drv = NULL;
+
+       FOREACH_DRIVER_ON_PCIBUS(drv) {
+               if (drv && drv->drv_flags & RTE_PCI_DRV_IOVA_AS_VA) {
+                       FOREACH_DEVICE_ON_PCIBUS(dev) {
+                               if (dev->kdrv == RTE_KDRV_VFIO &&
+                                   rte_pci_match(drv, dev))
+                                       return 1;
+                       }
+               }
+       }
+       return 0;
+}
+
+/*
+ * Get iommu class of PCI devices on the bus.
+ */
+enum rte_iova_mode
+rte_pci_get_iommu_class(void)
+{
+       bool is_bound;
+       bool is_vfio_noiommu_enabled = true;
+       bool has_iova_va;
+       bool is_bound_uio;
+       bool spapr_iommu =
+#if defined(RTE_ARCH_PPC_64)
+               true;
+#else
+               false;
+#endif
+
+       is_bound = pci_one_device_is_bound();
+       if (!is_bound)
+               return RTE_IOVA_DC;
+
+       has_iova_va = pci_one_device_has_iova_va();
+       is_bound_uio = pci_one_device_bound_uio();
+#ifdef VFIO_PRESENT
+       is_vfio_noiommu_enabled = rte_vfio_noiommu_is_enabled() == true ?
+                                       true : false;
+#endif
+
+       if (has_iova_va && !is_bound_uio && !is_vfio_noiommu_enabled &&
+                       !spapr_iommu)
+               return RTE_IOVA_VA;
+
+       if (has_iova_va) {
+               RTE_LOG(WARNING, EAL, "Some devices want iova as va but pa will be used because.. ");
+               if (is_vfio_noiommu_enabled)
+                       RTE_LOG(WARNING, EAL, "vfio-noiommu mode configured\n");
+               if (is_bound_uio)
+                       RTE_LOG(WARNING, EAL, "few device bound to UIO\n");
+               if (spapr_iommu)
+                       RTE_LOG(WARNING, EAL, "sPAPR IOMMU does not support IOVA as VA\n");
+       }
+
+       return RTE_IOVA_PA;
+}
+
 /* Read PCI config space. */
 int rte_pci_read_config(const struct rte_pci_device *device,
                void *buf, size_t len, off_t offset)