New upstream version 18.08
[deb_dpdk.git] / drivers / bus / pci / linux / pci_vfio.c
index aeeaa9e..686386d 100644 (file)
@@ -584,6 +584,9 @@ pci_vfio_map_resource_secondary(struct rte_pci_device *dev)
                dev->mem_resource[i].addr = maps[i].addr;
        }
 
+       /* we need save vfio_dev_fd, so it can be used during release */
+       dev->intr_handle.vfio_dev_fd = vfio_dev_fd;
+
        return 0;
 err_vfio_dev_fd:
        close(vfio_dev_fd);
@@ -603,22 +606,58 @@ pci_vfio_map_resource(struct rte_pci_device *dev)
                return pci_vfio_map_resource_secondary(dev);
 }
 
-int
-pci_vfio_unmap_resource(struct rte_pci_device *dev)
+static struct mapped_pci_resource *
+find_and_unmap_vfio_resource(struct mapped_pci_res_list *vfio_res_list,
+                       struct rte_pci_device *dev,
+                       const char *pci_addr)
+{
+       struct mapped_pci_resource *vfio_res = NULL;
+       struct pci_map *maps;
+       int i;
+
+       /* Get vfio_res */
+       TAILQ_FOREACH(vfio_res, vfio_res_list, next) {
+               if (rte_pci_addr_cmp(&vfio_res->pci_addr, &dev->addr))
+                       continue;
+               break;
+       }
+
+       if  (vfio_res == NULL)
+               return vfio_res;
+
+       RTE_LOG(INFO, EAL, "Releasing pci mapped resource for %s\n",
+               pci_addr);
+
+       maps = vfio_res->maps;
+       for (i = 0; i < (int) vfio_res->nb_maps; i++) {
+
+               /*
+                * We do not need to be aware of MSI-X table BAR mappings as
+                * when mapping. Just using current maps array is enough
+                */
+               if (maps[i].addr) {
+                       RTE_LOG(INFO, EAL, "Calling pci_unmap_resource for %s at %p\n",
+                               pci_addr, maps[i].addr);
+                       pci_unmap_resource(maps[i].addr, maps[i].size);
+               }
+       }
+
+       return vfio_res;
+}
+
+static int
+pci_vfio_unmap_resource_primary(struct rte_pci_device *dev)
 {
        char pci_addr[PATH_MAX] = {0};
        struct rte_pci_addr *loc = &dev->addr;
-       int i, ret;
        struct mapped_pci_resource *vfio_res = NULL;
        struct mapped_pci_res_list *vfio_res_list;
-
-       struct pci_map *maps;
+       int ret;
 
        /* store PCI address string */
        snprintf(pci_addr, sizeof(pci_addr), PCI_PRI_FMT,
                        loc->domain, loc->bus, loc->devid, loc->function);
 
-
        if (close(dev->intr_handle.fd) < 0) {
                RTE_LOG(INFO, EAL, "Error when closing eventfd file descriptor for %s\n",
                        pci_addr);
@@ -639,13 +678,10 @@ pci_vfio_unmap_resource(struct rte_pci_device *dev)
                return ret;
        }
 
-       vfio_res_list = RTE_TAILQ_CAST(rte_vfio_tailq.head, mapped_pci_res_list);
-       /* Get vfio_res */
-       TAILQ_FOREACH(vfio_res, vfio_res_list, next) {
-               if (memcmp(&vfio_res->pci_addr, &dev->addr, sizeof(dev->addr)))
-                       continue;
-               break;
-       }
+       vfio_res_list =
+               RTE_TAILQ_CAST(rte_vfio_tailq.head, mapped_pci_res_list);
+       vfio_res = find_and_unmap_vfio_resource(vfio_res_list, dev, pci_addr);
+
        /* if we haven't found our tailq entry, something's wrong */
        if (vfio_res == NULL) {
                RTE_LOG(ERR, EAL, "  %s cannot find TAILQ entry for PCI device!\n",
@@ -653,29 +689,55 @@ pci_vfio_unmap_resource(struct rte_pci_device *dev)
                return -1;
        }
 
-       /* unmap BARs */
-       maps = vfio_res->maps;
+       TAILQ_REMOVE(vfio_res_list, vfio_res, next);
 
-       RTE_LOG(INFO, EAL, "Releasing pci mapped resource for %s\n",
-               pci_addr);
-       for (i = 0; i < (int) vfio_res->nb_maps; i++) {
+       return 0;
+}
 
-               /*
-                * We do not need to be aware of MSI-X table BAR mappings as
-                * when mapping. Just using current maps array is enough
-                */
-               if (maps[i].addr) {
-                       RTE_LOG(INFO, EAL, "Calling pci_unmap_resource for %s at %p\n",
-                               pci_addr, maps[i].addr);
-                       pci_unmap_resource(maps[i].addr, maps[i].size);
-               }
+static int
+pci_vfio_unmap_resource_secondary(struct rte_pci_device *dev)
+{
+       char pci_addr[PATH_MAX] = {0};
+       struct rte_pci_addr *loc = &dev->addr;
+       struct mapped_pci_resource *vfio_res = NULL;
+       struct mapped_pci_res_list *vfio_res_list;
+       int ret;
+
+       /* store PCI address string */
+       snprintf(pci_addr, sizeof(pci_addr), PCI_PRI_FMT,
+                       loc->domain, loc->bus, loc->devid, loc->function);
+
+       ret = rte_vfio_release_device(rte_pci_get_sysfs_path(), pci_addr,
+                                 dev->intr_handle.vfio_dev_fd);
+       if (ret < 0) {
+               RTE_LOG(ERR, EAL,
+                       "%s(): cannot release device\n", __func__);
+               return ret;
        }
 
-       TAILQ_REMOVE(vfio_res_list, vfio_res, next);
+       vfio_res_list =
+               RTE_TAILQ_CAST(rte_vfio_tailq.head, mapped_pci_res_list);
+       vfio_res = find_and_unmap_vfio_resource(vfio_res_list, dev, pci_addr);
+
+       /* if we haven't found our tailq entry, something's wrong */
+       if (vfio_res == NULL) {
+               RTE_LOG(ERR, EAL, "  %s cannot find TAILQ entry for PCI device!\n",
+                               pci_addr);
+               return -1;
+       }
 
        return 0;
 }
 
+int
+pci_vfio_unmap_resource(struct rte_pci_device *dev)
+{
+       if (rte_eal_process_type() == RTE_PROC_PRIMARY)
+               return pci_vfio_unmap_resource_primary(dev);
+       else
+               return pci_vfio_unmap_resource_secondary(dev);
+}
+
 int
 pci_vfio_ioport_map(struct rte_pci_device *dev, int bar,
                    struct rte_pci_ioport *p)