diff options
author | Nipun Gupta <nipun.gupta@nxp.com> | 2018-04-27 22:51:58 -0400 |
---|---|---|
committer | Christoph Hellwig <hch@lst.de> | 2018-05-03 10:22:18 -0400 |
commit | 07397df29e57cde5799af16e8f148ae10ed75285 (patch) | |
tree | 7f4e2606ec8d6a26a5433cb4dac32338178092fd | |
parent | 892a0be43edd63e1cd228af3453a064e9e94f08e (diff) |
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>
-rw-r--r-- | drivers/amba/bus.c | 4 | ||||
-rw-r--r-- | drivers/base/dma-mapping.c | 31 | ||||
-rw-r--r-- | drivers/base/platform.c | 17 | ||||
-rw-r--r-- | drivers/gpu/host1x/bus.c | 6 | ||||
-rw-r--r-- | drivers/pci/pci-driver.c | 32 | ||||
-rw-r--r-- | include/linux/device.h | 4 | ||||
-rw-r--r-- | include/linux/platform_device.h | 2 |
7 files changed, 69 insertions, 27 deletions
diff --git a/drivers/amba/bus.c b/drivers/amba/bus.c index 4a3ac31c07d0..b1f41f7d8eeb 100644 --- a/drivers/amba/bus.c +++ b/drivers/amba/bus.c | |||
@@ -20,6 +20,7 @@ | |||
20 | #include <linux/sizes.h> | 20 | #include <linux/sizes.h> |
21 | #include <linux/limits.h> | 21 | #include <linux/limits.h> |
22 | #include <linux/clk/clk-conf.h> | 22 | #include <linux/clk/clk-conf.h> |
23 | #include <linux/platform_device.h> | ||
23 | 24 | ||
24 | #include <asm/irq.h> | 25 | #include <asm/irq.h> |
25 | 26 | ||
@@ -193,12 +194,15 @@ static const struct dev_pm_ops amba_pm = { | |||
193 | /* | 194 | /* |
194 | * Primecells are part of the Advanced Microcontroller Bus Architecture, | 195 | * Primecells are part of the Advanced Microcontroller Bus Architecture, |
195 | * so we call the bus "amba". | 196 | * so we call the bus "amba". |
197 | * DMA configuration for platform and AMBA bus is same. So here we reuse | ||
198 | * platform's DMA config routine. | ||
196 | */ | 199 | */ |
197 | struct bus_type amba_bustype = { | 200 | struct bus_type amba_bustype = { |
198 | .name = "amba", | 201 | .name = "amba", |
199 | .dev_groups = amba_dev_groups, | 202 | .dev_groups = amba_dev_groups, |
200 | .match = amba_match, | 203 | .match = amba_match, |
201 | .uevent = amba_uevent, | 204 | .uevent = amba_uevent, |
205 | .dma_configure = platform_dma_configure, | ||
202 | .pm = &amba_pm, | 206 | .pm = &amba_pm, |
203 | .force_dma = true, | 207 | .force_dma = true, |
204 | }; | 208 | }; |
diff --git a/drivers/base/dma-mapping.c b/drivers/base/dma-mapping.c index d82566d6e237..f831a582209c 100644 --- a/drivers/base/dma-mapping.c +++ b/drivers/base/dma-mapping.c | |||
@@ -329,36 +329,13 @@ void dma_common_free_remap(void *cpu_addr, size_t size, unsigned long vm_flags) | |||
329 | #endif | 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 | int dma_configure(struct device *dev) | 334 | int dma_configure(struct device *dev) |
337 | { | 335 | { |
338 | struct device *bridge = NULL, *dma_dev = dev; | 336 | if (dev->bus->dma_configure) |
339 | enum dev_dma_attr attr; | 337 | return dev->bus->dma_configure(dev); |
340 | int ret = 0; | 338 | return 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; | ||
362 | } | 339 | } |
363 | 340 | ||
364 | void dma_deconfigure(struct device *dev) | 341 | void dma_deconfigure(struct device *dev) |
diff --git a/drivers/base/platform.c b/drivers/base/platform.c index 8075ddc70a17..638d42e93772 100644 --- a/drivers/base/platform.c +++ b/drivers/base/platform.c | |||
@@ -1130,6 +1130,22 @@ int platform_pm_restore(struct device *dev) | |||
1130 | 1130 | ||
1131 | #endif /* CONFIG_HIBERNATE_CALLBACKS */ | 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 | static const struct dev_pm_ops platform_dev_pm_ops = { | 1149 | static const struct dev_pm_ops platform_dev_pm_ops = { |
1134 | .runtime_suspend = pm_generic_runtime_suspend, | 1150 | .runtime_suspend = pm_generic_runtime_suspend, |
1135 | .runtime_resume = pm_generic_runtime_resume, | 1151 | .runtime_resume = pm_generic_runtime_resume, |
@@ -1141,6 +1157,7 @@ struct bus_type platform_bus_type = { | |||
1141 | .dev_groups = platform_dev_groups, | 1157 | .dev_groups = platform_dev_groups, |
1142 | .match = platform_match, | 1158 | .match = platform_match, |
1143 | .uevent = platform_uevent, | 1159 | .uevent = platform_uevent, |
1160 | .dma_configure = platform_dma_configure, | ||
1144 | .pm = &platform_dev_pm_ops, | 1161 | .pm = &platform_dev_pm_ops, |
1145 | .force_dma = true, | 1162 | .force_dma = true, |
1146 | }; | 1163 | }; |
diff --git a/drivers/gpu/host1x/bus.c b/drivers/gpu/host1x/bus.c index 88a3558b7916..0c79bafae96c 100644 --- a/drivers/gpu/host1x/bus.c +++ b/drivers/gpu/host1x/bus.c | |||
@@ -314,6 +314,11 @@ static int host1x_device_match(struct device *dev, struct device_driver *drv) | |||
314 | return strcmp(dev_name(dev), drv->name) == 0; | 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 | static const struct dev_pm_ops host1x_device_pm_ops = { | 322 | static const struct dev_pm_ops host1x_device_pm_ops = { |
318 | .suspend = pm_generic_suspend, | 323 | .suspend = pm_generic_suspend, |
319 | .resume = pm_generic_resume, | 324 | .resume = pm_generic_resume, |
@@ -326,6 +331,7 @@ static const struct dev_pm_ops host1x_device_pm_ops = { | |||
326 | struct bus_type host1x_bus_type = { | 331 | struct bus_type host1x_bus_type = { |
327 | .name = "host1x", | 332 | .name = "host1x", |
328 | .match = host1x_device_match, | 333 | .match = host1x_device_match, |
334 | .dma_configure = host1x_dma_configure, | ||
329 | .pm = &host1x_device_pm_ops, | 335 | .pm = &host1x_device_pm_ops, |
330 | .force_dma = true, | 336 | .force_dma = true, |
331 | }; | 337 | }; |
diff --git a/drivers/pci/pci-driver.c b/drivers/pci/pci-driver.c index b9a131137e64..ba8c6b46269e 100644 --- a/drivers/pci/pci-driver.c +++ b/drivers/pci/pci-driver.c | |||
@@ -16,6 +16,8 @@ | |||
16 | #include <linux/pm_runtime.h> | 16 | #include <linux/pm_runtime.h> |
17 | #include <linux/suspend.h> | 17 | #include <linux/suspend.h> |
18 | #include <linux/kexec.h> | 18 | #include <linux/kexec.h> |
19 | #include <linux/of_device.h> | ||
20 | #include <linux/acpi.h> | ||
19 | #include "pci.h" | 21 | #include "pci.h" |
20 | #include "pcie/portdrv.h" | 22 | #include "pcie/portdrv.h" |
21 | 23 | ||
@@ -1577,6 +1579,35 @@ static int pci_bus_num_vf(struct device *dev) | |||
1577 | return pci_num_vf(to_pci_dev(dev)); | 1579 | return pci_num_vf(to_pci_dev(dev)); |
1578 | } | 1580 | } |
1579 | 1581 | ||
1582 | /** | ||
1583 | * pci_dma_configure - Setup DMA configuration | ||
1584 | * @dev: ptr to dev structure | ||
1585 | * | ||
1586 | * Function to update PCI devices's DMA configuration using the same | ||
1587 | * info from the OF node or ACPI node of host bridge's parent (if any). | ||
1588 | */ | ||
1589 | static int pci_dma_configure(struct device *dev) | ||
1590 | { | ||
1591 | struct device *bridge; | ||
1592 | int ret = 0; | ||
1593 | |||
1594 | bridge = pci_get_host_bridge_device(to_pci_dev(dev)); | ||
1595 | |||
1596 | if (IS_ENABLED(CONFIG_OF) && bridge->parent && | ||
1597 | bridge->parent->of_node) { | ||
1598 | ret = of_dma_configure(dev, bridge->parent->of_node); | ||
1599 | } else if (has_acpi_companion(bridge)) { | ||
1600 | struct acpi_device *adev = to_acpi_device_node(bridge->fwnode); | ||
1601 | enum dev_dma_attr attr = acpi_get_dma_attr(adev); | ||
1602 | |||
1603 | if (attr != DEV_DMA_NOT_SUPPORTED) | ||
1604 | ret = acpi_dma_configure(dev, attr); | ||
1605 | } | ||
1606 | |||
1607 | pci_put_host_bridge_device(bridge); | ||
1608 | return ret; | ||
1609 | } | ||
1610 | |||
1580 | struct bus_type pci_bus_type = { | 1611 | struct bus_type pci_bus_type = { |
1581 | .name = "pci", | 1612 | .name = "pci", |
1582 | .match = pci_bus_match, | 1613 | .match = pci_bus_match, |
@@ -1589,6 +1620,7 @@ struct bus_type pci_bus_type = { | |||
1589 | .drv_groups = pci_drv_groups, | 1620 | .drv_groups = pci_drv_groups, |
1590 | .pm = PCI_PM_OPS_PTR, | 1621 | .pm = PCI_PM_OPS_PTR, |
1591 | .num_vf = pci_bus_num_vf, | 1622 | .num_vf = pci_bus_num_vf, |
1623 | .dma_configure = pci_dma_configure, | ||
1592 | .force_dma = true, | 1624 | .force_dma = true, |
1593 | }; | 1625 | }; |
1594 | EXPORT_SYMBOL(pci_bus_type); | 1626 | EXPORT_SYMBOL(pci_bus_type); |
diff --git a/include/linux/device.h b/include/linux/device.h index 477956990f5e..63aa672bd394 100644 --- a/include/linux/device.h +++ b/include/linux/device.h | |||
@@ -88,6 +88,8 @@ extern void bus_remove_file(struct bus_type *, struct bus_attribute *); | |||
88 | * @resume: Called to bring a device on this bus out of sleep mode. | 88 | * @resume: Called to bring a device on this bus out of sleep mode. |
89 | * @num_vf: Called to find out how many virtual functions a device on this | 89 | * @num_vf: Called to find out how many virtual functions a device on this |
90 | * bus supports. | 90 | * bus supports. |
91 | * @dma_configure: Called to setup DMA configuration on a device on | ||
92 | this bus. | ||
91 | * @pm: Power management operations of this bus, callback the specific | 93 | * @pm: Power management operations of this bus, callback the specific |
92 | * device driver's pm-ops. | 94 | * device driver's pm-ops. |
93 | * @iommu_ops: IOMMU specific operations for this bus, used to attach IOMMU | 95 | * @iommu_ops: IOMMU specific operations for this bus, used to attach IOMMU |
@@ -130,6 +132,8 @@ struct bus_type { | |||
130 | 132 | ||
131 | int (*num_vf)(struct device *dev); | 133 | int (*num_vf)(struct device *dev); |
132 | 134 | ||
135 | int (*dma_configure)(struct device *dev); | ||
136 | |||
133 | const struct dev_pm_ops *pm; | 137 | const struct dev_pm_ops *pm; |
134 | 138 | ||
135 | const struct iommu_ops *iommu_ops; | 139 | const struct iommu_ops *iommu_ops; |
diff --git a/include/linux/platform_device.h b/include/linux/platform_device.h index 49f634d96118..3097c943fab9 100644 --- a/include/linux/platform_device.h +++ b/include/linux/platform_device.h | |||
@@ -356,6 +356,8 @@ extern int platform_pm_restore(struct device *dev); | |||
356 | #define platform_pm_restore NULL | 356 | #define platform_pm_restore NULL |
357 | #endif | 357 | #endif |
358 | 358 | ||
359 | extern int platform_dma_configure(struct device *dev); | ||
360 | |||
359 | #ifdef CONFIG_PM_SLEEP | 361 | #ifdef CONFIG_PM_SLEEP |
360 | #define USE_PLATFORM_PM_SLEEP_OPS \ | 362 | #define USE_PLATFORM_PM_SLEEP_OPS \ |
361 | .suspend = platform_pm_suspend, \ | 363 | .suspend = platform_pm_suspend, \ |