linux-mips
[Top] [All Lists]

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

To: Ralf Baechle <ralf@oss.sgi.com>
Subject: [2.5 PATCH] R10K DMA cache flushing routines for non-coherent systems
From: Vivien Chappelier <vivien.chappelier@enst-bretagne.fr>
Date: Sun, 14 Jul 2002 23:17:39 +0200 (CEST)
Cc: linux-mips@oss.sgi.com
Sender: owner-linux-mips@oss.sgi.com
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;


<Prev in Thread] Current Thread [Next in Thread>