Thread (1 message) 1 message, 1 author, 2017-03-22

[PATCH] of: Fix DMA mask assignment

From: robh+dt@kernel.org (Rob Herring)
Date: 2017-03-22 15:19:58
Also in: linux-devicetree

On Tue, Mar 7, 2017 at 12:12 PM, Robin Murphy [off-list ref] wrote:
As we start moving towards mandating that device DMA addressing
capabilities are correctly described in DT for platforms like arm64,
Why? There's no point to dma-ranges if the bus is not restricting the
device. dma-ranges is supposed to apply to a bus, not a device. For
example, using dma-ranges for a 32-bit device on a 64-bit platform is
wrong. To put it another way, devices know their addressing
capability, so we don't need to describe that in DT, only external
restrictions outside of the device.
it
turns out that actually assigning DMA masks wider than 32 bits from
"dma-ranges" is made largely impossible by the current code. New PCI
devices are passed in with 32-bit masks, while new platform devices are
passed in with their masks unset, so we install default 32-bit masks for
them. As a result, subsequently taking the minimum between any existing
mask and the size given by "dma-ranges" means that we can never exceed
32 bits for the vast majority of devices.

Since the DT can be assumed to describe the hardware appropriately, and
the device's driver is expected by the DMA API to explicitly set a mask
later when it probes, we can safely let "dma-ranges" unconditionally
override any initial mask from device creation (and as a small bonus
deduplicate the calculation in the process).

CC: Arnd Bergmann <arnd@arndb.de>
CC: Murali Karicheri <redacted>
Fixes: 9a6d7298b083 ("of: Calculate device DMA masks based on DT dma-range size")
Changing behavior since 4.1 doesn't really seem like a fix. A fix
should generally be tagged for stable and I'd be nervous on this one.

Are we sure all the things a driver may do still work the same? A
driver changing the default 32-bit mask to a 64-bit mask for example.
quoted hunk
Signed-off-by: Robin Murphy <robin.murphy@arm.com>
---
 drivers/of/device.c | 11 ++---------
 1 file changed, 2 insertions(+), 9 deletions(-)
diff --git a/drivers/of/device.c b/drivers/of/device.c
index b1e6bebda3f3..9bb8518b28f2 100644
--- a/drivers/of/device.c
+++ b/drivers/of/device.c
@@ -129,15 +129,8 @@ void of_dma_configure(struct device *dev, struct device_node *np)
        }

        dev->dma_pfn_offset = offset;
-
-       /*
-        * Limit coherent and dma mask based on size and default mask
-        * set by the driver.
-        */
-       dev->coherent_dma_mask = min(dev->coherent_dma_mask,
-                                    DMA_BIT_MASK(ilog2(dma_addr + size)));
-       *dev->dma_mask = min((*dev->dma_mask),
-                            DMA_BIT_MASK(ilog2(dma_addr + size)));
+       dev->coherent_dma_mask = DMA_BIT_MASK(ilog2(dma_addr + size));
+       *dev->dma_mask = dev->coherent_dma_mask;

        coherent = of_dma_is_coherent(np);
        dev_dbg(dev, "device is%sdma coherent\n",
--
2.11.0.dirty
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help