diff options
author | Tycho Nightingale <tychon@FreeBSD.org> | 2019-05-16 17:41:16 +0000 |
---|---|---|
committer | Tycho Nightingale <tychon@FreeBSD.org> | 2019-05-16 17:41:16 +0000 |
commit | b961c0f2442979d7a611964adb729188c90e5203 (patch) | |
tree | 93a024fb0dbd3aee0fd9fe943e67fc19dd7c45c5 /sys/compat | |
parent | f4ab98c597fcf448d18fe51387e66da08e709a8c (diff) | |
download | src-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.c | 27 |
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, |