[2.5 PATCH] R10K DMA cache flushing routines for non-coherent systems

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Hi,

	This patch adds support for DMA cache flushing for the R10000
processor on non-coherent systems (Indy and O2).

Vivien.

================================================================================

--- linux/arch/mips64/mm/andes.c	Mon Jul  8 22:26:10 2002
+++ linux.patch/arch/mips64/mm/andes.c	Sun Jul  7 14:48:26 2002
@@ -11,13 +11,17 @@
 #include <linux/kernel.h>
 #include <linux/sched.h>
 #include <linux/mm.h>
+#include <asm/io.h>
 #include <asm/page.h>
 #include <asm/pgtable.h>
-#include <asm/r10kcache.h>
 #include <asm/system.h>
 #include <asm/mmu_context.h>
 
-static int scache_lsz64;
+/* Secondary cache parameters. */
+static unsigned int scache_size, sc_lsize;	/* Again, in bytes */
+
+#include <asm/r10kcache.h>
+
 
 /*
  * This version has been tuned on an Origin.  For other machines the arguments
@@ -98,7 +102,7 @@
  */
 static void andes_flush_cache_l2(void)
 {
-	switch (sc_lsize()) {
+	switch (sc_lsize) {
 		case 64:
 			blast_scache64();
 			break;
@@ -111,13 +115,96 @@
 	}
 }
 
+static void
+andes_flush_cache_all(void)
+{
+	andes_flush_cache_l1();
+	andes_flush_cache_l2();
+}
+
 void
 andes_flush_icache_page(unsigned long page)
 {
-	if (scache_lsz64)
-		blast_scache64_page(page);
-	else
-		blast_scache128_page(page);
+	switch (sc_lsize) {
+		case 64:
+			blast_scache64_page(page);
+			break;
+		case 128:
+			blast_scache128_page(page);
+			break;
+		default:
+			printk(KERN_EMERG "Unknown L2 line size\n");
+			while(1);
+	}
+}
+
+/*
+ * Writeback and invalidate the cache before DMA.
+ */
+
+static void andes_dma_cache_wback_inv(unsigned long addr, unsigned long size)
+{
+	unsigned long end, a;
+
+
+	if (size >= (unsigned long)dcache_size) {
+		flush_cache_l1();
+	} else {
+		a = addr & ~((unsigned long)dc_lsize - 1);
+		end = (addr + size) & ~((unsigned long)dc_lsize - 1);
+		while (1) {
+			flush_dcache_line(a); /* Hit_Writeback_Inv_D */
+			if (a == end) break;
+			a += dc_lsize;
+		}
+	}
+
+	if (size >= (unsigned long)scache_size) {
+		flush_cache_l2();
+	} else {
+		a = addr & ~((unsigned long) sc_lsize - 1);
+		end = (addr + size) & ~((unsigned long) sc_lsize - 1);
+		while (1) {
+			flush_scache_line(a);	/* Hit_Writeback_Inv_S */
+			if (a == end) break;
+			a += sc_lsize;
+		}
+	}
+}
+
+static void andes_dma_cache_inv(unsigned long addr, unsigned long size)
+{
+	unsigned long end, a;
+
+
+	if (size >= (unsigned long)dcache_size) {
+		flush_cache_l1();
+	} else {
+		a = addr & ~((unsigned long)dc_lsize - 1);
+		end = (addr + size) & ~((unsigned long)dc_lsize - 1);
+		while (1) {
+			flush_dcache_line(a); /* Hit_Writeback_Inv_D */
+			if (a == end) break;
+			a += dc_lsize;
+		}
+	}
+
+	if (size >= (unsigned long)scache_size) {
+		flush_cache_l2();
+	} else {
+		a = addr & ~((unsigned long) sc_lsize - 1);
+		end = (addr + size) & ~((unsigned long) sc_lsize - 1);
+		while (1) {
+			flush_scache_line(a);	/* Hit_Writeback_Inv_S */
+			if (a == end) break;
+			a += sc_lsize;
+		}
+	}
+}
+
+static void andes_dma_cache_wback(unsigned long addr, unsigned long size)
+{
+	panic("andes_dma_cache called - should not happen.");
 }
 
 static void
@@ -176,11 +263,9 @@
 	}
 }
 
-void local_flush_tlb_range(struct vm_area_struct *vma, unsigned long start,
+void local_flush_tlb_range(struct mm_struct *mm, unsigned long start,
                            unsigned long end)
 {
-	struct mm_struct *mm = vma->vm_mm;
-
 	if (CPU_CONTEXT(smp_processor_id(), mm) != 0) {
 		unsigned long flags;
 		int size;
@@ -305,31 +390,28 @@
 
 void __init ld_mmu_andes(void)
 {
+	/* get secondary cache parameters */
+	scache_size = scache_size();
+	sc_lsize = sc_lsize();
+
 	printk("Primary instruction cache %dkb, linesize %d bytes\n",
 	       icache_size >> 10, ic_lsize);
 	printk("Primary data cache %dkb, linesize %d bytes\n",
 	       dcache_size >> 10, dc_lsize);
 	printk("Secondary cache sized at %ldK, linesize %ld\n",
-	       scache_size() >> 10, sc_lsize());
+	       scache_size >> 10, sc_lsize);
 
 	_clear_page = andes_clear_page;
 	_copy_page = andes_copy_page;
 
+	_flush_cache_all = andes_flush_cache_all;
 	_flush_cache_l1 = andes_flush_cache_l1;
 	_flush_cache_l2 = andes_flush_cache_l2;
 	_flush_cache_sigtramp = andes_flush_cache_sigtramp;
 
-	switch (sc_lsize()) {
-		case 64:
-			scache_lsz64 = 1;
-			break;
-		case 128:
-			scache_lsz64 = 0;
-			break;
-		default:
-			printk(KERN_EMERG "Unknown L2 line size\n");
-			while(1);
-	}
+	_dma_cache_wback_inv = andes_dma_cache_wback_inv;
+	_dma_cache_wback = andes_dma_cache_wback;
+	_dma_cache_inv = andes_dma_cache_inv;
     
 	update_mmu_cache = andes_update_mmu_cache;


[Index of Archives]     [Linux MIPS Home]     [LKML Archive]     [Linux ARM Kernel]     [Linux ARM]     [Linux]     [Git]     [Yosemite News]     [Linux SCSI]     [Linux Hams]

  Powered by Linux