Subject: [patch] linux: A wbflush() rework

From: "Maciej W. Rozycki" <[email-masked]>
Date: Mon, 8 Apr 2002 19:16:05 +0200 (MET DST)

Hello,

 Here is a rework of the wbflush() that makes code use iob() and possibly
fast_iob() where appropriate.  Additionally the DECstation __wbflush() 
backends are updated to match reality, yielding better and reliability
performance for I/O ASIC systems.  The code is needed specifically for R4k
not to generate an excessive number of spurious interrupts on DECstation. 

 The code applies on top of the "mb-wb" and "irq" patches. 

 Please apply.

  Maciej

-- 
+  Maciej W. Rozycki, Technical University of Gdansk, Poland   +
+--------------------------------------------------------------+
+        e-mail: [email-masked], PGP key available        +

patch-mips-2.4.18-20020323-wbflush-3
diff -up --recursive --new-file linux-mips-2.4.18-20020323.macro/arch/mips/dec/Makefile linux-mips-2.4.18-20020323/arch/mips/dec/Makefile
--- linux-mips-2.4.18-20020323.macro/arch/mips/dec/Makefile	Tue Jan 22 07:32:00 2002
+++ linux-mips-2.4.18-20020323/arch/mips/dec/Makefile	Mon Feb  4 01:06:32 2002
@@ -17,9 +17,10 @@ all: dec.o
 
 export-objs := setup.o wbflush.o
 obj-y	 := int-handler.o ioasic-irq.o kn02-irq.o reset.o rtc-dec.o setup.o \
-	time.o wbflush.o
+	time.o
 
 obj-$(CONFIG_PROM_CONSOLE)	+= promcon.o
+obj-$(CONFIG_CPU_HAS_WB)	+= wbflush.o
 
 int-handler.o:	int-handler.S
 
diff -up --recursive --new-file linux-mips-2.4.18-20020323.macro/arch/mips/dec/ioasic-irq.c linux-mips-2.4.18-20020323/arch/mips/dec/ioasic-irq.c
--- linux-mips-2.4.18-20020323.macro/arch/mips/dec/ioasic-irq.c	Tue Jan 22 06:44:47 2002
+++ linux-mips-2.4.18-20020323/arch/mips/dec/ioasic-irq.c	Mon Feb  4 01:00:53 2002
@@ -84,6 +84,7 @@ static inline void ack_ioasic_irq(unsign
 	spin_lock(&ioasic_lock);
 	mask_ioasic_irq(irq);
 	spin_unlock(&ioasic_lock);
+	fast_iob();
 }
 
 static inline void end_ioasic_irq(unsigned int irq)
@@ -119,6 +120,7 @@ static struct hw_interrupt_type ioasic_i
 static inline void end_ioasic_dma_irq(unsigned int irq)
 {
 	clear_ioasic_irq(irq);
+	fast_iob();
 	end_ioasic_irq(irq);
 }
 
@@ -142,6 +144,7 @@ void __init init_ioasic_irqs(int base)
 
 	/* Mask interrupts. */
 	ioasic_write(SIMR, 0);
+	fast_iob();
 
 	for (i = base; i < base + IO_INR_DMA; i++) {
 		irq_desc[i].status = IRQ_DISABLED;
diff -up --recursive --new-file linux-mips-2.4.18-20020323.macro/arch/mips/dec/kn02-irq.c linux-mips-2.4.18-20020323/arch/mips/dec/kn02-irq.c
--- linux-mips-2.4.18-20020323.macro/arch/mips/dec/kn02-irq.c	Tue Jan 22 06:47:34 2002
+++ linux-mips-2.4.18-20020323/arch/mips/dec/kn02-irq.c	Mon Feb  4 01:01:59 2002
@@ -83,6 +83,7 @@ static void ack_kn02_irq(unsigned int ir
 	spin_lock(&kn02_lock);
 	mask_kn02_irq(irq);
 	spin_unlock(&kn02_lock);
+	iob();
 }
 
 static void end_kn02_irq(unsigned int irq)
@@ -113,6 +114,7 @@ void __init init_kn02_irqs(int base)
 	/* Mask interrupts and preset write-only bits. */
 	cached_kn02_csr = (*csr & ~0xff0000) | 0xff;
 	*csr = cached_kn02_csr;
+	iob();
 
 	for (i = base; i < base + KN02_IRQ_LINES; i++) {
 		irq_desc[i].status = IRQ_DISABLED;
diff -up --recursive --new-file linux-mips-2.4.18-20020323.macro/arch/mips/dec/setup.c linux-mips-2.4.18-20020323/arch/mips/dec/setup.c
--- linux-mips-2.4.18-20020323.macro/arch/mips/dec/setup.c	Tue Jan 22 07:31:08 2002
+++ linux-mips-2.4.18-20020323/arch/mips/dec/setup.c	Mon Feb  4 01:10:36 2002
@@ -24,6 +24,7 @@
 #include <asm/irq_cpu.h>
 #include <asm/mipsregs.h>
 #include <asm/reboot.h>
+#include <asm/wbflush.h>
 
 #include <asm/dec/interrupts.h>
 #include <asm/dec/kn01.h>
@@ -87,8 +88,6 @@ static struct irqaction fpuirq = {NULL, 
 
 static struct irqaction haltirq = {dec_intr_halt, 0, 0, "halt", NULL, NULL};
 
-
-extern void wbflush_setup(void);
 
 extern struct rtc_ops dec_rtc_ops;
 
diff -up --recursive --new-file linux-mips-2.4.18-20020323.macro/arch/mips/dec/wbflush.c linux-mips-2.4.18-20020323/arch/mips/dec/wbflush.c
--- linux-mips-2.4.18-20020323.macro/arch/mips/dec/wbflush.c	Tue Nov  6 05:26:15 2001
+++ linux-mips-2.4.18-20020323/arch/mips/dec/wbflush.c	Mon Feb  4 01:03:17 2002
@@ -11,15 +11,18 @@
  * for more details.
  *
  * Copyright (C) 1998 Harald Koerfgen
+ * Copyright (C) 2002 Maciej W. Rozycki
  */
 
-#include <asm/bootinfo.h>
 #include <linux/init.h>
 
+#include <asm/bootinfo.h>
+#include <asm/system.h>
+#include <asm/wbflush.h>
+
 static void wbflush_kn01(void);
 static void wbflush_kn210(void);
-static void wbflush_kn02ba(void);
-static void wbflush_kn03(void);
+static void wbflush_mips(void);
 
 void (*__wbflush) (void);
 
@@ -27,28 +30,23 @@ void __init wbflush_setup(void)
 {
 	switch (mips_machtype) {
 	case MACH_DS23100:
-	    __wbflush = wbflush_kn01;
-	    break;
-	case MACH_DS5100:	/*  DS5100 MIPSMATE */
-	    __wbflush = wbflush_kn210;
-	    break;
 	case MACH_DS5000_200:	/* DS5000 3max */
-	    __wbflush = wbflush_kn01;
-	    break;
+		__wbflush = wbflush_kn01;
+		break;
+	case MACH_DS5100:	/* DS5100 MIPSMATE */
+		__wbflush = wbflush_kn210;
+		break;
 	case MACH_DS5000_1XX:	/* DS5000/100 3min */
-	    __wbflush = wbflush_kn02ba;
-	    break;
-	case MACH_DS5000_2X0:	/* DS5000/240 3max+ */
-	    __wbflush = wbflush_kn03;
-	    break;
 	case MACH_DS5000_XX:	/* Personal DS5000/2x */
-	    __wbflush = wbflush_kn02ba;
-	    break;
+	case MACH_DS5000_2X0:	/* DS5000/240 3max+ */
+	default:
+		__wbflush = wbflush_mips;
+		break;
 	}
 }
 
 /*
- * For the DS3100 and DS5000/200 the writeback buffer functions
+ * For the DS3100 and DS5000/200 the R2020/R3220 writeback buffer functions
  * as part of Coprocessor 0.
  */
 static void wbflush_kn01(void)
@@ -78,29 +76,16 @@ static void wbflush_kn210(void)
 	"mtc0\t$2,$12\n\t"
 	"nop\n\t"
 	".set\tpop"
-  : : :"$2", "$3");
-}
-
-/*
- * Looks like some magic with the System Interrupt Mask Register
- * in the famous IOASIC for kmins and maxines.
- */
-static void wbflush_kn02ba(void)
-{
-    asm(".set\tpush\n\t"
-	".set\tnoreorder\n\t"
-	"lui\t$2,0xbc04\n\t"
-	"lw\t$3,0x120($2)\n\t"
-	"lw\t$3,0x120($2)\n\t"
-	".set\tpop"
-  : : :"$2", "$3");
+	: : : "$2", "$3");
 }
 
 /*
- * The DS500/2x0 doesnt need to write back the WB.
+ * I/O ASIC systems use a standard writeback buffer that gets flushed
+ * upon an uncached read.
  */
-static void wbflush_kn03(void)
+static void wbflush_mips(void)
 {
+	__fast_iob();
 }
 
 #include <linux/module.h>
diff -up --recursive --new-file linux-mips-2.4.18-20020323.macro/arch/mips/mm/c-r3k.c linux-mips-2.4.18-20020323/arch/mips/mm/c-r3k.c
--- linux-mips-2.4.18-20020323.macro/arch/mips/mm/c-r3k.c	Tue Feb 19 05:28:14 2002
+++ linux-mips-2.4.18-20020323/arch/mips/mm/c-r3k.c	Sun Mar 24 21:16:14 2002
@@ -19,7 +19,6 @@
 #include <asm/system.h>
 #include <asm/isadep.h>
 #include <asm/io.h>
-#include <asm/wbflush.h>
 #include <asm/bootinfo.h>
 #include <asm/cpu.h>
 
@@ -314,7 +313,7 @@ static void r3k_flush_cache_sigtramp(uns
 
 static void r3k_dma_cache_wback_inv(unsigned long start, unsigned long size)
 {
-	wbflush();
+	iob();
 	r3k_flush_dcache_range(start, start + size);
 }
 
diff -up --recursive --new-file linux-mips-2.4.18-20020323.macro/arch/mips/mm/c-tx39.c linux-mips-2.4.18-20020323/arch/mips/mm/c-tx39.c
--- linux-mips-2.4.18-20020323.macro/arch/mips/mm/c-tx39.c	Sat Dec  1 05:26:01 2001
+++ linux-mips-2.4.18-20020323/arch/mips/mm/c-tx39.c	Mon Feb  4 01:12:41 2002
@@ -20,7 +20,6 @@
 #include <asm/system.h>
 #include <asm/isadep.h>
 #include <asm/io.h>
-#include <asm/wbflush.h>
 #include <asm/bootinfo.h>
 #include <asm/cpu.h>
 
@@ -63,8 +62,8 @@ static void tx39h_flush_icache_all(void)
 static void tx39h_dma_cache_wback_inv(unsigned long addr, unsigned long size)
 {
 	unsigned long end, a;
-	wbflush();
 
+	iob();
 	a = addr & ~(dcache_lsize - 1);
 	end = (addr + size) & ~(dcache_lsize - 1);
 	while (1) {
diff -up --recursive --new-file linux-mips-2.4.18-20020323.macro/arch/mips/mm/tlb-r3k.c linux-mips-2.4.18-20020323/arch/mips/mm/tlb-r3k.c
--- linux-mips-2.4.18-20020323.macro/arch/mips/mm/tlb-r3k.c	Fri Jan 18 05:28:05 2002
+++ linux-mips-2.4.18-20020323/arch/mips/mm/tlb-r3k.c	Mon Feb  4 00:59:46 2002
@@ -19,7 +19,6 @@
 #include <asm/system.h>
 #include <asm/isadep.h>
 #include <asm/io.h>
-#include <asm/wbflush.h>
 #include <asm/bootinfo.h>
 #include <asm/cpu.h>
 
diff -up --recursive --new-file linux-mips-2.4.18-20020323.macro/drivers/char/dz.c linux-mips-2.4.18-20020323/drivers/char/dz.c
--- linux-mips-2.4.18-20020323.macro/drivers/char/dz.c	Sun Jan 20 21:37:53 2002
+++ linux-mips-2.4.18-20020323/drivers/char/dz.c	Mon Feb  4 01:13:30 2002
@@ -35,7 +35,6 @@
 #include <linux/param.h>
 #include <linux/tqueue.h>
 #include <linux/interrupt.h>
-#include <asm-mips/wbflush.h>
 #include <asm/dec/interrupts.h>
 
 #include <linux/console.h>
@@ -53,6 +52,8 @@
 #include <linux/fs.h>
 #include <asm/bootinfo.h>
 
+#include <asm/system.h>
+
 #define CONSOLE_LINE (3)	/* for definition of struct console */
 
 extern int (*prom_printf) (char *,...);
@@ -1420,7 +1421,7 @@ int __init dz_init(void)
 #ifndef CONFIG_SERIAL_CONSOLE
 	dz_out(info, DZ_CSR, DZ_CLR);
 	while ((tmp = dz_in(info, DZ_CSR)) & DZ_CLR);
-	wbflush();
+	iob();
 
 	/* enable scanning */
 	dz_out(info, DZ_CSR, DZ_MSE);
diff -up --recursive --new-file linux-mips-2.4.18-20020323.macro/drivers/net/declance.c linux-mips-2.4.18-20020323/drivers/net/declance.c
--- linux-mips-2.4.18-20020323.macro/drivers/net/declance.c	Sun Mar 24 20:58:18 2002
+++ linux-mips-2.4.18-20020323/drivers/net/declance.c	Sun Mar 24 21:16:14 2002
@@ -60,7 +60,7 @@ static char *lancestr = "lance";
 #include <asm/dec/machtype.h>
 #include <asm/dec/tc.h>
 #include <asm/dec/kn01.h>
-#include <asm/wbflush.h>
+#include <asm/system.h>
 #include <asm/addrspace.h>
 
 #include <linux/config.h>
@@ -306,7 +306,7 @@ int dec_lance_debug = 2;
 static inline void writereg(volatile unsigned short *regptr, short value)
 {
 	*regptr = value;
-	wbflush();
+	iob();
 }
 
 /* Load the CSR registers */
@@ -386,7 +386,7 @@ void cp_to_buf(void *to, const void *fro
 		}
 	}
 
-	wbflush();
+	iob();
 }
 
 void cp_from_buf(void *to, unsigned char *from, int len)
@@ -514,7 +514,7 @@ static void lance_init_ring(struct net_d
 		if (i < 3 && ZERO)
 			printk("%d: 0x%8.8x(0x%8.8x)\n", i, leptr, (int) lp->rx_buf_ptr_cpu[i]);
 	}
-	wbflush();
+	iob();
 }
 
 static int init_restart_lance(struct lance_private *lp)
@@ -1084,7 +1084,7 @@ static int __init dec_lance_init(struct 
 		lp->dma_ptr_reg = (unsigned long *) (system_base + IOCTL + LANCE_DMA_P);
 		*(lp->dma_ptr_reg) = PHYSADDR(dev->mem_start) << 3;
 		*(unsigned long *) (system_base + IOCTL + SSR) |= (1 << 16);
-		wbflush();
+		fast_iob();
 
 		break;
 	case PMAD_LANCE:
diff -up --recursive --new-file linux-mips-2.4.18-20020323.macro/drivers/scsi/NCR53C9x.h linux-mips-2.4.18-20020323/drivers/scsi/NCR53C9x.h
--- linux-mips-2.4.18-20020323.macro/drivers/scsi/NCR53C9x.h	Fri Oct 19 04:29:11 2001
+++ linux-mips-2.4.18-20020323/drivers/scsi/NCR53C9x.h	Mon Feb  4 01:14:34 2002
@@ -144,12 +144,7 @@
 
 #ifndef MULTIPLE_PAD_SIZES
 
-#ifdef CONFIG_CPU_HAS_WB
-#include <asm/wbflush.h>
-#define esp_write(__reg, __val) do{(__reg) = (__val); wbflush();} while(0)
-#else
-#define esp_write(__reg, __val) ((__reg) = (__val))
-#endif
+#define esp_write(__reg, __val) do{(__reg) = (__val); iob();} while(0)
 #define esp_read(__reg) (__reg)
 
 struct ESP_regs {
diff -up --recursive --new-file linux-mips-2.4.18-20020323.macro/drivers/scsi/dec_esp.c linux-mips-2.4.18-20020323/drivers/scsi/dec_esp.c
--- linux-mips-2.4.18-20020323.macro/drivers/scsi/dec_esp.c	Tue Jan 22 03:06:51 2002
+++ linux-mips-2.4.18-20020323/drivers/scsi/dec_esp.c	Mon Feb  4 01:15:48 2002
@@ -46,6 +46,8 @@
 #include <asm/dec/ioasic_ints.h>
 #include <asm/dec/machtype.h>
 
+#include <asm/system.h>
+
 /*
  * Once upon a time the pmaz code used to be working but
  * it hasn't been maintained for quite some time.
@@ -308,17 +310,9 @@ static void scsi_dma_err_int(int irq, vo
 
 static void scsi_dma_int(int irq, void *dev_id, struct pt_regs *regs)
 {
-	volatile unsigned int *dummy = (volatile unsigned int *)KSEG1;
-
 	/* next page */
 	*scsi_next_ptr = ((*scsi_dma_ptr + PAGE_SIZE) & PAGE_MASK) << 3;
-
-	/*
-	 * This routine will only work on IOASIC machines
-	 * so we can avoid an indirect function call here
-	 * and flush the writeback buffer the fast way
-	 */
-	*dummy;
+	fast_iob();
 }
 
 static int dma_bytes_sent(struct NCR_ESP *esp, int fifo_count)
@@ -370,8 +364,6 @@ static void dma_dump_state(struct NCR_ES
 
 static void dma_init_read(struct NCR_ESP *esp, __u32 vaddress, int length)
 {
-	volatile unsigned int *dummy = (volatile unsigned int *)KSEG1;
-
 	if (vaddress & 3)
 		panic("dec_efs.c: unable to handle partial word transfers, yet...");
 
@@ -384,17 +376,11 @@ static void dma_init_read(struct NCR_ESP
 	/* prepare for next page */
 	*scsi_next_ptr = ((vaddress + PAGE_SIZE) & PAGE_MASK) << 3;
 	*ioasic_ssr |= (SCSI_DMA_DIR | SCSI_DMA_EN);
-
-	/*
-	 * see above
-	 */
-	*dummy;
+	fast_iob();
 }
 
 static void dma_init_write(struct NCR_ESP *esp, __u32 vaddress, int length)
 {
-	volatile unsigned int *dummy = (volatile unsigned int *)KSEG1;
-
 	if (vaddress & 3)
 		panic("dec_efs.c: unable to handle partial word transfers, yet...");
 
@@ -407,11 +393,7 @@ static void dma_init_write(struct NCR_ES
 	/* prepare for next page */
 	*scsi_next_ptr = ((vaddress + PAGE_SIZE) & PAGE_MASK) << 3;
 	*ioasic_ssr |= SCSI_DMA_EN;
-
-	/*
-	 * see above
-	 */
-	*dummy;
+	fast_iob();
 }
 
 static void dma_ints_off(struct NCR_ESP *esp)
diff -up --recursive --new-file linux-mips-2.4.18-20020323.macro/drivers/tc/zs.c linux-mips-2.4.18-20020323/drivers/tc/zs.c
--- linux-mips-2.4.18-20020323.macro/drivers/tc/zs.c	Sun Mar 24 21:02:44 2002
+++ linux-mips-2.4.18-20020323/drivers/tc/zs.c	Sun Mar 24 21:16:14 2002
@@ -67,7 +67,6 @@
 #include <asm/segment.h>
 #include <asm/bitops.h>
 #include <asm/uaccess.h>
-#include <asm/wbflush.h>
 #include <asm/bootinfo.h>
 #ifdef CONFIG_DECSTATION
 #include <asm/dec/interrupts.h>
@@ -276,7 +275,7 @@ static inline unsigned char read_zsreg(s
 
 	if (reg != 0) {
 		*channel->control = reg & 0xf;
-		wbflush(); RECOVERY_DELAY;
+		fast_iob(); RECOVERY_DELAY;
 	}
 	retval = *channel->control;
 	RECOVERY_DELAY;
@@ -288,10 +287,10 @@ static inline void write_zsreg(struct de
 {
 	if (reg != 0) {
 		*channel->control = reg & 0xf;
-		wbflush(); RECOVERY_DELAY;
+		fast_iob(); RECOVERY_DELAY;
 	}
 	*channel->control = value;
-	wbflush(); RECOVERY_DELAY;
+	fast_iob(); RECOVERY_DELAY;
 	return;
 }
 
@@ -308,7 +307,7 @@ static inline void write_zsdata(struct d
 				unsigned char value)
 {
 	*channel->data = value;
-	wbflush(); RECOVERY_DELAY;
+	fast_iob(); RECOVERY_DELAY;
 	return;
 }