lkml.org 
[lkml]   [2022]   [Aug]   [5]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
Patch in this message
/
From
Subject[PATCH V2 2/2] LoongArch: Remove ARCH_HAS_PHYS_TO_DMA
Date
Use _DMA defined in ACPI spec for translation betweeen
DMA address and CPU address, and implement acpi_arch_dma_setup
for initializing dev->dma_range_map, where acpi_dma_get_range
is called for parsing _DMA.

e.g.
If we have two dma ranges:
cpu address dma address size offset
0x200080000000 0x2080000000 0x400000000 0x1fe000000000
0x400080000000 0x4080000000 0x400000000 0x3fc000000000

_DMA for pci devices should be declared in host bridge as
flowing:

Name (_DMA, ResourceTemplate() {
QWordMemory (ResourceProducer,
PosDecode,
MinFixed,
MaxFixed,
NonCacheable,
ReadWrite,
0x0,
0x4080000000,
0x447fffffff,
0x3fc000000000,
0x400000000,
,
,
)

QWordMemory (ResourceProducer,
PosDecode,
MinFixed,
MaxFixed,
NonCacheable,
ReadWrite,
0x0,
0x2080000000,
0x247fffffff,
0x1fe000000000,
0x400000000,
,
,
)
})

Signed-off-by: Jianmin Lv <lvjianmin@loongson.cn>
---
arch/loongarch/Kconfig | 1 -
arch/loongarch/kernel/dma.c | 62 +++++++++++++++++++++----------------------
arch/loongarch/kernel/setup.c | 2 +-
include/linux/acpi.h | 9 ++++---
4 files changed, 38 insertions(+), 36 deletions(-)

diff --git a/arch/loongarch/Kconfig b/arch/loongarch/Kconfig
index b57daee..9dedcf9 100644
--- a/arch/loongarch/Kconfig
+++ b/arch/loongarch/Kconfig
@@ -7,7 +7,6 @@ config LOONGARCH
select ARCH_ENABLE_MEMORY_HOTPLUG
select ARCH_ENABLE_MEMORY_HOTREMOVE
select ARCH_HAS_ACPI_TABLE_UPGRADE if ACPI
- select ARCH_HAS_PHYS_TO_DMA
select ARCH_HAS_PTE_SPECIAL
select ARCH_HAS_TICK_BROADCAST if GENERIC_CLOCKEVENTS_BROADCAST
select ARCH_INLINE_READ_LOCK if !PREEMPTION
diff --git a/arch/loongarch/kernel/dma.c b/arch/loongarch/kernel/dma.c
index 8c9b531..7850e6b 100644
--- a/arch/loongarch/kernel/dma.c
+++ b/arch/loongarch/kernel/dma.c
@@ -2,39 +2,39 @@
/*
* Copyright (C) 2020-2022 Loongson Technology Corporation Limited
*/
-#include <linux/init.h>
+#include <linux/acpi.h>
#include <linux/dma-direct.h>
-#include <linux/dma-mapping.h>
-#include <linux/dma-map-ops.h>
-#include <linux/swiotlb.h>

-#include <asm/bootinfo.h>
-#include <asm/dma.h>
-#include <asm/loongson.h>
-
-/*
- * We extract 4bit node id (bit 44~47) from Loongson-3's
- * 48bit physical address space and embed it into 40bit.
- */
-
-static int node_id_offset;
-
-dma_addr_t phys_to_dma(struct device *dev, phys_addr_t paddr)
-{
- long nid = (paddr >> 44) & 0xf;
-
- return ((nid << 44) ^ paddr) | (nid << node_id_offset);
-}
-
-phys_addr_t dma_to_phys(struct device *dev, dma_addr_t daddr)
+void acpi_arch_dma_setup(struct device *dev)
{
- long nid = (daddr >> node_id_offset) & 0xf;
+ int ret;
+ const struct bus_dma_region *map = NULL;
+
+ ret = acpi_dma_get_range(dev, &map);
+ if (!ret) {
+ const struct bus_dma_region *r = map;
+ u64 mask, dma_start, dma_end = 0;
+
+ /* determine the overall bounds of all dma regions */
+ for (dma_start = U64_MAX; r->size; r++) {
+
+ /* Take lower and upper limits */
+ if (r->dma_start < dma_start)
+ dma_start = r->dma_start;
+ if (r->dma_start + r->size - 1 > dma_end)
+ dma_end = r->dma_start + r->size - 1;
+ }
+
+ if (dma_start >= dma_end) {
+ dev_dbg(dev, "Invalid DMA regions configuration\n");
+ return;
+ }
+
+ mask = DMA_BIT_MASK(ilog2(dma_end) + 1);
+ dev->bus_dma_limit = dma_end;
+ dev->dma_range_map = map;
+ dev->coherent_dma_mask = min(dev->coherent_dma_mask, mask);
+ *dev->dma_mask = min(*dev->dma_mask, mask);
+ }

- return ((nid << node_id_offset) ^ daddr) | (nid << 44);
-}
-
-void __init plat_swiotlb_setup(void)
-{
- swiotlb_init(true, SWIOTLB_VERBOSE);
- node_id_offset = ((readl(LS7A_DMA_CFG) & LS7A_DMA_NODE_MASK) >> LS7A_DMA_NODE_SHF) + 36;
}
diff --git a/arch/loongarch/kernel/setup.c b/arch/loongarch/kernel/setup.c
index c74860b..974f085 100644
--- a/arch/loongarch/kernel/setup.c
+++ b/arch/loongarch/kernel/setup.c
@@ -247,7 +247,7 @@ static void __init arch_mem_init(char **cmdline_p)
sparse_init();
memblock_set_bottom_up(true);

- plat_swiotlb_setup();
+ swiotlb_init(true, SWIOTLB_VERBOSE);

dma_contiguous_reserve(PFN_PHYS(max_low_pfn));

diff --git a/include/linux/acpi.h b/include/linux/acpi.h
index 34e0545..33977b87 100644
--- a/include/linux/acpi.h
+++ b/include/linux/acpi.h
@@ -278,14 +278,17 @@ int acpi_table_parse_madt(enum acpi_madt_type id,

void acpi_numa_x2apic_affinity_init(struct acpi_srat_x2apic_cpu_affinity *pa);

+#if defined(CONFIG_ARM64) || defined(CONFIG_LOONGARCH)
+void acpi_arch_dma_setup(struct device *dev);
+#else
+static inline void acpi_arch_dma_setup(struct device *dev) { }
+#endif
+
#ifdef CONFIG_ARM64
void acpi_numa_gicc_affinity_init(struct acpi_srat_gicc_affinity *pa);
-void acpi_arch_dma_setup(struct device *dev);
#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) { }
#endif

int acpi_numa_memory_affinity_init (struct acpi_srat_mem_affinity *ma);
--
1.8.3.1
\
 
 \ /
  Last update: 2022-08-05 09:32    [W:0.095 / U:0.348 seconds]
©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site