Thread (11 messages) 11 messages, 4 authors, 2019-11-21

Re: [PATCH] dma-mapping: treat dev->bus_dma_mask as a DMA limit

From: Nicolas Saenz Julienne <hidden>
Date: 2019-11-14 09:47:10
Also in: linux-acpi, linux-arm-kernel, linux-devicetree, linux-iommu, linux-mips, linux-pci, linuxppc-dev, lkml

On Wed, 2019-11-13 at 20:34 +0000, Robin Murphy wrote:
On 13/11/2019 4:13 pm, Nicolas Saenz Julienne wrote:
quoted
Using a mask to represent bus DMA constraints has a set of limitations.
The biggest one being it can only hold a power of two (minus one). The
DMA mapping code is already aware of this and treats dev->bus_dma_mask
as a limit. This quirk is already used by some architectures although
still rare.

With the introduction of the Raspberry Pi 4 we've found a new contender
for the use of bus DMA limits, as its PCIe bus can only address the
lower 3GB of memory (of a total of 4GB). This is impossible to represent
with a mask. To make things worse the device-tree code rounds non power
of two bus DMA limits to the next power of two, which is unacceptable in
this case.

In the light of this, rename dev->bus_dma_mask to dev->bus_dma_limit all
over the tree and treat it as such. Note that dev->bus_dma_limit is
meant to contain the higher accesible DMA address.
Neat, you win a "why didn't I do it that way in the first place?" :)
:)
Looking at it without all the history of previous attempts, this looks 
entirely reasonable, and definitely a step in the right direction.

[...]
quoted
diff --git a/drivers/acpi/arm64/iort.c b/drivers/acpi/arm64/iort.c
index 5a7551d060f2..f18827cf96df 100644
--- a/drivers/acpi/arm64/iort.c
+++ b/drivers/acpi/arm64/iort.c
@@ -1097,7 +1097,7 @@ void iort_dma_setup(struct device *dev, u64 *dma_addr,
u64 *dma_size)
  		 * Limit coherent and dma mask based on size
  		 * retrieved from firmware.
  		 */
-		dev->bus_dma_mask = mask;
+		dev->bus_dma_limit = mask;
Although this preserves the existing behaviour, as in of_dma_configure() 
we can do better here since we have the original address range to hand. 
I think it's worth keeping the ACPI and OF paths in sync for minor 
tweaks like this, rather than letting them diverge unnecessarily.
I figure you mean something like this:
@@ -1085,19 +1085,15 @@ void iort_dma_setup(struct device *dev, u64 *dma_addr,
u64 *dma_size)
        }

        if (!ret) {
-               msb = fls64(dmaaddr + size - 1);
-               /*
-                * Round-up to the power-of-two mask or set
-                * the mask to the whole 64-bit address space
-                * in case the DMA region covers the full
-                * memory window.
-                */
-               mask = msb == 64 ? U64_MAX : (1ULL << msb) - 1;
+               /* Round-up to the power-of-two */
+               end = dmaddr + size - 1;
+               mask = DMA_BIT_MASK(ilog2(end) + 1);
+
                /*
                 * Limit coherent and dma mask based on size
                 * retrieved from firmware.
                 */
-               dev->bus_dma_limit = mask;
+               dev->bus_dma_limit = end;
                dev->coherent_dma_mask = mask;
                *dev->dma_mask = mask;
        }
Otherwise, the rest looks OK to me - in principle we could store it as 
an exclusive limit such that we could then streamline the min_not_zero() 
tests to just min(mask, limit - 1), but that's probably too clever for 
its own good.
Yes, that was my first intuition and in a perfect world I'd prefer it like
that. But as you say, it's probably going to cause more trouble than anything.

Regards,
Nicolas

Attachments

Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help