LoongArch inclusion category: feature bugzilla: https://gitee.com/openeuler/kernel/issues/I82GAS CVE: NA
--------------------------------
To be compatible with OLD firmware which has no _DMA method, we should use arch specific phys_to_dma.
Signed-off-by: Hongchen Zhang zhanghongchen@loongson.cn Signed-off-by: yangyinglu yangyinglu@loongson.cn --- arch/loongarch/Kconfig | 1 + arch/loongarch/kernel/dma.c | 26 +++++++++++++++++++++++++- 2 files changed, 26 insertions(+), 1 deletion(-)
diff --git a/arch/loongarch/Kconfig b/arch/loongarch/Kconfig index e438c18f3a3a..432dd5c8e6ec 100644 --- a/arch/loongarch/Kconfig +++ b/arch/loongarch/Kconfig @@ -134,6 +134,7 @@ config LOONGARCH select HAVE_SAMPLE_FTRACE_DIRECT_MULTI select HAVE_SETUP_PER_CPU_AREA if NUMA select HAVE_STACKPROTECTOR + select ARCH_HAS_PHYS_TO_DMA select HAVE_SYSCALL_TRACEPOINTS select HAVE_TIF_NOHZ select HAVE_VIRT_CPU_ACCOUNTING_GEN if !SMP diff --git a/arch/loongarch/kernel/dma.c b/arch/loongarch/kernel/dma.c index 7a9c6a9dd2d0..b10809609de4 100644 --- a/arch/loongarch/kernel/dma.c +++ b/arch/loongarch/kernel/dma.c @@ -4,6 +4,28 @@ */ #include <linux/acpi.h> #include <linux/dma-direct.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) +{ + long nid = (daddr >> node_id_offset) & 0xf; + + return ((nid << node_id_offset) ^ daddr) | (nid << 44); +}
void acpi_arch_dma_setup(struct device *dev) { @@ -11,6 +33,9 @@ void acpi_arch_dma_setup(struct device *dev) u64 mask, end = 0; const struct bus_dma_region *map = NULL;
+ if (node_id_offset == 0) + node_id_offset = ((readl(LS7A_DMA_CFG) & LS7A_DMA_NODE_MASK) >> LS7A_DMA_NODE_SHF) + 36; + ret = acpi_dma_get_range(dev, &map); if (!ret && map) { const struct bus_dma_region *r = map; @@ -26,5 +51,4 @@ void acpi_arch_dma_setup(struct device *dev) dev->coherent_dma_mask = min(dev->coherent_dma_mask, mask); *dev->dma_mask = min(*dev->dma_mask, mask); } - }