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

drivers: flag buses which demand DMA configuration

We do not want the common dma_configure() pathway to apply
indiscriminately to all devices, since there are plenty of buses which
do not have DMA capability, and if their child devices were used for
DMA API calls it would only be indicative of a driver bug. However,
there are a number of buses for which DMA is implicitly expected even
when not described by firmware - those we whitelist with an automatic
opt-in to dma_configure(), assuming that the DMA address space and the
physical address space are equivalent if not otherwise specified.

Commit 723288836628 ("of: restrict DMA configuration") introduced a
short-term fix by comparing explicit bus types, but this approach is far
from pretty, doesn't scale well, and fails to cope at all with bus
drivers which may be built as modules, like host1x. Let's refine things
by making that opt-in a property of the bus type, which neatly addresses
those problems and lets the decision of whether firmware description of
DMA capability should be optional or mandatory stay internal to the bus
drivers themselves.

Signed-off-by: Robin Murphy <robin.murphy@arm.com>
Acked-by: Rob Herring <robh@kernel.org>
Acked-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Acked-by: Thierry Reding <treding@nvidia.com>
Signed-off-by: Christoph Hellwig <hch@lst.de>

authored by

Robin Murphy and committed by
Christoph Hellwig
d89e2378 33d930e5

+9 -7
+1
drivers/amba/bus.c
··· 195 195 .match = amba_match, 196 196 .uevent = amba_uevent, 197 197 .pm = &amba_pm, 198 + .force_dma = true, 198 199 }; 199 200 200 201 static int __init amba_init(void)
+1
drivers/base/platform.c
··· 1143 1143 .match = platform_match, 1144 1144 .uevent = platform_uevent, 1145 1145 .pm = &platform_dev_pm_ops, 1146 + .force_dma = true, 1146 1147 }; 1147 1148 EXPORT_SYMBOL_GPL(platform_bus_type); 1148 1149
+1
drivers/gpu/host1x/bus.c
··· 320 320 .name = "host1x", 321 321 .match = host1x_device_match, 322 322 .pm = &host1x_device_pm_ops, 323 + .force_dma = true, 323 324 }; 324 325 325 326 static void __host1x_device_del(struct host1x_device *device)
+1 -7
drivers/of/device.c
··· 9 9 #include <linux/module.h> 10 10 #include <linux/mod_devicetable.h> 11 11 #include <linux/slab.h> 12 - #include <linux/pci.h> 13 12 #include <linux/platform_device.h> 14 - #include <linux/amba/bus.h> 15 13 16 14 #include <asm/errno.h> 17 15 #include "of_private.h" ··· 99 101 * DMA configuration regardless of whether "dma-ranges" is 100 102 * correctly specified or not. 101 103 */ 102 - if (!dev_is_pci(dev) && 103 - #ifdef CONFIG_ARM_AMBA 104 - dev->bus != &amba_bustype && 105 - #endif 106 - dev->bus != &platform_bus_type) 104 + if (!dev->bus->force_dma) 107 105 return ret == -ENODEV ? 0 : ret; 108 106 109 107 dma_addr = offset = 0;
+1
drivers/pci/pci-driver.c
··· 1466 1466 .drv_groups = pci_drv_groups, 1467 1467 .pm = PCI_PM_OPS_PTR, 1468 1468 .num_vf = pci_bus_num_vf, 1469 + .force_dma = true, 1469 1470 }; 1470 1471 EXPORT_SYMBOL(pci_bus_type); 1471 1472
+4
include/linux/device.h
··· 97 97 * @p: The private data of the driver core, only the driver core can 98 98 * touch this. 99 99 * @lock_key: Lock class key for use by the lock validator 100 + * @force_dma: Assume devices on this bus should be set up by dma_configure() 101 + * even if DMA capability is not explicitly described by firmware. 100 102 * 101 103 * A bus is a channel between the processor and one or more devices. For the 102 104 * purposes of the device model, all devices are connected via a bus, even if ··· 137 135 138 136 struct subsys_private *p; 139 137 struct lock_class_key lock_key; 138 + 139 + bool force_dma; 140 140 }; 141 141 142 142 extern int __must_check bus_register(struct bus_type *bus);