Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>

+79 -13
+9
arch/sparc/include/asm/memctrl.h
··· 1 + #ifndef _SPARC_MEMCTRL_H 2 + #define _SPARC_MEMCTRL_H 3 + 4 + typedef int (*dimm_printer_t)(int synd_code, unsigned long paddr, char *buf, int buflen); 5 + 6 + int register_dimm_printer(dimm_printer_t func); 7 + void unregister_dimm_printer(dimm_printer_t func); 8 + 9 + #endif /* _SPARC_MEMCTRL_H */
+16 -5
arch/sparc64/kernel/chmc.c
··· 22 22 #include <asm/prom.h> 23 23 #include <asm/head.h> 24 24 #include <asm/io.h> 25 + #include <asm/memctrl.h> 25 26 26 27 #define DRV_MODULE_NAME "chmc" 27 28 #define PFX DRV_MODULE_NAME ": " ··· 159 158 /* This is the main purpose of this driver. */ 160 159 #define SYNDROME_MIN -1 161 160 #define SYNDROME_MAX 144 162 - int chmc_getunumber(int syndrome_code, 163 - unsigned long phys_addr, 164 - char *buf, int buflen) 161 + static int chmc_print_dimm(int syndrome_code, 162 + unsigned long phys_addr, 163 + char *buf, int buflen) 165 164 { 166 165 struct chmc_bank_info *bp; 167 166 struct chmc_obp_mem_layout *prop; ··· 467 466 468 467 static int __init chmc_init(void) 469 468 { 469 + int ret; 470 + 470 471 if (!chmc_platform()) 471 472 return -ENODEV; 472 473 473 - return of_register_driver(&chmc_driver, &of_bus_type); 474 + ret = register_dimm_printer(chmc_print_dimm); 475 + if (!ret) { 476 + ret = of_register_driver(&chmc_driver, &of_bus_type); 477 + if (ret) 478 + unregister_dimm_printer(chmc_print_dimm); 479 + } 480 + return ret; 474 481 } 475 482 476 483 static void __exit chmc_cleanup(void) 477 484 { 478 - if (chmc_platform()) 485 + if (chmc_platform()) { 486 + unregister_dimm_printer(chmc_print_dimm); 479 487 of_unregister_driver(&chmc_driver); 488 + } 480 489 } 481 490 482 491 module_init(chmc_init);
+54 -8
arch/sparc64/kernel/traps.c
··· 37 37 #include <asm/timer.h> 38 38 #include <asm/head.h> 39 39 #include <asm/prom.h> 40 + #include <asm/memctrl.h> 40 41 41 42 #include "entry.h" 42 43 #include "kstack.h" ··· 128 127 printk("kernel BUG at %s:%d!\n", file, line); 129 128 } 130 129 #endif 130 + 131 + static DEFINE_SPINLOCK(dimm_handler_lock); 132 + static dimm_printer_t dimm_handler; 133 + 134 + static int sprintf_dimm(int synd_code, unsigned long paddr, char *buf, int buflen) 135 + { 136 + unsigned long flags; 137 + int ret = -ENODEV; 138 + 139 + spin_lock_irqsave(&dimm_handler_lock, flags); 140 + if (dimm_handler) { 141 + ret = dimm_handler(synd_code, paddr, buf, buflen); 142 + } else if (tlb_type == spitfire) { 143 + if (prom_getunumber(synd_code, paddr, buf, buflen) == -1) 144 + ret = -EINVAL; 145 + else 146 + ret = 0; 147 + } else 148 + ret = -ENODEV; 149 + spin_unlock_irqrestore(&dimm_handler_lock, flags); 150 + 151 + return ret; 152 + } 153 + 154 + int register_dimm_printer(dimm_printer_t func) 155 + { 156 + unsigned long flags; 157 + int ret = 0; 158 + 159 + spin_lock_irqsave(&dimm_handler_lock, flags); 160 + if (!dimm_handler) 161 + dimm_handler = func; 162 + else 163 + ret = -EEXIST; 164 + spin_unlock_irqrestore(&dimm_handler_lock, flags); 165 + 166 + return ret; 167 + } 168 + 169 + void unregister_dimm_printer(dimm_printer_t func) 170 + { 171 + unsigned long flags; 172 + 173 + spin_lock_irqsave(&dimm_handler_lock, flags); 174 + if (dimm_handler == func) 175 + dimm_handler = NULL; 176 + spin_unlock_irqrestore(&dimm_handler_lock, flags); 177 + } 178 + 131 179 132 180 void spitfire_insn_access_exception(struct pt_regs *regs, unsigned long sfsr, unsigned long sfar) 133 181 { ··· 425 375 426 376 if (udbl & bit) { 427 377 scode = ecc_syndrome_table[udbl & 0xff]; 428 - if (prom_getunumber(scode, afar, 429 - memmod_str, sizeof(memmod_str)) == -1) 378 + if (sprintf_dimm(scode, afar, memmod_str, sizeof(memmod_str)) < 0) 430 379 p = syndrome_unknown; 431 380 else 432 381 p = memmod_str; ··· 436 387 437 388 if (udbh & bit) { 438 389 scode = ecc_syndrome_table[udbh & 0xff]; 439 - if (prom_getunumber(scode, afar, 440 - memmod_str, sizeof(memmod_str)) == -1) 390 + if (sprintf_dimm(scode, afar, memmod_str, sizeof(memmod_str)) < 0) 441 391 p = syndrome_unknown; 442 392 else 443 393 p = memmod_str; ··· 1109 1061 return "???"; 1110 1062 } 1111 1063 1112 - extern int chmc_getunumber(int, unsigned long, char *, int); 1113 - 1114 1064 static void cheetah_log_errors(struct pt_regs *regs, struct cheetah_err_info *info, 1115 1065 unsigned long afsr, unsigned long afar, int recoverable) 1116 1066 { ··· 1150 1104 1151 1105 syndrome = (afsr & CHAFSR_E_SYNDROME) >> CHAFSR_E_SYNDROME_SHIFT; 1152 1106 syndrome = cheetah_ecc_syntab[syndrome]; 1153 - ret = chmc_getunumber(syndrome, afar, unum, sizeof(unum)); 1107 + ret = sprintf_dimm(syndrome, afar, unum, sizeof(unum)); 1154 1108 if (ret != -1) 1155 1109 printk("%s" "ERROR(%d): AFAR E-syndrome [%s]\n", 1156 1110 (recoverable ? KERN_WARNING : KERN_CRIT), ··· 1161 1115 1162 1116 syndrome = (afsr & CHAFSR_M_SYNDROME) >> CHAFSR_M_SYNDROME_SHIFT; 1163 1117 syndrome = cheetah_mtag_syntab[syndrome]; 1164 - ret = chmc_getunumber(syndrome, afar, unum, sizeof(unum)); 1118 + ret = sprintf_dimm(syndrome, afar, unum, sizeof(unum)); 1165 1119 if (ret != -1) 1166 1120 printk("%s" "ERROR(%d): AFAR M-syndrome [%s]\n", 1167 1121 (recoverable ? KERN_WARNING : KERN_CRIT),