Received: from mail.onstor.com ([66.201.51.107]) by onstor-exch02.onstor.net with Microsoft SMTPSVC(6.0.3790.1830);
	 Thu, 28 Feb 2008 17:31:03 -0800
Received: from ftp.linux-mips.org ([194.74.144.162]) by mail.onstor.com with Microsoft SMTPSVC(6.0.3790.1830);
	 Thu, 28 Feb 2008 17:31:02 -0800
Received: from localhost.localdomain ([127.0.0.1]:52641 "EHLO
	ftp.linux-mips.org") by ftp.linux-mips.org with ESMTP
	id S28593148AbYB2Baq (ORCPT <rfc822;andy.sharp@onstor.com>);
	Fri, 29 Feb 2008 01:30:46 +0000
Received: with ECARTIS (v1.0.0; list linux-mips); Fri, 29 Feb 2008 01:30:26 +0000 (GMT)
Received: from relay01.mx.bawue.net ([193.7.176.67]:50617 "EHLO
	relay01.mx.bawue.net") by ftp.linux-mips.org with ESMTP
	id S28593144AbYB2BaX (ORCPT <rfc822;linux-mips@linux-mips.org>);
	Fri, 29 Feb 2008 01:30:23 +0000
Received: from lagash (88-106-132-201.dynamic.dsl.as9105.com [88.106.132.201])
	(using TLSv1 with cipher AES256-SHA (256/256 bits))
	(No client certificate requested)
	by relay01.mx.bawue.net (Postfix) with ESMTP id 36F9C48916;
	Fri, 29 Feb 2008 02:30:18 +0100 (CET)
Received: from ths by lagash with local (Exim 4.69)
	(envelope-from <ths@networkno.de>)
	id 1JUu4n-0003Qs-4X; Fri, 29 Feb 2008 01:30:17 +0000
Date:	Fri, 29 Feb 2008 01:30:17 +0000
From:	Thiemo Seufer <ths@networkno.de>
To:	linux-mips@linux-mips.org
Cc:	ralf@linux-mips.org
Subject: [PATCH] Fix PIO IDE on Broadcom SWARM
Message-ID: <20080229013017.GB18731@networkno.de>
MIME-Version: 1.0
Content-Type: text/plain; charset=us-ascii
Content-Disposition: inline
User-Agent: Mutt/1.5.17+20080114 (2008-01-14)
X-archive-position: 18323
X-ecartis-version: Ecartis v1.0.0
Sender:	linux-mips-bounce@linux-mips.org
Errors-to: linux-mips-bounce@linux-mips.org
X-original-sender: ths@networkno.de
Precedence: bulk
X-list:	linux-mips
Return-Path: linux-mips-bounce@linux-mips.org
X-OriginalArrivalTime: 29 Feb 2008 01:31:02.0767 (UTC) FILETIME=[BEE617F0:01C87A72]

This patch marks pages tainted by PIO IDE as dirty, instead of trying
to flush them right away. This

a) fixes PIO IDE for systems without dcache aliases (which lacked
   the necessary cache flush so far)
b) improves performance a bit, since some pages may never need a
   cache flush
c) obsoletes local_flush_data_cache_page


Signed-off-by: Thiemo Seufer <ths@networkno.de>

Index: linux.git/include/asm-mips/mach-generic/ide.h
===================================================================
--- linux.git.orig/include/asm-mips/mach-generic/ide.h	2008-02-29 00:16:03.000000000 +0000
+++ linux.git/include/asm-mips/mach-generic/ide.h	2008-02-29 00:23:59.000000000 +0000
@@ -107,107 +107,66 @@
 #endif
 
 /* MIPS port and memory-mapped I/O string operations.  */
-static inline void __ide_flush_prologue(void)
+static inline void __ide_set_pages_dirty(void *addr, unsigned long size)
 {
-#ifdef CONFIG_SMP
-	if (cpu_has_dc_aliases)
-		preempt_disable();
-#endif
-}
+	unsigned long end = addr + size;
 
-static inline void __ide_flush_epilogue(void)
-{
-#ifdef CONFIG_SMP
-	if (cpu_has_dc_aliases)
-		preempt_enable();
-#endif
-}
-
-static inline void __ide_flush_dcache_range(unsigned long addr, unsigned long size)
-{
-	if (cpu_has_dc_aliases) {
-		unsigned long end = addr + size;
-
-		while (addr < end) {
-			local_flush_data_cache_page((void *)addr);
-			addr += PAGE_SIZE;
-		}
+	while (addr < end) {
+		SetPageDcacheDirty(virt_to_page(addr));
+		addr += PAGE_SIZE;
 	}
 }
 
-/*
- * insw() and gang might be called with interrupts disabled, so we can't
- * send IPIs for flushing due to the potencial of deadlocks, see the comment
- * above smp_call_function() in arch/mips/kernel/smp.c.  We work around the
- * problem by disabling preemption so we know we actually perform the flush
- * on the processor that actually has the lines to be flushed which hopefully
- * is even better for performance anyway.
- */
 static inline void __ide_insw(unsigned long port, void *addr,
 	unsigned int count)
 {
-	__ide_flush_prologue();
 	insw(port, addr, count);
-	__ide_flush_dcache_range((unsigned long)addr, count * 2);
-	__ide_flush_epilogue();
+	__ide_set_pages_dirty(addr, count * 2);
 }
 
-static inline void __ide_insl(unsigned long port, void *addr, unsigned int count)
+static inline void __ide_insl(unsigned long port, void *addr,
+	unsigned int count)
 {
-	__ide_flush_prologue();
 	insl(port, addr, count);
-	__ide_flush_dcache_range((unsigned long)addr, count * 4);
-	__ide_flush_epilogue();
+	__ide_set_pages_dirty(addr, count * 4);
 }
 
 static inline void __ide_outsw(unsigned long port, const void *addr,
 	unsigned long count)
 {
-	__ide_flush_prologue();
 	outsw(port, addr, count);
-	__ide_flush_dcache_range((unsigned long)addr, count * 2);
-	__ide_flush_epilogue();
+	__ide_set_pages_dirty(addr, count * 2);
 }
 
 static inline void __ide_outsl(unsigned long port, const void *addr,
 	unsigned long count)
 {
-	__ide_flush_prologue();
 	outsl(port, addr, count);
-	__ide_flush_dcache_range((unsigned long)addr, count * 4);
-	__ide_flush_epilogue();
+	__ide_set_pages_dirty(addr, count * 4);
 }
 
 static inline void __ide_mm_insw(void __iomem *port, void *addr, u32 count)
 {
-	__ide_flush_prologue();
 	readsw(port, addr, count);
-	__ide_flush_dcache_range((unsigned long)addr, count * 2);
-	__ide_flush_epilogue();
+	__ide_set_pages_dirty(addr, count * 2);
 }
 
 static inline void __ide_mm_insl(void __iomem *port, void *addr, u32 count)
 {
-	__ide_flush_prologue();
 	readsl(port, addr, count);
-	__ide_flush_dcache_range((unsigned long)addr, count * 4);
-	__ide_flush_epilogue();
+	__ide_set_pages_dirty(addr, count * 4);
 }
 
 static inline void __ide_mm_outsw(void __iomem *port, void *addr, u32 count)
 {
-	__ide_flush_prologue();
 	writesw(port, addr, count);
-	__ide_flush_dcache_range((unsigned long)addr, count * 2);
-	__ide_flush_epilogue();
+	__ide_set_pages_dirty(addr, count * 2);
 }
 
 static inline void __ide_mm_outsl(void __iomem * port, void *addr, u32 count)
 {
-	__ide_flush_prologue();
 	writesl(port, addr, count);
-	__ide_flush_dcache_range((unsigned long)addr, count * 4);
-	__ide_flush_epilogue();
+	__ide_set_pages_dirty(addr, count * 4);
 }
 
 /* ide_insw calls insw, not __ide_insw.  Why? */
Index: linux.git/arch/mips/mm/c-r3k.c
===================================================================
--- linux.git.orig/arch/mips/mm/c-r3k.c	2008-02-29 00:53:35.000000000 +0000
+++ linux.git/arch/mips/mm/c-r3k.c	2008-02-29 00:53:55.000000000 +0000
@@ -266,10 +266,6 @@
 		r3k_flush_icache_range(kaddr, kaddr + PAGE_SIZE);
 }
 
-static void local_r3k_flush_data_cache_page(void *addr)
-{
-}
-
 static void r3k_flush_data_cache_page(unsigned long addr)
 {
 }
@@ -322,7 +318,6 @@
 	flush_icache_range = r3k_flush_icache_range;
 
 	flush_cache_sigtramp = r3k_flush_cache_sigtramp;
-	local_flush_data_cache_page = local_r3k_flush_data_cache_page;
 	flush_data_cache_page = r3k_flush_data_cache_page;
 
 	_dma_cache_wback_inv = r3k_dma_cache_wback_inv;
Index: linux.git/arch/mips/mm/c-r4k.c
===================================================================
--- linux.git.orig/arch/mips/mm/c-r4k.c	2008-02-29 00:53:34.000000000 +0000
+++ linux.git/arch/mips/mm/c-r4k.c	2008-02-29 00:55:47.000000000 +0000
@@ -1289,7 +1289,6 @@
 
 	flush_cache_sigtramp	= r4k_flush_cache_sigtramp;
 	flush_icache_all	= r4k_flush_icache_all;
-	local_flush_data_cache_page	= local_r4k_flush_data_cache_page;
 	flush_data_cache_page	= r4k_flush_data_cache_page;
 	flush_icache_range	= r4k_flush_icache_range;
 
Index: linux.git/arch/mips/mm/c-tx39.c
===================================================================
--- linux.git.orig/arch/mips/mm/c-tx39.c	2008-02-29 00:53:34.000000000 +0000
+++ linux.git/arch/mips/mm/c-tx39.c	2008-02-29 00:54:46.000000000 +0000
@@ -210,11 +210,6 @@
 		tx39_blast_icache_page_indexed(page);
 }
 
-static void local_tx39_flush_data_cache_page(void * addr)
-{
-	tx39_blast_dcache_page((unsigned long)addr);
-}
-
 static void tx39_flush_data_cache_page(unsigned long addr)
 {
 	tx39_blast_dcache_page(addr);
@@ -352,7 +347,6 @@
 		flush_icache_range	= (void *) tx39h_flush_icache_all;
 
 		flush_cache_sigtramp	= (void *) tx39h_flush_icache_all;
-		local_flush_data_cache_page	= (void *) tx39h_flush_icache_all;
 		flush_data_cache_page	= (void *) tx39h_flush_icache_all;
 
 		_dma_cache_wback_inv	= tx39h_dma_cache_wback_inv;
@@ -377,7 +371,6 @@
 		flush_icache_range = tx39_flush_icache_range;
 
 		flush_cache_sigtramp = tx39_flush_cache_sigtramp;
-		local_flush_data_cache_page = local_tx39_flush_data_cache_page;
 		flush_data_cache_page = tx39_flush_data_cache_page;
 
 		_dma_cache_wback_inv = tx39_dma_cache_wback_inv;
Index: linux.git/arch/mips/mm/cache.c
===================================================================
--- linux.git.orig/arch/mips/mm/cache.c	2008-02-29 00:53:34.000000000 +0000
+++ linux.git/arch/mips/mm/cache.c	2008-02-29 00:56:58.000000000 +0000
@@ -32,11 +32,9 @@
 
 /* MIPS specific cache operations */
 void (*flush_cache_sigtramp)(unsigned long addr);
-void (*local_flush_data_cache_page)(void * addr);
 void (*flush_data_cache_page)(unsigned long addr);
 void (*flush_icache_all)(void);
 
-EXPORT_SYMBOL_GPL(local_flush_data_cache_page);
 EXPORT_SYMBOL(flush_data_cache_page);
 
 #ifdef CONFIG_DMA_NONCOHERENT
Index: linux.git/include/asm-mips/cacheflush.h
===================================================================
--- linux.git.orig/include/asm-mips/cacheflush.h	2008-02-29 00:53:34.000000000 +0000
+++ linux.git/include/asm-mips/cacheflush.h	2008-02-29 00:57:12.000000000 +0000
@@ -76,7 +76,6 @@
 
 extern void (*flush_cache_sigtramp)(unsigned long addr);
 extern void (*flush_icache_all)(void);
-extern void (*local_flush_data_cache_page)(void * addr);
 extern void (*flush_data_cache_page)(unsigned long addr);
 
 /*

