Commit db59e1b6 authored by Jean-Philippe Brucker's avatar Jean-Philippe Brucker Committed by Joerg Roedel
Browse files

ACPI: arm64: Move DMA setup operations out of IORT



Extract generic DMA setup code out of IORT, so it can be reused by VIOT.
Keep it in drivers/acpi/arm64 for now, since it could break x86
platforms that haven't run this code so far, if they have invalid
tables.

Reviewed-by: default avatarEric Auger <eric.auger@redhat.com>
Signed-off-by: default avatarJean-Philippe Brucker <jean-philippe@linaro.org>
Reviewed-by: default avatarRobin Murphy <robin.murphy@arm.com>
Link: https://lore.kernel.org/r/20210618152059.1194210-2-jean-philippe@linaro.org


Signed-off-by: default avatarJoerg Roedel <jroedel@suse.de>
parent 8124c8a6
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
# SPDX-License-Identifier: GPL-2.0-only
obj-$(CONFIG_ACPI_IORT) 	+= iort.o
obj-$(CONFIG_ACPI_GTDT) 	+= gtdt.o
obj-y				+= dma.o
+50 −0
Original line number Diff line number Diff line
// SPDX-License-Identifier: GPL-2.0-only
#include <linux/acpi.h>
#include <linux/acpi_iort.h>
#include <linux/device.h>
#include <linux/dma-direct.h>

void acpi_arch_dma_setup(struct device *dev, u64 *dma_addr, u64 *dma_size)
{
	int ret;
	u64 end, mask;
	u64 dmaaddr = 0, size = 0, offset = 0;

	/*
	 * If @dev is expected to be DMA-capable then the bus code that created
	 * it should have initialised its dma_mask pointer by this point. For
	 * now, we'll continue the legacy behaviour of coercing it to the
	 * coherent mask if not, but we'll no longer do so quietly.
	 */
	if (!dev->dma_mask) {
		dev_warn(dev, "DMA mask not set\n");
		dev->dma_mask = &dev->coherent_dma_mask;
	}

	if (dev->coherent_dma_mask)
		size = max(dev->coherent_dma_mask, dev->coherent_dma_mask + 1);
	else
		size = 1ULL << 32;

	ret = acpi_dma_get_range(dev, &dmaaddr, &offset, &size);
	if (ret == -ENODEV)
		ret = iort_dma_get_ranges(dev, &size);
	if (!ret) {
		/*
		 * Limit coherent and dma mask based on size retrieved from
		 * firmware.
		 */
		end = dmaaddr + size - 1;
		mask = DMA_BIT_MASK(ilog2(end) + 1);
		dev->bus_dma_limit = end;
		dev->coherent_dma_mask = min(dev->coherent_dma_mask, mask);
		*dev->dma_mask = min(*dev->dma_mask, mask);
	}

	*dma_addr = dmaaddr;
	*dma_size = size;

	ret = dma_direct_set_offset(dev, dmaaddr + offset, dmaaddr, size);

	dev_dbg(dev, "dma_offset(%#08llx)%s\n", offset, ret ? " failed!" : "");
}
+8 −46
Original line number Diff line number Diff line
@@ -1144,56 +1144,18 @@ static int rc_dma_get_range(struct device *dev, u64 *size)
}

/**
 * iort_dma_setup() - Set-up device DMA parameters.
 * iort_dma_get_ranges() - Look up DMA addressing limit for the device
 * @dev: device to lookup
 * @size: DMA range size result pointer
 *
 * @dev: device to configure
 * @dma_addr: device DMA address result pointer
 * @dma_size: DMA range size result pointer
 * Return: 0 on success, an error otherwise.
 */
void iort_dma_setup(struct device *dev, u64 *dma_addr, u64 *dma_size)
int iort_dma_get_ranges(struct device *dev, u64 *size)
{
	u64 end, mask, dmaaddr = 0, size = 0, offset = 0;
	int ret;

	/*
	 * If @dev is expected to be DMA-capable then the bus code that created
	 * it should have initialised its dma_mask pointer by this point. For
	 * now, we'll continue the legacy behaviour of coercing it to the
	 * coherent mask if not, but we'll no longer do so quietly.
	 */
	if (!dev->dma_mask) {
		dev_warn(dev, "DMA mask not set\n");
		dev->dma_mask = &dev->coherent_dma_mask;
	}

	if (dev->coherent_dma_mask)
		size = max(dev->coherent_dma_mask, dev->coherent_dma_mask + 1);
	if (dev_is_pci(dev))
		return rc_dma_get_range(dev, size);
	else
		size = 1ULL << 32;

	ret = acpi_dma_get_range(dev, &dmaaddr, &offset, &size);
	if (ret == -ENODEV)
		ret = dev_is_pci(dev) ? rc_dma_get_range(dev, &size)
				      : nc_dma_get_range(dev, &size);

	if (!ret) {
		/*
		 * Limit coherent and dma mask based on size retrieved from
		 * firmware.
		 */
		end = dmaaddr + size - 1;
		mask = DMA_BIT_MASK(ilog2(end) + 1);
		dev->bus_dma_limit = end;
		dev->coherent_dma_mask = min(dev->coherent_dma_mask, mask);
		*dev->dma_mask = min(*dev->dma_mask, mask);
	}

	*dma_addr = dmaaddr;
	*dma_size = size;

	ret = dma_direct_set_offset(dev, dmaaddr + offset, dmaaddr, size);

	dev_dbg(dev, "dma_offset(%#08llx)%s\n", offset, ret ? " failed!" : "");
		return nc_dma_get_range(dev, size);
}

static void __init acpi_iort_register_irq(int hwirq, const char *name,
+1 −1
Original line number Diff line number Diff line
@@ -1537,7 +1537,7 @@ int acpi_dma_configure_id(struct device *dev, enum dev_dma_attr attr,
		return 0;
	}

	iort_dma_setup(dev, &dma_addr, &size);
	acpi_arch_dma_setup(dev, &dma_addr, &size);

	iommu = iort_iommu_configure_id(dev, input_id);
	if (PTR_ERR(iommu) == -EPROBE_DEFER)
+3 −0
Original line number Diff line number Diff line
@@ -259,9 +259,12 @@ void acpi_numa_x2apic_affinity_init(struct acpi_srat_x2apic_cpu_affinity *pa);

#ifdef CONFIG_ARM64
void acpi_numa_gicc_affinity_init(struct acpi_srat_gicc_affinity *pa);
void acpi_arch_dma_setup(struct device *dev, u64 *dma_addr, u64 *dma_size);
#else
static inline void
acpi_numa_gicc_affinity_init(struct acpi_srat_gicc_affinity *pa) { }
static inline void
acpi_arch_dma_setup(struct device *dev, u64 *dma_addr, u64 *dma_size) { }
#endif

int acpi_numa_memory_affinity_init (struct acpi_srat_mem_affinity *ma);
Loading