[SPARC32]: Fix sun4d sbus and current handling.

Linux Kernel Mailing List <[email protected]> Wed, 16 Mar 2005 18:57:39 +0000
Newsgroups gmane.linux.kernel.commits.2-4
Message-ID <[email protected]>
ChangeSet 1.1560.1.6, 2005/03/16 10:57:39-08:00, [email protected]

	[SPARC32]: Fix sun4d sbus and current handling.
	
	- ASI_M_VIKING_TMP2 is only available on SuperSparc-I so
	  we cannot use it to store the current task pointer.
	  Use ASI_M_VIKING_TMP1 instead which is available on all
	  sun4d processors.
	- Apply sun4d IOUNIT ranges to SBUS bus ranges.
	
	Signed-off-by: David S. Miller <[email protected]>



 arch/sparc/kernel/sun4d_smp.c |   18 +++++-------------
 arch/sparc/mm/io-unit.c       |    2 +-
 arch/sparc/prom/ranges.c      |    2 +-
 drivers/sbus/sbus.c           |   16 ++++++++++++++++
 include/asm-sparc/asi.h       |    3 ++-
 include/asm-sparc/oplib.h     |    3 +++
 include/asm-sparc/winmacro.h  |    9 ++++++---
 7 files changed, 34 insertions(+), 19 deletions(-)


diff -Nru a/arch/sparc/kernel/sun4d_smp.c b/arch/sparc/kernel/sun4d_smp.c
--- a/arch/sparc/kernel/sun4d_smp.c	2005-03-16 15:02:54 -08:00
+++ b/arch/sparc/kernel/sun4d_smp.c	2005-03-16 15:02:54 -08:00
@@ -132,8 +132,7 @@
 		
 	/* Fix idle thread fields. */
 	__asm__ __volatile__("ld [%0], %%g6\n\t"
-			     "sta %%g6, [%%g0] %1\n\t"
-			     : : "r" (&current_set[cpuid]), "i" (ASI_M_VIKING_TMP2)
+			     : : "r" (&current_set[cpuid])
 			     : "memory" /* paranoid */);
 
 	cpu_leds[cpuid] = 0x9;
@@ -494,25 +493,18 @@
 
 void __init smp4d_blackbox_current(unsigned *addr)
 {
-	/* We have a nice Linux current register :) */
-	int rd = addr[1] & 0x3e000000;
+	int rd = *addr & 0x3e000000;
 	
-	addr[0] = 0x10800006;			/* b .+24 */
-	addr[1] = 0xc0800820 | rd;		/* lda [%g0] ASI_M_VIKING_TMP2, reg */
+	addr[0] = 0xc0800800 | rd;		/* lda [%g0] ASI_M_VIKING_TMP1, reg */
+	addr[2] = 0x81282002 | rd | (rd >> 11);	/* sll reg, 2, reg */
+	addr[4] = 0x01000000;			/* nop */
 }
 
 void __init sun4d_init_smp(void)
 {
 	int i;
-	extern unsigned int patchme_store_new_current[];
 	extern unsigned int t_nmi[], linux_trap_ipi15_sun4d[], linux_trap_ipi15_sun4m[];
 
-	/* Store current into Linux current register :) */
-	__asm__ __volatile__("sta %%g6, [%%g0] %0" : : "i"(ASI_M_VIKING_TMP2));
-	
-	/* Patch switch_to */
-	patchme_store_new_current[0] = (patchme_store_new_current[0] & 0x3e000000) | 0xc0a00820;
-	
 	/* Patch ipi15 trap table */
 	t_nmi[1] = t_nmi[1] + (linux_trap_ipi15_sun4d - linux_trap_ipi15_sun4m);
 	
diff -Nru a/arch/sparc/mm/io-unit.c b/arch/sparc/mm/io-unit.c
--- a/arch/sparc/mm/io-unit.c	2005-03-16 15:02:54 -08:00
+++ b/arch/sparc/mm/io-unit.c	2005-03-16 15:02:54 -08:00
@@ -188,7 +188,7 @@
 			pte_t *ptep;
 			long i;
 
-			pgdp = pgd_offset(init_task.mm, addr);
+			pgdp = pgd_offset(&init_mm, addr);
 			pmdp = pmd_offset(pgdp, addr);
 			ptep = pte_offset(pmdp, addr);
 
diff -Nru a/arch/sparc/prom/ranges.c b/arch/sparc/prom/ranges.c
--- a/arch/sparc/prom/ranges.c	2005-03-16 15:02:54 -08:00
+++ b/arch/sparc/prom/ranges.c	2005-03-16 15:02:54 -08:00
@@ -34,7 +34,7 @@
 	}
 }
 
-static void
+void
 prom_adjust_ranges(struct linux_prom_ranges *ranges1, int nranges1,
 		   struct linux_prom_ranges *ranges2, int nranges2)
 {
diff -Nru a/drivers/sbus/sbus.c b/drivers/sbus/sbus.c
--- a/drivers/sbus/sbus.c	2005-03-16 15:02:54 -08:00
+++ b/drivers/sbus/sbus.c	2005-03-16 15:02:54 -08:00
@@ -215,6 +215,8 @@
  * prom_sbus_ranges_init(), with all sun4d stuff cut away.
  * Ask DaveM what is going on here, how is sun4d supposed to work... XXX
  */
+/* added back sun4d patch from Thomas Bogendoerfer - should be OK (crn) */
+
 static void __init sbus_bus_ranges_init(int parent_node, struct sbus_bus *sbus)
 {
 	int len;
@@ -227,6 +229,20 @@
 		return;
 	}
 	sbus->num_sbus_ranges = len / sizeof(struct linux_prom_ranges);
+#ifdef CONFIG_SPARC32
+	if (sparc_cpu_model == sun4d) {
+		struct linux_prom_ranges iounit_ranges[PROMREG_MAX];
+		int num_iounit_ranges;
+
+		len = prom_getproperty(parent_node, "ranges",
+				       (char *) iounit_ranges,
+				       sizeof (iounit_ranges));
+		if (len != -1) {
+			num_iounit_ranges = (len/sizeof(struct linux_prom_ranges));
+			prom_adjust_ranges (sbus->sbus_ranges, sbus->num_sbus_ranges, iounit_ranges, num_iounit_ranges);
+		}
+	}
+#endif
 }
 
 static void __init __apply_ranges_to_regs(struct linux_prom_ranges *ranges,
diff -Nru a/include/asm-sparc/asi.h b/include/asm-sparc/asi.h
--- a/include/asm-sparc/asi.h	2005-03-16 15:02:54 -08:00
+++ b/include/asm-sparc/asi.h	2005-03-16 15:02:54 -08:00
@@ -104,7 +104,8 @@
 #define ASI_M_DCDR         0x39   /* Data Cache Diagnostics Register rw, ss */
 
 #define ASI_M_VIKING_TMP1  0x40	  /* Emulation temporary 1 on Viking */
-#define ASI_M_VIKING_TMP2  0x41	  /* Emulation temporary 2 on Viking */
+/* only available on SuperSparc I */
+/* #define ASI_M_VIKING_TMP2  0x41 */  /* Emulation temporary 2 on Viking */
 
 #define ASI_M_ACTION       0x4c   /* Breakpoint Action Register (GNU/Viking) */
 
diff -Nru a/include/asm-sparc/oplib.h b/include/asm-sparc/oplib.h
--- a/include/asm-sparc/oplib.h	2005-03-16 15:02:54 -08:00
+++ b/include/asm-sparc/oplib.h	2005-03-16 15:02:54 -08:00
@@ -296,6 +296,9 @@
 
 /* Dorking with Bus ranges... */
 
+extern void prom_adjust_ranges(struct linux_prom_ranges *, int,
+			       struct linux_prom_ranges *, int);
+
 /* Apply promlib probes OBIO ranges to registers. */
 extern void prom_apply_obio_ranges(struct linux_prom_registers *obioregs, int nregs);
 
diff -Nru a/include/asm-sparc/winmacro.h b/include/asm-sparc/winmacro.h
--- a/include/asm-sparc/winmacro.h	2005-03-16 15:02:54 -08:00
+++ b/include/asm-sparc/winmacro.h	2005-03-16 15:02:54 -08:00
@@ -113,9 +113,12 @@
 	and      %idreg, 0xc, %idreg; \
 	ld       [%idreg + %dest_reg], %dest_reg;
 
-/* Sliiick. We have a Linux current register :) -jj */
-#define LOAD_CURRENT4D(dest_reg) \
-	lda	 [%g0] ASI_M_VIKING_TMP2, %dest_reg;
+#define LOAD_CURRENT4D(dest_reg, idreg) \
+	lda	 [%g0] ASI_M_VIKING_TMP1, %idreg; \
+	sethi	%hi(C_LABEL(current_set)), %dest_reg; \
+	sll	%idreg, 2, %idreg; \
+	or	%dest_reg, %lo(C_LABEL(current_set)), %dest_reg; \
+	ld	[%idreg + %dest_reg], %dest_reg;
 
 /* Blackbox - take care with this... - check smp4m and smp4d before changing this. */
 #define LOAD_CURRENT(dest_reg, idreg) 					\