[dpdk-dev,17/25] eal/linux/pci: Add functions for unmapping igb_uio resources
Commit Message
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@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(+)
@@ -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.
@@ -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
@@ -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