Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

of/device: Update dma_range_map only when dev has valid dma-ranges

The commit e0d072782c73 ("dma-mapping: introduce DMA range map,
supplanting dma_pfn_offset") always update dma_range_map even though it was
already set, like in the sunxi_mbus driver. the issue is reported at [1].
This patch avoid this(Updating it only when dev has valid dma-ranges).

Meanwhile, dma_range_map contains the devices' dma_ranges information,
This patch moves dma_range_map before of_iommu_configure. The iommu
driver may need to know the dma_address requirements of its iommu
consumer devices.

[1] https://lore.kernel.org/linux-arm-kernel/5c7946f3-b56e-da00-a750-be097c7ceb32@arm.com/

CC: Frank Rowand <frowand.list@gmail.com>
Fixes: e0d072782c73 ("dma-mapping: introduce DMA range map, supplanting dma_pfn_offset"),
Suggested-by: Robin Murphy <robin.murphy@arm.com>
Signed-off-by: Yong Wu <yong.wu@mediatek.com>
Signed-off-by: Paul Kocialkowski <paul.kocialkowski@bootlin.com>
Reviewed-by: Rob Herring <robh@kernel.org>
Reviewed-by: Robin Murphy <robin.murphy@arm.com>
Signed-off-by: Rob Herring <robh@kernel.org>
Link: https://lore.kernel.org/r/20210119105203.15530-1-yong.wu@mediatek.com

authored by

Yong Wu and committed by
Rob Herring
89c7cb16 30596ae0

+7 -3
+7 -3
drivers/of/device.c
··· 162 162 mask = DMA_BIT_MASK(ilog2(end) + 1); 163 163 dev->coherent_dma_mask &= mask; 164 164 *dev->dma_mask &= mask; 165 - /* ...but only set bus limit if we found valid dma-ranges earlier */ 166 - if (!ret) 165 + /* ...but only set bus limit and range map if we found valid dma-ranges earlier */ 166 + if (!ret) { 167 167 dev->bus_dma_limit = end; 168 + dev->dma_range_map = map; 169 + } 168 170 169 171 coherent = of_dma_is_coherent(np); 170 172 dev_dbg(dev, "device is%sdma coherent\n", ··· 174 172 175 173 iommu = of_iommu_configure(dev, np, id); 176 174 if (PTR_ERR(iommu) == -EPROBE_DEFER) { 175 + /* Don't touch range map if it wasn't set from a valid dma-ranges */ 176 + if (!ret) 177 + dev->dma_range_map = NULL; 177 178 kfree(map); 178 179 return -EPROBE_DEFER; 179 180 } ··· 186 181 187 182 arch_setup_dma_ops(dev, dma_start, size, iommu, coherent); 188 183 189 - dev->dma_range_map = map; 190 184 return 0; 191 185 } 192 186 EXPORT_SYMBOL_GPL(of_dma_configure_id);