Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 07397df2 authored by Nipun Gupta's avatar Nipun Gupta Committed by Christoph Hellwig
Browse files

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: default avatarChristoph Hellwig <hch@lst.de>
Signed-off-by: default avatarNipun Gupta <nipun.gupta@nxp.com>
Acked-by: Bjorn Helgaas <bhelgaas@google.com>  # PCI parts
Acked-by: default avatarThierry Reding <treding@nvidia.com>
Reviewed-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
[hch: simplified host1x_dma_configure based on a comment from Thierry,
      rewrote changelog]
Signed-off-by: default avatarChristoph Hellwig <hch@lst.de>
parent 892a0be4
Loading
Loading
Loading
Loading
+4 −0
Original line number Diff line number Diff line
@@ -20,6 +20,7 @@
#include <linux/sizes.h>
#include <linux/limits.h>
#include <linux/clk/clk-conf.h>
#include <linux/platform_device.h>

#include <asm/irq.h>

@@ -193,12 +194,15 @@ static const struct dev_pm_ops amba_pm = {
/*
 * Primecells are part of the Advanced Microcontroller Bus Architecture,
 * so we call the bus "amba".
 * DMA configuration for platform and AMBA bus is same. So here we reuse
 * platform's DMA config routine.
 */
struct bus_type amba_bustype = {
	.name		= "amba",
	.dev_groups	= amba_dev_groups,
	.match		= amba_match,
	.uevent		= amba_uevent,
	.dma_configure	= platform_dma_configure,
	.pm		= &amba_pm,
	.force_dma	= true,
};
+4 −27
Original line number Diff line number Diff line
@@ -329,36 +329,13 @@ void dma_common_free_remap(void *cpu_addr, size_t size, unsigned long vm_flags)
#endif

/*
 * Common configuration to enable DMA API use for a device
 * enables DMA API use for a device
 */
#include <linux/pci.h>

int dma_configure(struct device *dev)
{
	struct device *bridge = NULL, *dma_dev = dev;
	enum dev_dma_attr attr;
	int ret = 0;

	if (dev_is_pci(dev)) {
		bridge = pci_get_host_bridge_device(to_pci_dev(dev));
		dma_dev = bridge;
		if (IS_ENABLED(CONFIG_OF) && dma_dev->parent &&
		    dma_dev->parent->of_node)
			dma_dev = dma_dev->parent;
	}

	if (dma_dev->of_node) {
		ret = of_dma_configure(dev, dma_dev->of_node);
	} else if (has_acpi_companion(dma_dev)) {
		attr = acpi_get_dma_attr(to_acpi_device_node(dma_dev->fwnode));
		if (attr != DEV_DMA_NOT_SUPPORTED)
			ret = acpi_dma_configure(dev, attr);
	}

	if (bridge)
		pci_put_host_bridge_device(bridge);

	return ret;
	if (dev->bus->dma_configure)
		return dev->bus->dma_configure(dev);
	return 0;
}

void dma_deconfigure(struct device *dev)
+17 −0
Original line number Diff line number Diff line
@@ -1130,6 +1130,22 @@ int platform_pm_restore(struct device *dev)

#endif /* CONFIG_HIBERNATE_CALLBACKS */

int platform_dma_configure(struct device *dev)
{
	enum dev_dma_attr attr;
	int ret = 0;

	if (dev->of_node) {
		ret = of_dma_configure(dev, dev->of_node);
	} else if (has_acpi_companion(dev)) {
		attr = acpi_get_dma_attr(to_acpi_device_node(dev->fwnode));
		if (attr != DEV_DMA_NOT_SUPPORTED)
			ret = acpi_dma_configure(dev, attr);
	}

	return ret;
}

static const struct dev_pm_ops platform_dev_pm_ops = {
	.runtime_suspend = pm_generic_runtime_suspend,
	.runtime_resume = pm_generic_runtime_resume,
@@ -1141,6 +1157,7 @@ struct bus_type platform_bus_type = {
	.dev_groups	= platform_dev_groups,
	.match		= platform_match,
	.uevent		= platform_uevent,
	.dma_configure	= platform_dma_configure,
	.pm		= &platform_dev_pm_ops,
	.force_dma	= true,
};
+6 −0
Original line number Diff line number Diff line
@@ -314,6 +314,11 @@ static int host1x_device_match(struct device *dev, struct device_driver *drv)
	return strcmp(dev_name(dev), drv->name) == 0;
}

static int host1x_dma_configure(struct device *dev)
{
	return of_dma_configure(dev, dev->of_node);
}

static const struct dev_pm_ops host1x_device_pm_ops = {
	.suspend = pm_generic_suspend,
	.resume = pm_generic_resume,
@@ -326,6 +331,7 @@ static const struct dev_pm_ops host1x_device_pm_ops = {
struct bus_type host1x_bus_type = {
	.name = "host1x",
	.match = host1x_device_match,
	.dma_configure	= host1x_dma_configure,
	.pm = &host1x_device_pm_ops,
	.force_dma = true,
};
+32 −0
Original line number Diff line number Diff line
@@ -16,6 +16,8 @@
#include <linux/pm_runtime.h>
#include <linux/suspend.h>
#include <linux/kexec.h>
#include <linux/of_device.h>
#include <linux/acpi.h>
#include "pci.h"
#include "pcie/portdrv.h"

@@ -1577,6 +1579,35 @@ static int pci_bus_num_vf(struct device *dev)
	return pci_num_vf(to_pci_dev(dev));
}

/**
 * pci_dma_configure - Setup DMA configuration
 * @dev: ptr to dev structure
 *
 * Function to update PCI devices's DMA configuration using the same
 * info from the OF node or ACPI node of host bridge's parent (if any).
 */
static int pci_dma_configure(struct device *dev)
{
	struct device *bridge;
	int ret = 0;

	bridge = pci_get_host_bridge_device(to_pci_dev(dev));

	if (IS_ENABLED(CONFIG_OF) && bridge->parent &&
	    bridge->parent->of_node) {
		ret = of_dma_configure(dev, bridge->parent->of_node);
	} else if (has_acpi_companion(bridge)) {
		struct acpi_device *adev = to_acpi_device_node(bridge->fwnode);
		enum dev_dma_attr attr = acpi_get_dma_attr(adev);

		if (attr != DEV_DMA_NOT_SUPPORTED)
			ret = acpi_dma_configure(dev, attr);
	}

	pci_put_host_bridge_device(bridge);
	return ret;
}

struct bus_type pci_bus_type = {
	.name		= "pci",
	.match		= pci_bus_match,
@@ -1589,6 +1620,7 @@ struct bus_type pci_bus_type = {
	.drv_groups	= pci_drv_groups,
	.pm		= PCI_PM_OPS_PTR,
	.num_vf		= pci_bus_num_vf,
	.dma_configure	= pci_dma_configure,
	.force_dma	= true,
};
EXPORT_SYMBOL(pci_bus_type);
Loading