Skip to content

Commit db59e1b

Browse files
jpbruckerjoergroedel
authored andcommitted
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: Eric Auger <eric.auger@redhat.com> Signed-off-by: Jean-Philippe Brucker <jean-philippe@linaro.org> Reviewed-by: Robin Murphy <robin.murphy@arm.com> Link: https://lore.kernel.org/r/20210618152059.1194210-2-jean-philippe@linaro.org Signed-off-by: Joerg Roedel <jroedel@suse.de>
1 parent 8124c8a commit db59e1b

File tree

6 files changed

+66
-50
lines changed

6 files changed

+66
-50
lines changed

drivers/acpi/arm64/Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
11
# SPDX-License-Identifier: GPL-2.0-only
22
obj-$(CONFIG_ACPI_IORT) += iort.o
33
obj-$(CONFIG_ACPI_GTDT) += gtdt.o
4+
obj-y += dma.o

drivers/acpi/arm64/dma.c

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
// SPDX-License-Identifier: GPL-2.0-only
2+
#include <linux/acpi.h>
3+
#include <linux/acpi_iort.h>
4+
#include <linux/device.h>
5+
#include <linux/dma-direct.h>
6+
7+
void acpi_arch_dma_setup(struct device *dev, u64 *dma_addr, u64 *dma_size)
8+
{
9+
int ret;
10+
u64 end, mask;
11+
u64 dmaaddr = 0, size = 0, offset = 0;
12+
13+
/*
14+
* If @dev is expected to be DMA-capable then the bus code that created
15+
* it should have initialised its dma_mask pointer by this point. For
16+
* now, we'll continue the legacy behaviour of coercing it to the
17+
* coherent mask if not, but we'll no longer do so quietly.
18+
*/
19+
if (!dev->dma_mask) {
20+
dev_warn(dev, "DMA mask not set\n");
21+
dev->dma_mask = &dev->coherent_dma_mask;
22+
}
23+
24+
if (dev->coherent_dma_mask)
25+
size = max(dev->coherent_dma_mask, dev->coherent_dma_mask + 1);
26+
else
27+
size = 1ULL << 32;
28+
29+
ret = acpi_dma_get_range(dev, &dmaaddr, &offset, &size);
30+
if (ret == -ENODEV)
31+
ret = iort_dma_get_ranges(dev, &size);
32+
if (!ret) {
33+
/*
34+
* Limit coherent and dma mask based on size retrieved from
35+
* firmware.
36+
*/
37+
end = dmaaddr + size - 1;
38+
mask = DMA_BIT_MASK(ilog2(end) + 1);
39+
dev->bus_dma_limit = end;
40+
dev->coherent_dma_mask = min(dev->coherent_dma_mask, mask);
41+
*dev->dma_mask = min(*dev->dma_mask, mask);
42+
}
43+
44+
*dma_addr = dmaaddr;
45+
*dma_size = size;
46+
47+
ret = dma_direct_set_offset(dev, dmaaddr + offset, dmaaddr, size);
48+
49+
dev_dbg(dev, "dma_offset(%#08llx)%s\n", offset, ret ? " failed!" : "");
50+
}

drivers/acpi/arm64/iort.c

Lines changed: 8 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -1144,56 +1144,18 @@ static int rc_dma_get_range(struct device *dev, u64 *size)
11441144
}
11451145

11461146
/**
1147-
* iort_dma_setup() - Set-up device DMA parameters.
1147+
* iort_dma_get_ranges() - Look up DMA addressing limit for the device
1148+
* @dev: device to lookup
1149+
* @size: DMA range size result pointer
11481150
*
1149-
* @dev: device to configure
1150-
* @dma_addr: device DMA address result pointer
1151-
* @dma_size: DMA range size result pointer
1151+
* Return: 0 on success, an error otherwise.
11521152
*/
1153-
void iort_dma_setup(struct device *dev, u64 *dma_addr, u64 *dma_size)
1153+
int iort_dma_get_ranges(struct device *dev, u64 *size)
11541154
{
1155-
u64 end, mask, dmaaddr = 0, size = 0, offset = 0;
1156-
int ret;
1157-
1158-
/*
1159-
* If @dev is expected to be DMA-capable then the bus code that created
1160-
* it should have initialised its dma_mask pointer by this point. For
1161-
* now, we'll continue the legacy behaviour of coercing it to the
1162-
* coherent mask if not, but we'll no longer do so quietly.
1163-
*/
1164-
if (!dev->dma_mask) {
1165-
dev_warn(dev, "DMA mask not set\n");
1166-
dev->dma_mask = &dev->coherent_dma_mask;
1167-
}
1168-
1169-
if (dev->coherent_dma_mask)
1170-
size = max(dev->coherent_dma_mask, dev->coherent_dma_mask + 1);
1155+
if (dev_is_pci(dev))
1156+
return rc_dma_get_range(dev, size);
11711157
else
1172-
size = 1ULL << 32;
1173-
1174-
ret = acpi_dma_get_range(dev, &dmaaddr, &offset, &size);
1175-
if (ret == -ENODEV)
1176-
ret = dev_is_pci(dev) ? rc_dma_get_range(dev, &size)
1177-
: nc_dma_get_range(dev, &size);
1178-
1179-
if (!ret) {
1180-
/*
1181-
* Limit coherent and dma mask based on size retrieved from
1182-
* firmware.
1183-
*/
1184-
end = dmaaddr + size - 1;
1185-
mask = DMA_BIT_MASK(ilog2(end) + 1);
1186-
dev->bus_dma_limit = end;
1187-
dev->coherent_dma_mask = min(dev->coherent_dma_mask, mask);
1188-
*dev->dma_mask = min(*dev->dma_mask, mask);
1189-
}
1190-
1191-
*dma_addr = dmaaddr;
1192-
*dma_size = size;
1193-
1194-
ret = dma_direct_set_offset(dev, dmaaddr + offset, dmaaddr, size);
1195-
1196-
dev_dbg(dev, "dma_offset(%#08llx)%s\n", offset, ret ? " failed!" : "");
1158+
return nc_dma_get_range(dev, size);
11971159
}
11981160

11991161
static void __init acpi_iort_register_irq(int hwirq, const char *name,

drivers/acpi/scan.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1537,7 +1537,7 @@ int acpi_dma_configure_id(struct device *dev, enum dev_dma_attr attr,
15371537
return 0;
15381538
}
15391539

1540-
iort_dma_setup(dev, &dma_addr, &size);
1540+
acpi_arch_dma_setup(dev, &dma_addr, &size);
15411541

15421542
iommu = iort_iommu_configure_id(dev, input_id);
15431543
if (PTR_ERR(iommu) == -EPROBE_DEFER)

include/linux/acpi.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -259,9 +259,12 @@ void acpi_numa_x2apic_affinity_init(struct acpi_srat_x2apic_cpu_affinity *pa);
259259

260260
#ifdef CONFIG_ARM64
261261
void acpi_numa_gicc_affinity_init(struct acpi_srat_gicc_affinity *pa);
262+
void acpi_arch_dma_setup(struct device *dev, u64 *dma_addr, u64 *dma_size);
262263
#else
263264
static inline void
264265
acpi_numa_gicc_affinity_init(struct acpi_srat_gicc_affinity *pa) { }
266+
static inline void
267+
acpi_arch_dma_setup(struct device *dev, u64 *dma_addr, u64 *dma_size) { }
265268
#endif
266269

267270
int acpi_numa_memory_affinity_init (struct acpi_srat_mem_affinity *ma);

include/linux/acpi_iort.h

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ struct irq_domain *iort_get_device_domain(struct device *dev, u32 id,
3434
void acpi_configure_pmsi_domain(struct device *dev);
3535
int iort_pmsi_get_dev_id(struct device *dev, u32 *dev_id);
3636
/* IOMMU interface */
37-
void iort_dma_setup(struct device *dev, u64 *dma_addr, u64 *size);
37+
int iort_dma_get_ranges(struct device *dev, u64 *size);
3838
const struct iommu_ops *iort_iommu_configure_id(struct device *dev,
3939
const u32 *id_in);
4040
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(
4848
{ return NULL; }
4949
static inline void acpi_configure_pmsi_domain(struct device *dev) { }
5050
/* IOMMU interface */
51-
static inline void iort_dma_setup(struct device *dev, u64 *dma_addr,
52-
u64 *size) { }
51+
static inline int iort_dma_get_ranges(struct device *dev, u64 *size)
52+
{ return -ENODEV; }
5353
static inline const struct iommu_ops *iort_iommu_configure_id(
5454
struct device *dev, const u32 *id_in)
5555
{ return NULL; }

0 commit comments

Comments
 (0)