133 lines
3.7 KiB
Diff
133 lines
3.7 KiB
Diff
From b64c74ac5d26a1b55d0d343ca344f805591b0991 Mon Sep 17 00:00:00 2001
|
|
From: Min Lin <linmin@eswincomputing.com>
|
|
Date: Mon, 29 Jul 2024 14:19:28 +0000
|
|
Subject: [PATCH 005/128] riscv: mm: dma-noncoherent: Add arch_dma_set_uncached
|
|
|
|
Add arch_dma_set_uncached and arch_dma_clear_uncached
|
|
|
|
Signed-off-by: Min Lin <linmin@eswincomputing.com>
|
|
Signed-off-by: Pritesh Patel <pritesh.patel@einfochips.com>
|
|
---
|
|
arch/riscv/mm/dma-noncoherent.c | 82 +++++++++++++++++++++++++++++++++
|
|
1 file changed, 82 insertions(+)
|
|
|
|
diff --git a/arch/riscv/mm/dma-noncoherent.c b/arch/riscv/mm/dma-noncoherent.c
|
|
index 341bd6706b4c..39b2bea86960 100644
|
|
--- a/arch/riscv/mm/dma-noncoherent.c
|
|
+++ b/arch/riscv/mm/dma-noncoherent.c
|
|
@@ -10,6 +10,10 @@
|
|
#include <linux/mm.h>
|
|
#include <asm/cacheflush.h>
|
|
#include <asm/dma-noncoherent.h>
|
|
+#ifdef CONFIG_SOC_SIFIVE_EIC7700
|
|
+#include <linux/io.h>
|
|
+#include <linux/iommu.h>
|
|
+#endif
|
|
|
|
static bool noncoherent_supported __ro_after_init;
|
|
int dma_cache_alignment __ro_after_init = ARCH_DMA_MINALIGN;
|
|
@@ -128,6 +132,13 @@ void arch_dma_prep_coherent(struct page *page, size_t size)
|
|
ALT_CMO_OP(flush, flush_addr, size, riscv_cbom_block_size);
|
|
}
|
|
|
|
+#ifdef CONFIG_IOMMU_DMA
|
|
+void arch_teardown_dma_ops(struct device *dev)
|
|
+{
|
|
+ dev->dma_ops = NULL;
|
|
+}
|
|
+#endif
|
|
+
|
|
void arch_setup_dma_ops(struct device *dev, u64 dma_base, u64 size,
|
|
const struct iommu_ops *iommu, bool coherent)
|
|
{
|
|
@@ -137,11 +148,18 @@ void arch_setup_dma_ops(struct device *dev, u64 dma_base, u64 size,
|
|
dev_driver_string(dev), dev_name(dev),
|
|
ARCH_DMA_MINALIGN, riscv_cbom_block_size);
|
|
|
|
+#ifndef CONFIG_SOC_SIFIVE_EIC7700
|
|
WARN_TAINT(!coherent && !noncoherent_supported, TAINT_CPU_OUT_OF_SPEC,
|
|
"%s %s: device non-coherent but no non-coherent operations supported",
|
|
dev_driver_string(dev), dev_name(dev));
|
|
+#endif
|
|
|
|
dev->dma_coherent = coherent;
|
|
+
|
|
+#ifdef CONFIG_SOC_SIFIVE_EIC7700
|
|
+ if (iommu)
|
|
+ iommu_setup_dma_ops(dev, dma_base, size);
|
|
+#endif
|
|
}
|
|
|
|
void riscv_noncoherent_supported(void)
|
|
@@ -156,3 +174,67 @@ void __init riscv_set_dma_cache_alignment(void)
|
|
if (!noncoherent_supported)
|
|
dma_cache_alignment = 1;
|
|
}
|
|
+#ifdef CONFIG_SOC_SIFIVE_EIC7700
|
|
+static struct page **__iommu_dma_common_find_pages(void *cpu_addr)
|
|
+{
|
|
+ struct vm_struct *area = find_vm_area(cpu_addr);
|
|
+
|
|
+ if (!area || area->flags != VM_DMA_COHERENT)
|
|
+ return NULL;
|
|
+ return area->pages;
|
|
+}
|
|
+
|
|
+void arch_dma_clear_uncached(void *addr, size_t size)
|
|
+{
|
|
+ struct page **pages = NULL;
|
|
+
|
|
+ pages = __iommu_dma_common_find_pages(addr);
|
|
+ if (!pages) { // todo: supposed to handle this error
|
|
+ pr_err( "smmu_dbg, fail to find pages\n");
|
|
+
|
|
+ return;
|
|
+ }
|
|
+ kvfree(pages);
|
|
+ memunmap(addr);
|
|
+}
|
|
+
|
|
+void *arch_dma_set_uncached(void *addr, size_t size)
|
|
+{
|
|
+ struct page **pages = NULL;
|
|
+ static struct page *page = NULL;
|
|
+ struct vm_struct *area = NULL;
|
|
+ phys_addr_t phys_addr = convert_pha_from_mem_to_sys_port(__pa(addr));
|
|
+ void *mem_base = NULL;
|
|
+
|
|
+ mem_base = memremap(phys_addr, size, MEMREMAP_WT);
|
|
+ if (!mem_base) {
|
|
+ pr_err("%s memremap failed for addr %px\n", __func__, addr);
|
|
+ return ERR_PTR(-EINVAL);
|
|
+ }
|
|
+
|
|
+ pages = kvzalloc(sizeof(*pages), GFP_KERNEL);
|
|
+ if (!pages) {
|
|
+ pr_err("smmu_dbg, failed to alloc memory!\n");
|
|
+ goto err_pages_alloc;
|
|
+ }
|
|
+ page = virt_to_page(addr);
|
|
+ area = find_vm_area(mem_base);
|
|
+ if (!area) {
|
|
+ pr_err("smmu_dbg, failed to find vm area!\n");
|
|
+ goto err_find_vm_area;
|
|
+ }
|
|
+ pages[0] = page;
|
|
+ area->pages = pages;
|
|
+ area->flags = VM_DMA_COHERENT;
|
|
+
|
|
+ return mem_base;
|
|
+
|
|
+err_find_vm_area:
|
|
+ kvfree(pages);
|
|
+
|
|
+err_pages_alloc:
|
|
+ memunmap(mem_base);
|
|
+
|
|
+ return NULL;
|
|
+}
|
|
+#endif
|
|
--
|
|
2.47.0
|
|
|