Skip to content

Commit

Permalink
sparc64: Add generic interface for registering a dimm printing handler.
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
David S. Miller committed Aug 25, 2008
1 parent 83ef64b commit 881d021
Show file tree
Hide file tree
Showing 3 changed files with 79 additions and 13 deletions.
9 changes: 9 additions & 0 deletions arch/sparc/include/asm/memctrl.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
#ifndef _SPARC_MEMCTRL_H
#define _SPARC_MEMCTRL_H

typedef int (*dimm_printer_t)(int synd_code, unsigned long paddr, char *buf, int buflen);

int register_dimm_printer(dimm_printer_t func);
void unregister_dimm_printer(dimm_printer_t func);

#endif /* _SPARC_MEMCTRL_H */
21 changes: 16 additions & 5 deletions arch/sparc64/kernel/chmc.c
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
#include <asm/prom.h>
#include <asm/head.h>
#include <asm/io.h>
#include <asm/memctrl.h>

#define DRV_MODULE_NAME "chmc"
#define PFX DRV_MODULE_NAME ": "
Expand Down Expand Up @@ -158,9 +159,9 @@ static struct chmc_bank_info *chmc_find_bank(unsigned long phys_addr)
/* This is the main purpose of this driver. */
#define SYNDROME_MIN -1
#define SYNDROME_MAX 144
int chmc_getunumber(int syndrome_code,
unsigned long phys_addr,
char *buf, int buflen)
static int chmc_print_dimm(int syndrome_code,
unsigned long phys_addr,
char *buf, int buflen)
{
struct chmc_bank_info *bp;
struct chmc_obp_mem_layout *prop;
Expand Down Expand Up @@ -466,16 +467,26 @@ static inline bool chmc_platform(void)

static int __init chmc_init(void)
{
int ret;

if (!chmc_platform())
return -ENODEV;

return of_register_driver(&chmc_driver, &of_bus_type);
ret = register_dimm_printer(chmc_print_dimm);
if (!ret) {
ret = of_register_driver(&chmc_driver, &of_bus_type);
if (ret)
unregister_dimm_printer(chmc_print_dimm);
}
return ret;
}

static void __exit chmc_cleanup(void)
{
if (chmc_platform())
if (chmc_platform()) {
unregister_dimm_printer(chmc_print_dimm);
of_unregister_driver(&chmc_driver);
}
}

module_init(chmc_init);
Expand Down
62 changes: 54 additions & 8 deletions arch/sparc64/kernel/traps.c
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@
#include <asm/timer.h>
#include <asm/head.h>
#include <asm/prom.h>
#include <asm/memctrl.h>

#include "entry.h"
#include "kstack.h"
Expand Down Expand Up @@ -128,6 +129,55 @@ void do_BUG(const char *file, int line)
}
#endif

static DEFINE_SPINLOCK(dimm_handler_lock);
static dimm_printer_t dimm_handler;

static int sprintf_dimm(int synd_code, unsigned long paddr, char *buf, int buflen)
{
unsigned long flags;
int ret = -ENODEV;

spin_lock_irqsave(&dimm_handler_lock, flags);
if (dimm_handler) {
ret = dimm_handler(synd_code, paddr, buf, buflen);
} else if (tlb_type == spitfire) {
if (prom_getunumber(synd_code, paddr, buf, buflen) == -1)
ret = -EINVAL;
else
ret = 0;
} else
ret = -ENODEV;
spin_unlock_irqrestore(&dimm_handler_lock, flags);

return ret;
}

int register_dimm_printer(dimm_printer_t func)
{
unsigned long flags;
int ret = 0;

spin_lock_irqsave(&dimm_handler_lock, flags);
if (!dimm_handler)
dimm_handler = func;
else
ret = -EEXIST;
spin_unlock_irqrestore(&dimm_handler_lock, flags);

return ret;
}

void unregister_dimm_printer(dimm_printer_t func)
{
unsigned long flags;

spin_lock_irqsave(&dimm_handler_lock, flags);
if (dimm_handler == func)
dimm_handler = NULL;
spin_unlock_irqrestore(&dimm_handler_lock, flags);
}


void spitfire_insn_access_exception(struct pt_regs *regs, unsigned long sfsr, unsigned long sfar)
{
siginfo_t info;
Expand Down Expand Up @@ -375,8 +425,7 @@ static void spitfire_log_udb_syndrome(unsigned long afar, unsigned long udbh, un

if (udbl & bit) {
scode = ecc_syndrome_table[udbl & 0xff];
if (prom_getunumber(scode, afar,
memmod_str, sizeof(memmod_str)) == -1)
if (sprintf_dimm(scode, afar, memmod_str, sizeof(memmod_str)) < 0)
p = syndrome_unknown;
else
p = memmod_str;
Expand All @@ -387,8 +436,7 @@ static void spitfire_log_udb_syndrome(unsigned long afar, unsigned long udbh, un

if (udbh & bit) {
scode = ecc_syndrome_table[udbh & 0xff];
if (prom_getunumber(scode, afar,
memmod_str, sizeof(memmod_str)) == -1)
if (sprintf_dimm(scode, afar, memmod_str, sizeof(memmod_str)) < 0)
p = syndrome_unknown;
else
p = memmod_str;
Expand Down Expand Up @@ -1061,8 +1109,6 @@ static const char *cheetah_get_string(unsigned long bit)
return "???";
}

extern int chmc_getunumber(int, unsigned long, char *, int);

static void cheetah_log_errors(struct pt_regs *regs, struct cheetah_err_info *info,
unsigned long afsr, unsigned long afar, int recoverable)
{
Expand Down Expand Up @@ -1104,7 +1150,7 @@ static void cheetah_log_errors(struct pt_regs *regs, struct cheetah_err_info *in

syndrome = (afsr & CHAFSR_E_SYNDROME) >> CHAFSR_E_SYNDROME_SHIFT;
syndrome = cheetah_ecc_syntab[syndrome];
ret = chmc_getunumber(syndrome, afar, unum, sizeof(unum));
ret = sprintf_dimm(syndrome, afar, unum, sizeof(unum));
if (ret != -1)
printk("%s" "ERROR(%d): AFAR E-syndrome [%s]\n",
(recoverable ? KERN_WARNING : KERN_CRIT),
Expand All @@ -1115,7 +1161,7 @@ static void cheetah_log_errors(struct pt_regs *regs, struct cheetah_err_info *in

syndrome = (afsr & CHAFSR_M_SYNDROME) >> CHAFSR_M_SYNDROME_SHIFT;
syndrome = cheetah_mtag_syntab[syndrome];
ret = chmc_getunumber(syndrome, afar, unum, sizeof(unum));
ret = sprintf_dimm(syndrome, afar, unum, sizeof(unum));
if (ret != -1)
printk("%s" "ERROR(%d): AFAR M-syndrome [%s]\n",
(recoverable ? KERN_WARNING : KERN_CRIT),
Expand Down

0 comments on commit 881d021

Please sign in to comment.