aboutsummaryrefslogtreecommitdiff
path: root/sys/compat
diff options
context:
space:
mode:
authorTycho Nightingale <tychon@FreeBSD.org>2019-05-16 17:41:16 +0000
committerTycho Nightingale <tychon@FreeBSD.org>2019-05-16 17:41:16 +0000
commitb961c0f2442979d7a611964adb729188c90e5203 (patch)
tree93a024fb0dbd3aee0fd9fe943e67fc19dd7c45c5 /sys/compat
parentf4ab98c597fcf448d18fe51387e66da08e709a8c (diff)
downloadsrc-b961c0f2442979d7a611964adb729188c90e5203.tar.gz
src-b961c0f2442979d7a611964adb729188c90e5203.zip
Allow loading the same DMA address multiple times without any prior
unload for the LinuxKPI. Reviewed by: kib, zeising Sponsored by: Dell EMC Isilon Differential Revision: https://reviews.freebsd.org/D20181
Notes
Notes: svn path=/head/; revision=347836
Diffstat (limited to 'sys/compat')
-rw-r--r--sys/compat/linuxkpi/common/src/linux_pci.c27
1 files changed, 27 insertions, 0 deletions
diff --git a/sys/compat/linuxkpi/common/src/linux_pci.c b/sys/compat/linuxkpi/common/src/linux_pci.c
index ff559b0eb0fc..8de6968a7de0 100644
--- a/sys/compat/linuxkpi/common/src/linux_pci.c
+++ b/sys/compat/linuxkpi/common/src/linux_pci.c
@@ -520,6 +520,7 @@ linux_dma_alloc_coherent(struct device *dev, size_t size,
return (mem);
}
+#if defined(__i386__) || defined(__amd64__) || defined(__aarch64__)
dma_addr_t
linux_dma_map_phys(struct device *dev, vm_paddr_t phys, size_t len)
{
@@ -530,6 +531,15 @@ linux_dma_map_phys(struct device *dev, vm_paddr_t phys, size_t len)
priv = dev->dma_priv;
+ /*
+ * If the resultant mapping will be entirely 1:1 with the
+ * physical address, short-circuit the remainder of the
+ * bus_dma API. This avoids tracking collisions in the pctrie
+ * with the additional benefit of reducing overhead.
+ */
+ if (bus_dma_id_mapped(priv->dmat, phys, len))
+ return (phys);
+
obj = uma_zalloc(linux_dma_obj_zone, 0);
DMA_PRIV_LOCK(priv);
@@ -562,7 +572,15 @@ linux_dma_map_phys(struct device *dev, vm_paddr_t phys, size_t len)
DMA_PRIV_UNLOCK(priv);
return (obj->dma_addr);
}
+#else
+dma_addr_t
+linux_dma_map_phys(struct device *dev, vm_paddr_t phys, size_t len)
+{
+ return (phys);
+}
+#endif
+#if defined(__i386__) || defined(__amd64__) || defined(__aarch64__)
void
linux_dma_unmap(struct device *dev, dma_addr_t dma_addr, size_t len)
{
@@ -571,6 +589,9 @@ linux_dma_unmap(struct device *dev, dma_addr_t dma_addr, size_t len)
priv = dev->dma_priv;
+ if (pctrie_is_empty(&priv->ptree))
+ return;
+
DMA_PRIV_LOCK(priv);
obj = LINUX_DMA_PCTRIE_LOOKUP(&priv->ptree, dma_addr);
if (obj == NULL) {
@@ -584,6 +605,12 @@ linux_dma_unmap(struct device *dev, dma_addr_t dma_addr, size_t len)
uma_zfree(linux_dma_obj_zone, obj);
}
+#else
+void
+linux_dma_unmap(struct device *dev, dma_addr_t dma_addr, size_t len)
+{
+}
+#endif
int
linux_dma_map_sg_attrs(struct device *dev, struct scatterlist *sgl, int nents,