aboutsummaryrefslogtreecommitdiffstats
path: root/arch
diff options
context:
space:
mode:
authorDavid S. Miller <davem@davemloft.net>2008-08-25 01:08:34 -0400
committerDavid S. Miller <davem@davemloft.net>2008-08-25 01:08:34 -0400
commit881d021ab0d675f519b68df916fde969940ef988 (patch)
treeb4b60a1d2a0a25c8b1f1fbf322a44d89817a22da /arch
parent83ef64b9dea6e3ed287a45d56166913bffcd2497 (diff)
sparc64: Add generic interface for registering a dimm printing handler.
The way to do this varies by platform type and the exact memory controller the cpu uses. For Spitfire cpus we currently just use prom_getunumber() and hope that works. For Cheetah cpus we have a memory controller driver that can compute this information. Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'arch')
-rw-r--r--arch/sparc/include/asm/memctrl.h9
-rw-r--r--arch/sparc64/kernel/chmc.c21
-rw-r--r--arch/sparc64/kernel/traps.c62
3 files changed, 79 insertions, 13 deletions
diff --git a/arch/sparc/include/asm/memctrl.h b/arch/sparc/include/asm/memctrl.h
new file mode 100644
index 000000000000..4065c56af7b6
--- /dev/null
+++ b/arch/sparc/include/asm/memctrl.h
@@ -0,0 +1,9 @@
1#ifndef _SPARC_MEMCTRL_H
2#define _SPARC_MEMCTRL_H
3
4typedef int (*dimm_printer_t)(int synd_code, unsigned long paddr, char *buf, int buflen);
5
6int register_dimm_printer(dimm_printer_t func);
7void unregister_dimm_printer(dimm_printer_t func);
8
9#endif /* _SPARC_MEMCTRL_H */
diff --git a/arch/sparc64/kernel/chmc.c b/arch/sparc64/kernel/chmc.c
index 2f73ddc8676d..a3c79fd5dd31 100644
--- a/arch/sparc64/kernel/chmc.c
+++ b/arch/sparc64/kernel/chmc.c
@@ -22,6 +22,7 @@
22#include <asm/prom.h> 22#include <asm/prom.h>
23#include <asm/head.h> 23#include <asm/head.h>
24#include <asm/io.h> 24#include <asm/io.h>
25#include <asm/memctrl.h>
25 26
26#define DRV_MODULE_NAME "chmc" 27#define DRV_MODULE_NAME "chmc"
27#define PFX DRV_MODULE_NAME ": " 28#define PFX DRV_MODULE_NAME ": "
@@ -158,9 +159,9 @@ static struct chmc_bank_info *chmc_find_bank(unsigned long phys_addr)
158/* This is the main purpose of this driver. */ 159/* This is the main purpose of this driver. */
159#define SYNDROME_MIN -1 160#define SYNDROME_MIN -1
160#define SYNDROME_MAX 144 161#define SYNDROME_MAX 144
161int chmc_getunumber(int syndrome_code, 162static int chmc_print_dimm(int syndrome_code,
162 unsigned long phys_addr, 163 unsigned long phys_addr,
163 char *buf, int buflen) 164 char *buf, int buflen)
164{ 165{
165 struct chmc_bank_info *bp; 166 struct chmc_bank_info *bp;
166 struct chmc_obp_mem_layout *prop; 167 struct chmc_obp_mem_layout *prop;
@@ -466,16 +467,26 @@ static inline bool chmc_platform(void)
466 467
467static int __init chmc_init(void) 468static int __init chmc_init(void)
468{ 469{
470 int ret;
471
469 if (!chmc_platform()) 472 if (!chmc_platform())
470 return -ENODEV; 473 return -ENODEV;
471 474
472 return of_register_driver(&chmc_driver, &of_bus_type); 475 ret = register_dimm_printer(chmc_print_dimm);
476 if (!ret) {
477 ret = of_register_driver(&chmc_driver, &of_bus_type);
478 if (ret)
479 unregister_dimm_printer(chmc_print_dimm);
480 }
481 return ret;
473} 482}
474 483
475static void __exit chmc_cleanup(void) 484static void __exit chmc_cleanup(void)
476{ 485{
477 if (chmc_platform()) 486 if (chmc_platform()) {
487 unregister_dimm_printer(chmc_print_dimm);
478 of_unregister_driver(&chmc_driver); 488 of_unregister_driver(&chmc_driver);
489 }
479} 490}
480 491
481module_init(chmc_init); 492module_init(chmc_init);
diff --git a/arch/sparc64/kernel/traps.c b/arch/sparc64/kernel/traps.c
index 3d924121c796..17880ccfa3cd 100644
--- a/arch/sparc64/kernel/traps.c
+++ b/arch/sparc64/kernel/traps.c
@@ -37,6 +37,7 @@
37#include <asm/timer.h> 37#include <asm/timer.h>
38#include <asm/head.h> 38#include <asm/head.h>
39#include <asm/prom.h> 39#include <asm/prom.h>
40#include <asm/memctrl.h>
40 41
41#include "entry.h" 42#include "entry.h"
42#include "kstack.h" 43#include "kstack.h"
@@ -128,6 +129,55 @@ void do_BUG(const char *file, int line)
128} 129}
129#endif 130#endif
130 131
132static DEFINE_SPINLOCK(dimm_handler_lock);
133static dimm_printer_t dimm_handler;
134
135static int sprintf_dimm(int synd_code, unsigned long paddr, char *buf, int buflen)
136{
137 unsigned long flags;
138 int ret = -ENODEV;
139
140 spin_lock_irqsave(&dimm_handler_lock, flags);
141 if (dimm_handler) {
142 ret = dimm_handler(synd_code, paddr, buf, buflen);
143 } else if (tlb_type == spitfire) {
144 if (prom_getunumber(synd_code, paddr, buf, buflen) == -1)
145 ret = -EINVAL;
146 else
147 ret = 0;
148 } else
149 ret = -ENODEV;
150 spin_unlock_irqrestore(&dimm_handler_lock, flags);
151
152 return ret;
153}
154
155int register_dimm_printer(dimm_printer_t func)
156{
157 unsigned long flags;
158 int ret = 0;
159
160 spin_lock_irqsave(&dimm_handler_lock, flags);
161 if (!dimm_handler)
162 dimm_handler = func;
163 else
164 ret = -EEXIST;
165 spin_unlock_irqrestore(&dimm_handler_lock, flags);
166
167 return ret;
168}
169
170void unregister_dimm_printer(dimm_printer_t func)
171{
172 unsigned long flags;
173
174 spin_lock_irqsave(&dimm_handler_lock, flags);
175 if (dimm_handler == func)
176 dimm_handler = NULL;
177 spin_unlock_irqrestore(&dimm_handler_lock, flags);
178}
179
180
131void spitfire_insn_access_exception(struct pt_regs *regs, unsigned long sfsr, unsigned long sfar) 181void spitfire_insn_access_exception(struct pt_regs *regs, unsigned long sfsr, unsigned long sfar)
132{ 182{
133 siginfo_t info; 183 siginfo_t info;
@@ -375,8 +425,7 @@ static void spitfire_log_udb_syndrome(unsigned long afar, unsigned long udbh, un
375 425
376 if (udbl & bit) { 426 if (udbl & bit) {
377 scode = ecc_syndrome_table[udbl & 0xff]; 427 scode = ecc_syndrome_table[udbl & 0xff];
378 if (prom_getunumber(scode, afar, 428 if (sprintf_dimm(scode, afar, memmod_str, sizeof(memmod_str)) < 0)
379 memmod_str, sizeof(memmod_str)) == -1)
380 p = syndrome_unknown; 429 p = syndrome_unknown;
381 else 430 else
382 p = memmod_str; 431 p = memmod_str;
@@ -387,8 +436,7 @@ static void spitfire_log_udb_syndrome(unsigned long afar, unsigned long udbh, un
387 436
388 if (udbh & bit) { 437 if (udbh & bit) {
389 scode = ecc_syndrome_table[udbh & 0xff]; 438 scode = ecc_syndrome_table[udbh & 0xff];
390 if (prom_getunumber(scode, afar, 439 if (sprintf_dimm(scode, afar, memmod_str, sizeof(memmod_str)) < 0)
391 memmod_str, sizeof(memmod_str)) == -1)
392 p = syndrome_unknown; 440 p = syndrome_unknown;
393 else 441 else
394 p = memmod_str; 442 p = memmod_str;
@@ -1061,8 +1109,6 @@ static const char *cheetah_get_string(unsigned long bit)
1061 return "???"; 1109 return "???";
1062} 1110}
1063 1111
1064extern int chmc_getunumber(int, unsigned long, char *, int);
1065
1066static void cheetah_log_errors(struct pt_regs *regs, struct cheetah_err_info *info, 1112static void cheetah_log_errors(struct pt_regs *regs, struct cheetah_err_info *info,
1067 unsigned long afsr, unsigned long afar, int recoverable) 1113 unsigned long afsr, unsigned long afar, int recoverable)
1068{ 1114{
@@ -1104,7 +1150,7 @@ static void cheetah_log_errors(struct pt_regs *regs, struct cheetah_err_info *in
1104 1150
1105 syndrome = (afsr & CHAFSR_E_SYNDROME) >> CHAFSR_E_SYNDROME_SHIFT; 1151 syndrome = (afsr & CHAFSR_E_SYNDROME) >> CHAFSR_E_SYNDROME_SHIFT;
1106 syndrome = cheetah_ecc_syntab[syndrome]; 1152 syndrome = cheetah_ecc_syntab[syndrome];
1107 ret = chmc_getunumber(syndrome, afar, unum, sizeof(unum)); 1153 ret = sprintf_dimm(syndrome, afar, unum, sizeof(unum));
1108 if (ret != -1) 1154 if (ret != -1)
1109 printk("%s" "ERROR(%d): AFAR E-syndrome [%s]\n", 1155 printk("%s" "ERROR(%d): AFAR E-syndrome [%s]\n",
1110 (recoverable ? KERN_WARNING : KERN_CRIT), 1156 (recoverable ? KERN_WARNING : KERN_CRIT),
@@ -1115,7 +1161,7 @@ static void cheetah_log_errors(struct pt_regs *regs, struct cheetah_err_info *in
1115 1161
1116 syndrome = (afsr & CHAFSR_M_SYNDROME) >> CHAFSR_M_SYNDROME_SHIFT; 1162 syndrome = (afsr & CHAFSR_M_SYNDROME) >> CHAFSR_M_SYNDROME_SHIFT;
1117 syndrome = cheetah_mtag_syntab[syndrome]; 1163 syndrome = cheetah_mtag_syntab[syndrome];
1118 ret = chmc_getunumber(syndrome, afar, unum, sizeof(unum)); 1164 ret = sprintf_dimm(syndrome, afar, unum, sizeof(unum));
1119 if (ret != -1) 1165 if (ret != -1)
1120 printk("%s" "ERROR(%d): AFAR M-syndrome [%s]\n", 1166 printk("%s" "ERROR(%d): AFAR M-syndrome [%s]\n",
1121 (recoverable ? KERN_WARNING : KERN_CRIT), 1167 (recoverable ? KERN_WARNING : KERN_CRIT),