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

dma-mapping: move dma configuration to bus infrastructure

ACPI/OF support for configuration of DMA is a bus specific aspect, and
thus should be configured by the bus. Introduces a 'dma_configure' bus
method so that busses can control their DMA capabilities.

Also update the PCI, Platform, ACPI and host1x buses to use the new
method.

Suggested-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: Nipun Gupta <nipun.gupta@nxp.com>
Acked-by: Bjorn Helgaas <bhelgaas@google.com> # PCI parts
Acked-by: Thierry Reding <treding@nvidia.com>
Reviewed-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
[hch: simplified host1x_dma_configure based on a comment from Thierry,
rewrote changelog]
Signed-off-by: Christoph Hellwig <hch@lst.de>

authored by

Nipun Gupta and committed by
Christoph Hellwig
07397df2 892a0be4

+69 -27
+4
drivers/amba/bus.c
··· 20 20 #include <linux/sizes.h> 21 21 #include <linux/limits.h> 22 22 #include <linux/clk/clk-conf.h> 23 + #include <linux/platform_device.h> 23 24 24 25 #include <asm/irq.h> 25 26 ··· 194 193 /* 195 194 * Primecells are part of the Advanced Microcontroller Bus Architecture, 196 195 * so we call the bus "amba". 196 + * DMA configuration for platform and AMBA bus is same. So here we reuse 197 + * platform's DMA config routine. 197 198 */ 198 199 struct bus_type amba_bustype = { 199 200 .name = "amba", 200 201 .dev_groups = amba_dev_groups, 201 202 .match = amba_match, 202 203 .uevent = amba_uevent, 204 + .dma_configure = platform_dma_configure, 203 205 .pm = &amba_pm, 204 206 .force_dma = true, 205 207 };
+4 -27
drivers/base/dma-mapping.c
··· 329 329 #endif 330 330 331 331 /* 332 - * Common configuration to enable DMA API use for a device 332 + * enables DMA API use for a device 333 333 */ 334 - #include <linux/pci.h> 335 - 336 334 int dma_configure(struct device *dev) 337 335 { 338 - struct device *bridge = NULL, *dma_dev = dev; 339 - enum dev_dma_attr attr; 340 - int ret = 0; 341 - 342 - if (dev_is_pci(dev)) { 343 - bridge = pci_get_host_bridge_device(to_pci_dev(dev)); 344 - dma_dev = bridge; 345 - if (IS_ENABLED(CONFIG_OF) && dma_dev->parent && 346 - dma_dev->parent->of_node) 347 - dma_dev = dma_dev->parent; 348 - } 349 - 350 - if (dma_dev->of_node) { 351 - ret = of_dma_configure(dev, dma_dev->of_node); 352 - } else if (has_acpi_companion(dma_dev)) { 353 - attr = acpi_get_dma_attr(to_acpi_device_node(dma_dev->fwnode)); 354 - if (attr != DEV_DMA_NOT_SUPPORTED) 355 - ret = acpi_dma_configure(dev, attr); 356 - } 357 - 358 - if (bridge) 359 - pci_put_host_bridge_device(bridge); 360 - 361 - return ret; 336 + if (dev->bus->dma_configure) 337 + return dev->bus->dma_configure(dev); 338 + return 0; 362 339 } 363 340 364 341 void dma_deconfigure(struct device *dev)
+17
drivers/base/platform.c
··· 1130 1130 1131 1131 #endif /* CONFIG_HIBERNATE_CALLBACKS */ 1132 1132 1133 + int platform_dma_configure(struct device *dev) 1134 + { 1135 + enum dev_dma_attr attr; 1136 + int ret = 0; 1137 + 1138 + if (dev->of_node) { 1139 + ret = of_dma_configure(dev, dev->of_node); 1140 + } else if (has_acpi_companion(dev)) { 1141 + attr = acpi_get_dma_attr(to_acpi_device_node(dev->fwnode)); 1142 + if (attr != DEV_DMA_NOT_SUPPORTED) 1143 + ret = acpi_dma_configure(dev, attr); 1144 + } 1145 + 1146 + return ret; 1147 + } 1148 + 1133 1149 static const struct dev_pm_ops platform_dev_pm_ops = { 1134 1150 .runtime_suspend = pm_generic_runtime_suspend, 1135 1151 .runtime_resume = pm_generic_runtime_resume, ··· 1157 1141 .dev_groups = platform_dev_groups, 1158 1142 .match = platform_match, 1159 1143 .uevent = platform_uevent, 1144 + .dma_configure = platform_dma_configure, 1160 1145 .pm = &platform_dev_pm_ops, 1161 1146 .force_dma = true, 1162 1147 };
+6
drivers/gpu/host1x/bus.c
··· 314 314 return strcmp(dev_name(dev), drv->name) == 0; 315 315 } 316 316 317 + static int host1x_dma_configure(struct device *dev) 318 + { 319 + return of_dma_configure(dev, dev->of_node); 320 + } 321 + 317 322 static const struct dev_pm_ops host1x_device_pm_ops = { 318 323 .suspend = pm_generic_suspend, 319 324 .resume = pm_generic_resume, ··· 331 326 struct bus_type host1x_bus_type = { 332 327 .name = "host1x", 333 328 .match = host1x_device_match, 329 + .dma_configure = host1x_dma_configure, 334 330 .pm = &host1x_device_pm_ops, 335 331 .force_dma = true, 336 332 };
+32
drivers/pci/pci-driver.c
··· 16 16 #include <linux/pm_runtime.h> 17 17 #include <linux/suspend.h> 18 18 #include <linux/kexec.h> 19 + #include <linux/of_device.h> 20 + #include <linux/acpi.h> 19 21 #include "pci.h" 20 22 #include "pcie/portdrv.h" 21 23 ··· 1579 1577 return pci_num_vf(to_pci_dev(dev)); 1580 1578 } 1581 1579 1580 + /** 1581 + * pci_dma_configure - Setup DMA configuration 1582 + * @dev: ptr to dev structure 1583 + * 1584 + * Function to update PCI devices's DMA configuration using the same 1585 + * info from the OF node or ACPI node of host bridge's parent (if any). 1586 + */ 1587 + static int pci_dma_configure(struct device *dev) 1588 + { 1589 + struct device *bridge; 1590 + int ret = 0; 1591 + 1592 + bridge = pci_get_host_bridge_device(to_pci_dev(dev)); 1593 + 1594 + if (IS_ENABLED(CONFIG_OF) && bridge->parent && 1595 + bridge->parent->of_node) { 1596 + ret = of_dma_configure(dev, bridge->parent->of_node); 1597 + } else if (has_acpi_companion(bridge)) { 1598 + struct acpi_device *adev = to_acpi_device_node(bridge->fwnode); 1599 + enum dev_dma_attr attr = acpi_get_dma_attr(adev); 1600 + 1601 + if (attr != DEV_DMA_NOT_SUPPORTED) 1602 + ret = acpi_dma_configure(dev, attr); 1603 + } 1604 + 1605 + pci_put_host_bridge_device(bridge); 1606 + return ret; 1607 + } 1608 + 1582 1609 struct bus_type pci_bus_type = { 1583 1610 .name = "pci", 1584 1611 .match = pci_bus_match, ··· 1620 1589 .drv_groups = pci_drv_groups, 1621 1590 .pm = PCI_PM_OPS_PTR, 1622 1591 .num_vf = pci_bus_num_vf, 1592 + .dma_configure = pci_dma_configure, 1623 1593 .force_dma = true, 1624 1594 }; 1625 1595 EXPORT_SYMBOL(pci_bus_type);
+4
include/linux/device.h
··· 88 88 * @resume: Called to bring a device on this bus out of sleep mode. 89 89 * @num_vf: Called to find out how many virtual functions a device on this 90 90 * bus supports. 91 + * @dma_configure: Called to setup DMA configuration on a device on 92 + this bus. 91 93 * @pm: Power management operations of this bus, callback the specific 92 94 * device driver's pm-ops. 93 95 * @iommu_ops: IOMMU specific operations for this bus, used to attach IOMMU ··· 131 129 int (*resume)(struct device *dev); 132 130 133 131 int (*num_vf)(struct device *dev); 132 + 133 + int (*dma_configure)(struct device *dev); 134 134 135 135 const struct dev_pm_ops *pm; 136 136
+2
include/linux/platform_device.h
··· 356 356 #define platform_pm_restore NULL 357 357 #endif 358 358 359 + extern int platform_dma_configure(struct device *dev); 360 + 359 361 #ifdef CONFIG_PM_SLEEP 360 362 #define USE_PLATFORM_PM_SLEEP_OPS \ 361 363 .suspend = platform_pm_suspend, \