aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSricharan R <sricharan@codeaurora.org>2017-04-10 07:21:01 -0400
committerJoerg Roedel <jroedel@suse.de>2017-04-20 10:31:06 -0400
commit09515ef5ddad71c7820e5e428da418b709feeb26 (patch)
tree3786792035e575e806a629cbf02ac3c96f5ebe53
parentefc8551a276faab19d85079da02c5fb602b0dcbe (diff)
of/acpi: Configure dma operations at probe time for platform/amba/pci bus devices
Configuring DMA ops at probe time will allow deferring device probe when the IOMMU isn't available yet. The dma_configure for the device is now called from the generic device_attach callback just before the bus/driver probe is called. This way, configuring the DMA ops for the device would be called at the same place for all bus_types, hence the deferred probing mechanism should work for all buses as well. pci_bus_add_devices (platform/amba)(_device_create/driver_register) | | pci_bus_add_device (device_add/driver_register) | | device_attach device_initial_probe | | __device_attach_driver __device_attach_driver | driver_probe_device | really_probe | dma_configure Similarly on the device/driver_unregister path __device_release_driver is called which inturn calls dma_deconfigure. This patch changes the dma ops configuration to probe time for both OF and ACPI based platform/amba/pci bus devices. Tested-by: Marek Szyprowski <m.szyprowski@samsung.com> Tested-by: Hanjun Guo <hanjun.guo@linaro.org> Reviewed-by: Robin Murphy <robin.murphy@arm.com> Acked-by: Rob Herring <robh@kernel.org> Acked-by: Bjorn Helgaas <bhelgaas@google.com> (drivers/pci part) Acked-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com> Signed-off-by: Sricharan R <sricharan@codeaurora.org> Signed-off-by: Joerg Roedel <jroedel@suse.de>
-rw-r--r--drivers/acpi/glue.c5
-rw-r--r--drivers/base/dd.c9
-rw-r--r--drivers/base/dma-mapping.c40
-rw-r--r--drivers/of/platform.c5
-rw-r--r--drivers/pci/probe.c28
-rw-r--r--include/linux/dma-mapping.h12
6 files changed, 62 insertions, 37 deletions
diff --git a/drivers/acpi/glue.c b/drivers/acpi/glue.c
index fb19e1cdb641..c05f24107bfc 100644
--- a/drivers/acpi/glue.c
+++ b/drivers/acpi/glue.c
@@ -176,7 +176,6 @@ int acpi_bind_one(struct device *dev, struct acpi_device *acpi_dev)
176 struct list_head *physnode_list; 176 struct list_head *physnode_list;
177 unsigned int node_id; 177 unsigned int node_id;
178 int retval = -EINVAL; 178 int retval = -EINVAL;
179 enum dev_dma_attr attr;
180 179
181 if (has_acpi_companion(dev)) { 180 if (has_acpi_companion(dev)) {
182 if (acpi_dev) { 181 if (acpi_dev) {
@@ -233,10 +232,6 @@ int acpi_bind_one(struct device *dev, struct acpi_device *acpi_dev)
233 if (!has_acpi_companion(dev)) 232 if (!has_acpi_companion(dev))
234 ACPI_COMPANION_SET(dev, acpi_dev); 233 ACPI_COMPANION_SET(dev, acpi_dev);
235 234
236 attr = acpi_get_dma_attr(acpi_dev);
237 if (attr != DEV_DMA_NOT_SUPPORTED)
238 acpi_dma_configure(dev, attr);
239
240 acpi_physnode_link_name(physical_node_name, node_id); 235 acpi_physnode_link_name(physical_node_name, node_id);
241 retval = sysfs_create_link(&acpi_dev->dev.kobj, &dev->kobj, 236 retval = sysfs_create_link(&acpi_dev->dev.kobj, &dev->kobj,
242 physical_node_name); 237 physical_node_name);
diff --git a/drivers/base/dd.c b/drivers/base/dd.c
index a1fbf55c4d3a..4882f06d12df 100644
--- a/drivers/base/dd.c
+++ b/drivers/base/dd.c
@@ -19,6 +19,7 @@
19 19
20#include <linux/device.h> 20#include <linux/device.h>
21#include <linux/delay.h> 21#include <linux/delay.h>
22#include <linux/dma-mapping.h>
22#include <linux/module.h> 23#include <linux/module.h>
23#include <linux/kthread.h> 24#include <linux/kthread.h>
24#include <linux/wait.h> 25#include <linux/wait.h>
@@ -356,6 +357,10 @@ re_probe:
356 if (ret) 357 if (ret)
357 goto pinctrl_bind_failed; 358 goto pinctrl_bind_failed;
358 359
360 ret = dma_configure(dev);
361 if (ret)
362 goto dma_failed;
363
359 if (driver_sysfs_add(dev)) { 364 if (driver_sysfs_add(dev)) {
360 printk(KERN_ERR "%s: driver_sysfs_add(%s) failed\n", 365 printk(KERN_ERR "%s: driver_sysfs_add(%s) failed\n",
361 __func__, dev_name(dev)); 366 __func__, dev_name(dev));
@@ -417,6 +422,8 @@ re_probe:
417 goto done; 422 goto done;
418 423
419probe_failed: 424probe_failed:
425 dma_deconfigure(dev);
426dma_failed:
420 if (dev->bus) 427 if (dev->bus)
421 blocking_notifier_call_chain(&dev->bus->p->bus_notifier, 428 blocking_notifier_call_chain(&dev->bus->p->bus_notifier,
422 BUS_NOTIFY_DRIVER_NOT_BOUND, dev); 429 BUS_NOTIFY_DRIVER_NOT_BOUND, dev);
@@ -826,6 +833,8 @@ static void __device_release_driver(struct device *dev, struct device *parent)
826 drv->remove(dev); 833 drv->remove(dev);
827 834
828 device_links_driver_cleanup(dev); 835 device_links_driver_cleanup(dev);
836 dma_deconfigure(dev);
837
829 devres_release_all(dev); 838 devres_release_all(dev);
830 dev->driver = NULL; 839 dev->driver = NULL;
831 dev_set_drvdata(dev, NULL); 840 dev_set_drvdata(dev, NULL);
diff --git a/drivers/base/dma-mapping.c b/drivers/base/dma-mapping.c
index efd71cf4fdea..449b948c7427 100644
--- a/drivers/base/dma-mapping.c
+++ b/drivers/base/dma-mapping.c
@@ -7,9 +7,11 @@
7 * This file is released under the GPLv2. 7 * This file is released under the GPLv2.
8 */ 8 */
9 9
10#include <linux/acpi.h>
10#include <linux/dma-mapping.h> 11#include <linux/dma-mapping.h>
11#include <linux/export.h> 12#include <linux/export.h>
12#include <linux/gfp.h> 13#include <linux/gfp.h>
14#include <linux/of_device.h>
13#include <linux/slab.h> 15#include <linux/slab.h>
14#include <linux/vmalloc.h> 16#include <linux/vmalloc.h>
15 17
@@ -341,3 +343,41 @@ void dma_common_free_remap(void *cpu_addr, size_t size, unsigned long vm_flags)
341 vunmap(cpu_addr); 343 vunmap(cpu_addr);
342} 344}
343#endif 345#endif
346
347/*
348 * Common configuration to enable DMA API use for a device
349 */
350#include <linux/pci.h>
351
352int dma_configure(struct device *dev)
353{
354 struct device *bridge = NULL, *dma_dev = dev;
355 enum dev_dma_attr attr;
356
357 if (dev_is_pci(dev)) {
358 bridge = pci_get_host_bridge_device(to_pci_dev(dev));
359 dma_dev = bridge;
360 if (IS_ENABLED(CONFIG_OF) && dma_dev->parent &&
361 dma_dev->parent->of_node)
362 dma_dev = dma_dev->parent;
363 }
364
365 if (dma_dev->of_node) {
366 of_dma_configure(dev, dma_dev->of_node);
367 } else if (has_acpi_companion(dma_dev)) {
368 attr = acpi_get_dma_attr(to_acpi_device_node(dma_dev->fwnode));
369 if (attr != DEV_DMA_NOT_SUPPORTED)
370 acpi_dma_configure(dev, attr);
371 }
372
373 if (bridge)
374 pci_put_host_bridge_device(bridge);
375
376 return 0;
377}
378
379void dma_deconfigure(struct device *dev)
380{
381 of_dma_deconfigure(dev);
382 acpi_dma_deconfigure(dev);
383}
diff --git a/drivers/of/platform.c b/drivers/of/platform.c
index 5344db50aa65..2aa4ebbde9cd 100644
--- a/drivers/of/platform.c
+++ b/drivers/of/platform.c
@@ -22,6 +22,7 @@
22#include <linux/slab.h> 22#include <linux/slab.h>
23#include <linux/of_address.h> 23#include <linux/of_address.h>
24#include <linux/of_device.h> 24#include <linux/of_device.h>
25#include <linux/of_iommu.h>
25#include <linux/of_irq.h> 26#include <linux/of_irq.h>
26#include <linux/of_platform.h> 27#include <linux/of_platform.h>
27#include <linux/platform_device.h> 28#include <linux/platform_device.h>
@@ -186,11 +187,9 @@ static struct platform_device *of_platform_device_create_pdata(
186 187
187 dev->dev.bus = &platform_bus_type; 188 dev->dev.bus = &platform_bus_type;
188 dev->dev.platform_data = platform_data; 189 dev->dev.platform_data = platform_data;
189 of_dma_configure(&dev->dev, dev->dev.of_node);
190 of_msi_configure(&dev->dev, dev->dev.of_node); 190 of_msi_configure(&dev->dev, dev->dev.of_node);
191 191
192 if (of_device_add(dev) != 0) { 192 if (of_device_add(dev) != 0) {
193 of_dma_deconfigure(&dev->dev);
194 platform_device_put(dev); 193 platform_device_put(dev);
195 goto err_clear_flag; 194 goto err_clear_flag;
196 } 195 }
@@ -248,7 +247,6 @@ static struct amba_device *of_amba_device_create(struct device_node *node,
248 dev_set_name(&dev->dev, "%s", bus_id); 247 dev_set_name(&dev->dev, "%s", bus_id);
249 else 248 else
250 of_device_make_bus_id(&dev->dev); 249 of_device_make_bus_id(&dev->dev);
251 of_dma_configure(&dev->dev, dev->dev.of_node);
252 250
253 /* Allow the HW Peripheral ID to be overridden */ 251 /* Allow the HW Peripheral ID to be overridden */
254 prop = of_get_property(node, "arm,primecell-periphid", NULL); 252 prop = of_get_property(node, "arm,primecell-periphid", NULL);
@@ -542,7 +540,6 @@ static int of_platform_device_destroy(struct device *dev, void *data)
542 amba_device_unregister(to_amba_device(dev)); 540 amba_device_unregister(to_amba_device(dev));
543#endif 541#endif
544 542
545 of_dma_deconfigure(dev);
546 of_node_clear_flag(dev->of_node, OF_POPULATED); 543 of_node_clear_flag(dev->of_node, OF_POPULATED);
547 of_node_clear_flag(dev->of_node, OF_POPULATED_BUS); 544 of_node_clear_flag(dev->of_node, OF_POPULATED_BUS);
548 return 0; 545 return 0;
diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c
index dfc9a2794141..5a8dd43db336 100644
--- a/drivers/pci/probe.c
+++ b/drivers/pci/probe.c
@@ -1893,33 +1893,6 @@ static void pci_set_msi_domain(struct pci_dev *dev)
1893 dev_set_msi_domain(&dev->dev, d); 1893 dev_set_msi_domain(&dev->dev, d);
1894} 1894}
1895 1895
1896/**
1897 * pci_dma_configure - Setup DMA configuration
1898 * @dev: ptr to pci_dev struct of the PCI device
1899 *
1900 * Function to update PCI devices's DMA configuration using the same
1901 * info from the OF node or ACPI node of host bridge's parent (if any).
1902 */
1903static void pci_dma_configure(struct pci_dev *dev)
1904{
1905 struct device *bridge = pci_get_host_bridge_device(dev);
1906
1907 if (IS_ENABLED(CONFIG_OF) &&
1908 bridge->parent && bridge->parent->of_node) {
1909 of_dma_configure(&dev->dev, bridge->parent->of_node);
1910 } else if (has_acpi_companion(bridge)) {
1911 struct acpi_device *adev = to_acpi_device_node(bridge->fwnode);
1912 enum dev_dma_attr attr = acpi_get_dma_attr(adev);
1913
1914 if (attr == DEV_DMA_NOT_SUPPORTED)
1915 dev_warn(&dev->dev, "DMA not supported.\n");
1916 else
1917 acpi_dma_configure(&dev->dev, attr);
1918 }
1919
1920 pci_put_host_bridge_device(bridge);
1921}
1922
1923void pci_device_add(struct pci_dev *dev, struct pci_bus *bus) 1896void pci_device_add(struct pci_dev *dev, struct pci_bus *bus)
1924{ 1897{
1925 int ret; 1898 int ret;
@@ -1933,7 +1906,6 @@ void pci_device_add(struct pci_dev *dev, struct pci_bus *bus)
1933 dev->dev.dma_mask = &dev->dma_mask; 1906 dev->dev.dma_mask = &dev->dma_mask;
1934 dev->dev.dma_parms = &dev->dma_parms; 1907 dev->dev.dma_parms = &dev->dma_parms;
1935 dev->dev.coherent_dma_mask = 0xffffffffull; 1908 dev->dev.coherent_dma_mask = 0xffffffffull;
1936 pci_dma_configure(dev);
1937 1909
1938 pci_set_dma_max_seg_size(dev, 65536); 1910 pci_set_dma_max_seg_size(dev, 65536);
1939 pci_set_dma_seg_boundary(dev, 0xffffffff); 1911 pci_set_dma_seg_boundary(dev, 0xffffffff);
diff --git a/include/linux/dma-mapping.h b/include/linux/dma-mapping.h
index 0977317c6835..4f3eecedca2d 100644
--- a/include/linux/dma-mapping.h
+++ b/include/linux/dma-mapping.h
@@ -728,6 +728,18 @@ dma_mark_declared_memory_occupied(struct device *dev,
728} 728}
729#endif /* CONFIG_HAVE_GENERIC_DMA_COHERENT */ 729#endif /* CONFIG_HAVE_GENERIC_DMA_COHERENT */
730 730
731#ifdef CONFIG_HAS_DMA
732int dma_configure(struct device *dev);
733void dma_deconfigure(struct device *dev);
734#else
735static inline int dma_configure(struct device *dev)
736{
737 return 0;
738}
739
740static inline void dma_deconfigure(struct device *dev) {}
741#endif
742
731/* 743/*
732 * Managed DMA API 744 * Managed DMA API
733 */ 745 */