[PATCH v4 1/6] ACPI: arm64: Move DMA setup operations out of IORT
Eric Auger
eric.auger at redhat.com
Wed Jun 16 02:35:46 PDT 2021
Hi jean,
On 6/10/21 9:51 AM, Jean-Philippe Brucker wrote:
> 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.
>
> Signed-off-by: Jean-Philippe Brucker <jean-philippe at linaro.org>
Reviewed-by: Eric Auger <eric.auger at redhat.com>
Eric
> ---
> drivers/acpi/arm64/Makefile | 1 +
> include/linux/acpi.h | 3 +++
> include/linux/acpi_iort.h | 6 ++---
> drivers/acpi/arm64/dma.c | 50 ++++++++++++++++++++++++++++++++++
> drivers/acpi/arm64/iort.c | 54 ++++++-------------------------------
> drivers/acpi/scan.c | 2 +-
> 6 files changed, 66 insertions(+), 50 deletions(-)
> create mode 100644 drivers/acpi/arm64/dma.c
>
> diff --git a/drivers/acpi/arm64/Makefile b/drivers/acpi/arm64/Makefile
> index 6ff50f4ed947..66acbe77f46e 100644
> --- a/drivers/acpi/arm64/Makefile
> +++ b/drivers/acpi/arm64/Makefile
> @@ -1,3 +1,4 @@
> # SPDX-License-Identifier: GPL-2.0-only
> obj-$(CONFIG_ACPI_IORT) += iort.o
> obj-$(CONFIG_ACPI_GTDT) += gtdt.o
> +obj-y += dma.o
> diff --git a/include/linux/acpi.h b/include/linux/acpi.h
> index c60745f657e9..7aaa9559cc19 100644
> --- a/include/linux/acpi.h
> +++ b/include/linux/acpi.h
> @@ -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);
> diff --git a/include/linux/acpi_iort.h b/include/linux/acpi_iort.h
> index 1a12baa58e40..f7f054833afd 100644
> --- a/include/linux/acpi_iort.h
> +++ b/include/linux/acpi_iort.h
> @@ -34,7 +34,7 @@ struct irq_domain *iort_get_device_domain(struct device *dev, u32 id,
> void acpi_configure_pmsi_domain(struct device *dev);
> int iort_pmsi_get_dev_id(struct device *dev, u32 *dev_id);
> /* IOMMU interface */
> -void iort_dma_setup(struct device *dev, u64 *dma_addr, u64 *size);
> +int iort_dma_get_ranges(struct device *dev, u64 *size);
> const struct iommu_ops *iort_iommu_configure_id(struct device *dev,
> const u32 *id_in);
> int iort_iommu_msi_get_resv_regions(struct device *dev, struct list_head *head);
> @@ -48,8 +48,8 @@ static inline struct irq_domain *iort_get_device_domain(
> { return NULL; }
> static inline void acpi_configure_pmsi_domain(struct device *dev) { }
> /* IOMMU interface */
> -static inline void iort_dma_setup(struct device *dev, u64 *dma_addr,
> - u64 *size) { }
> +static inline int iort_dma_get_ranges(struct device *dev, u64 *size)
> +{ return -ENODEV; }
> static inline const struct iommu_ops *iort_iommu_configure_id(
> struct device *dev, const u32 *id_in)
> { return NULL; }
> diff --git a/drivers/acpi/arm64/dma.c b/drivers/acpi/arm64/dma.c
> new file mode 100644
> index 000000000000..f16739ad3cc0
> --- /dev/null
> +++ b/drivers/acpi/arm64/dma.c
> @@ -0,0 +1,50 @@
> +// 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!" : "");
> +}
> diff --git a/drivers/acpi/arm64/iort.c b/drivers/acpi/arm64/iort.c
> index 3912a1f6058e..a940be1cf2af 100644
> --- a/drivers/acpi/arm64/iort.c
> +++ b/drivers/acpi/arm64/iort.c
> @@ -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,
> diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c
> index e10d38ac7cf2..ea613df8f913 100644
> --- a/drivers/acpi/scan.c
> +++ b/drivers/acpi/scan.c
> @@ -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)
More information about the linux-arm-kernel
mailing list