The patch adds functions for unmapping igb_uio resources. The patch is only
for Linux and igb_uio environment. VFIO and BSD are not supported.

Signed-off-by: Tetsuya Mukawa <mukawa at igel.co.jp>
---
 lib/librte_eal/linuxapp/eal/eal_pci.c              | 32 +++++++++++++
 lib/librte_eal/linuxapp/eal/eal_pci_uio.c          | 56 ++++++++++++++++++++++
 lib/librte_eal/linuxapp/eal/include/eal_pci_init.h |  7 +++
 3 files changed, 95 insertions(+)

diff --git a/lib/librte_eal/linuxapp/eal/eal_pci.c 
b/lib/librte_eal/linuxapp/eal/eal_pci.c
index 78df974..d7293c7 100644
--- a/lib/librte_eal/linuxapp/eal/eal_pci.c
+++ b/lib/librte_eal/linuxapp/eal/eal_pci.c
@@ -123,6 +123,22 @@ fail:
        return NULL;
 }

+#if defined(RTE_LIBRTE_EAL_HOTPLUG) && defined(RTE_LIBRTE_EAL_LINUXAPP)
+/* unmap a particular resource */
+void
+pci_unmap_resource(void *requested_addr, size_t size)
+{
+       /* Unmap the PCI memory resource of device */
+       if (munmap(requested_addr, size)) {
+               RTE_LOG(ERR, EAL, "%s(): cannot munmap(%p, 0x%lx): %s\n",
+                       __func__, requested_addr, (unsigned long)size,
+                       strerror(errno));
+       } else
+               RTE_LOG(DEBUG, EAL, "  PCI memory mapped at %p\n",
+                               requested_addr);
+}
+#endif /* RTE_LIBRTE_EAL_HOTPLUG & RTE_LIBRTE_EAL_LINUXAPP */
+
 /* parse the "resource" sysfs file */
 #define IORESOURCE_MEM  0x00000200

@@ -493,6 +509,22 @@ pci_map_device(struct rte_pci_device *dev)
        return 0;
 }

+#if defined(RTE_LIBRTE_EAL_HOTPLUG) && defined(RTE_LIBRTE_EAL_LINUXAPP)
+static void
+pci_unmap_device(struct rte_pci_device *dev)
+{
+       /* try unmapping the NIC resources using VFIO if it exists */
+#ifdef VFIO_PRESENT
+       if (pci_vfio_is_enabled()) {
+               RTE_LOG(ERR, EAL, "%s() doesn't support vfio yet.\n",
+                               __func__);
+               return;
+       }
+#endif
+       pci_uio_unmap_resource(dev);
+}
+#endif /* RTE_LIBRTE_EAL_HOTPLUG & RTE_LIBRTE_EAL_LINUXAPP */
+
 /*
  * If vendor/device ID match, call the devinit() function of the
  * driver.
diff --git a/lib/librte_eal/linuxapp/eal/eal_pci_uio.c 
b/lib/librte_eal/linuxapp/eal/eal_pci_uio.c
index f0deeba..ff48eb9 100644
--- a/lib/librte_eal/linuxapp/eal/eal_pci_uio.c
+++ b/lib/librte_eal/linuxapp/eal/eal_pci_uio.c
@@ -395,6 +395,62 @@ pci_uio_map_resource(struct rte_pci_device *dev)
        return 0;
 }

+#if defined(RTE_LIBRTE_EAL_HOTPLUG) && defined(RTE_LIBRTE_EAL_LINUXAPP)
+static void
+pci_uio_unmap(struct mapped_pci_resource *uio_res)
+{
+       int i;
+
+       for (i = 0; i != uio_res->nb_maps; i++)
+               pci_unmap_resource(uio_res->maps[i].addr,
+                               (size_t)uio_res->maps[i].size);
+}
+
+static struct mapped_pci_resource *
+pci_uio_find_resource(struct rte_pci_device *dev)
+{
+       struct mapped_pci_resource *uio_res;
+
+       TAILQ_FOREACH(uio_res, pci_res_list, next) {
+
+               /* skip this element if it doesn't match our PCI address */
+               if (!eal_compare_pci_addr(&uio_res->pci_addr, &dev->addr))
+                       return uio_res;
+       }
+       return NULL;
+}
+
+/* unmap the PCI resource of a PCI device in virtual memory */
+void
+pci_uio_unmap_resource(struct rte_pci_device *dev)
+{
+       struct mapped_pci_resource *uio_res;
+
+       /* find an entry for the device */
+       uio_res = pci_uio_find_resource(dev);
+       if (uio_res == NULL)
+               return;
+
+       /* secondary processes - just free maps */
+       if (rte_eal_process_type() != RTE_PROC_PRIMARY)
+               return pci_uio_unmap(uio_res);
+
+       TAILQ_REMOVE(pci_res_list, uio_res, next);
+
+       /* unmap all resources */
+       pci_uio_unmap(uio_res);
+
+       /* free uio resource */
+       rte_free(uio_res);
+
+       /* close fd if in primary process */
+       close(dev->intr_handle.fd);
+
+       dev->intr_handle.fd = -1;
+       dev->intr_handle.type = RTE_INTR_HANDLE_UNKNOWN;
+}
+#endif /* RTE_LIBRTE_EAL_HOTPLUG & RTE_LIBRTE_EAL_LINUXAPP */
+
 /*
  * parse a sysfs file containing one integer value
  * different to the eal version, as it needs to work with 64-bit values
diff --git a/lib/librte_eal/linuxapp/eal/include/eal_pci_init.h 
b/lib/librte_eal/linuxapp/eal/include/eal_pci_init.h
index d758bee..ab9c16b 100644
--- a/lib/librte_eal/linuxapp/eal/include/eal_pci_init.h
+++ b/lib/librte_eal/linuxapp/eal/include/eal_pci_init.h
@@ -65,6 +65,13 @@ void *pci_map_resource(void *requested_addr, int fd, off_t 
offset,
 /* map IGB_UIO resource prototype */
 int pci_uio_map_resource(struct rte_pci_device *dev);

+#if defined(RTE_LIBRTE_EAL_HOTPLUG) && defined(RTE_LIBRTE_EAL_LINUXAPP)
+void pci_unmap_resource(void *requested_addr, size_t size);
+
+/* unmap IGB_UIO resource prototype */
+void pci_uio_unmap_resource(struct rte_pci_device *dev);
+#endif /* RTE_LIBRTE_EAL_HOTPLUG & RTE_LIBRTE_EAL_LINUXAPP */
+
 #ifdef VFIO_PRESENT

 #define VFIO_MAX_GROUPS 64
-- 
1.9.1

Reply via email to