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;
|