[<prev] [next>] [<thread-prev] [day] [month] [year] [list]
Message-ID: <CAEHaoC1uCJ98JsYt4x2cHwOM6EvLotj5MTNi=1iGSfc3DOD3hA@mail.gmail.com>
Date: Sun, 3 Aug 2025 14:19:15 +0300
From: Constantine Gavrilov <cgavrilov@...inidat.com>
To: linux-kernel@...r.kernel.org, Marek Szyprowski <m.szyprowski@...sung.com>,
Robin Murphy <robin.murphy@....com>, iommu@...ts.linux.dev
Subject: [PATCH 8/8] Large DMA alloc/add min_dma_addr to device struct
This is the ninth patch from the set of patches that enable large IOMMU
DMA registrations. Entire work is available at the master branch of the
master branch of git@...hub.com:cgavrilov/linux.git repo.
Some devices (like NTB or GPU) allow mapping of the system memory to PCIe bars,
allowing to implement PCIe interconnects when devices are connected to more
than one root complex. After one root complex does the mapping, an application
on another root complex can access the memory using the PCIe bar of the device.
Since a typical system memory mapping uses offset translation (between the
device bar address and the DMA address), the device driver needs to know which
contiguous DMA address range is available to satisfy the device needs before it
can set up the mapping offset. After querying the available range, the device
driver can set up the mapping translation and use the top and low DMA address
constraints to ensure that future DMA allocation APIs will allocate DMA
addresses within the selected range.
This patch adds min_dma_addr to the device structure and uses the added field
in alloc_iova_fast() API.
commit 0bebd4d0829b941fc38c1311efa7309c033968e4 (HEAD -> master, github/master)
Author: Constantine Gavrilov <cgavrilov@...inidat.com>
Date: Tue Jul 1 15:29:40 2025 +0300
Add min_dma_addr to the device structure and use it in
iommu_dma_alloc_iova().
Devices that map memory windows to PCI bars (for example NTB devices)
may need this change. This is because such devices may use very large
memory windows (terabytes in size), and they cannot simply cap the top
DMA address to the size of the window, since the range [0-window size]
may not be available. Such devices can find an available DMA region by
calling iommu_domain_get_lowest_free_address_range(), set up the memory
window, and request DMA address allocations in the found range by calling
dma_set_min_dma_addr() and dma_set_mask_and_coherent().
diff --git a/drivers/iommu/dma-iommu.c b/drivers/iommu/dma-iommu.c
index 414d31347fc2..077d1cd0939d 100644
--- a/drivers/iommu/dma-iommu.c
+++ b/drivers/iommu/dma-iommu.c
@@ -810,7 +810,7 @@ static dma_addr_t iommu_dma_alloc_iova(struct
iommu_domain *domain,
* expected address bits are wired up between the device and the IOMMU.
*/
if (dma_limit > DMA_BIT_MASK(32) && (size - 1) <=
DMA_BIT_MASK(32) && dev->iommu->pci_32bit_workaround) {
- iova = alloc_iova_fast(iovad, iova_len, 0,
+ iova = alloc_iova_fast(iovad, iova_len, dev->min_dma_addr,
DMA_BIT_MASK(32) >> shift, false, align);
if (iova)
goto done;
@@ -819,7 +819,7 @@ static dma_addr_t iommu_dma_alloc_iova(struct
iommu_domain *domain,
dev_notice(dev, "Using %d-bit DMA addresses\n", bits_per(dma_limit));
}
- iova = alloc_iova_fast(iovad, iova_len, 0, dma_limit >> shift,
true, align);
+ iova = alloc_iova_fast(iovad, iova_len, dev->min_dma_addr,
dma_limit >> shift, true, align);
done:
return (dma_addr_t)iova << shift;
}
diff --git a/include/linux/device.h b/include/linux/device.h
index 0470d19da7f2..339c9187b033 100644
--- a/include/linux/device.h
+++ b/include/linux/device.h
@@ -621,6 +621,7 @@ struct device {
64 bit addresses for consistent
allocations such descriptors. */
u64 bus_dma_limit; /* upstream dma constraint */
+ u64 min_dma_addr; /* force minimal value for DMA address */
const struct bus_dma_region *dma_range_map;
struct device_dma_parameters *dma_parms;
@@ -690,6 +691,8 @@ struct device {
#endif
};
+#define dma_set_min_dma_addr(__dev__, __val__) __dev__->min_dma_addr = __val__
+
/**
* struct device_link - Device link representation.
* @supplier: The device on the supplier end of the link.
--
----------------------------------------
Constantine Gavrilov
System Architect and Platform Engineer
Infinidat
----------------------------------------
Powered by blists - more mailing lists