powerpc/chrp: Use the same RTAS daemon as pSeries
The CHRP code has some fishy timer based code to scan the RTAS event log, which uses a 1KB stack buffer and doesn't even use the results. The pSeries code as a nicer daemon that allows userspace to read the event log and basically uses the same RTAS interface This patch moves rtasd.c out of platform/pseries and makes it usable by CHRP, after removing the old crufty event log mechanism in there. The nvram logging part of the daemon is still only available on 64-bit since the underlying nvram management routines aren't currently shared. Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
This commit is contained in:
parent
188917e183
commit
3d541c4b7f
|
@ -46,6 +46,7 @@ procfs-y := proc_powerpc.o
|
||||||
obj-$(CONFIG_PROC_FS) += $(procfs-y)
|
obj-$(CONFIG_PROC_FS) += $(procfs-y)
|
||||||
rtaspci-$(CONFIG_PPC64)-$(CONFIG_PCI) := rtas_pci.o
|
rtaspci-$(CONFIG_PPC64)-$(CONFIG_PCI) := rtas_pci.o
|
||||||
obj-$(CONFIG_PPC_RTAS) += rtas.o rtas-rtc.o $(rtaspci-y-y)
|
obj-$(CONFIG_PPC_RTAS) += rtas.o rtas-rtc.o $(rtaspci-y-y)
|
||||||
|
obj-$(CONFIG_PPC_RTAS_DAEMON) += rtasd.o
|
||||||
obj-$(CONFIG_RTAS_FLASH) += rtas_flash.o
|
obj-$(CONFIG_RTAS_FLASH) += rtas_flash.o
|
||||||
obj-$(CONFIG_RTAS_PROC) += rtas-proc.o
|
obj-$(CONFIG_RTAS_PROC) += rtas-proc.o
|
||||||
obj-$(CONFIG_LPARCFG) += lparcfg.o
|
obj-$(CONFIG_LPARCFG) += lparcfg.o
|
||||||
|
|
|
@ -39,6 +39,7 @@ static unsigned long rtas_log_start;
|
||||||
static unsigned long rtas_log_size;
|
static unsigned long rtas_log_size;
|
||||||
|
|
||||||
static int surveillance_timeout = -1;
|
static int surveillance_timeout = -1;
|
||||||
|
|
||||||
static unsigned int rtas_error_log_max;
|
static unsigned int rtas_error_log_max;
|
||||||
static unsigned int rtas_error_log_buffer_max;
|
static unsigned int rtas_error_log_buffer_max;
|
||||||
|
|
||||||
|
@ -213,9 +214,11 @@ void pSeries_log_error(char *buf, unsigned int err_type, int fatal)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef CONFIG_PPC64
|
||||||
/* Write error to NVRAM */
|
/* Write error to NVRAM */
|
||||||
if (logging_enabled && !(err_type & ERR_FLAG_BOOT))
|
if (logging_enabled && !(err_type & ERR_FLAG_BOOT))
|
||||||
nvram_write_error_log(buf, len, err_type, error_log_cnt);
|
nvram_write_error_log(buf, len, err_type, error_log_cnt);
|
||||||
|
#endif /* CONFIG_PPC64 */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* rtas errors can occur during boot, and we do want to capture
|
* rtas errors can occur during boot, and we do want to capture
|
||||||
|
@ -264,7 +267,6 @@ void pSeries_log_error(char *buf, unsigned int err_type, int fatal)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static int rtas_log_open(struct inode * inode, struct file * file)
|
static int rtas_log_open(struct inode * inode, struct file * file)
|
||||||
{
|
{
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -300,6 +302,7 @@ static ssize_t rtas_log_read(struct file * file, char __user * buf,
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
spin_lock_irqsave(&rtasd_log_lock, s);
|
spin_lock_irqsave(&rtasd_log_lock, s);
|
||||||
|
|
||||||
/* if it's 0, then we know we got the last one (the one in NVRAM) */
|
/* if it's 0, then we know we got the last one (the one in NVRAM) */
|
||||||
while (rtas_log_size == 0) {
|
while (rtas_log_size == 0) {
|
||||||
if (file->f_flags & O_NONBLOCK) {
|
if (file->f_flags & O_NONBLOCK) {
|
||||||
|
@ -313,7 +316,9 @@ static ssize_t rtas_log_read(struct file * file, char __user * buf,
|
||||||
error = -ENODATA;
|
error = -ENODATA;
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
#ifdef CONFIG_PPC64
|
||||||
nvram_clear_error_log();
|
nvram_clear_error_log();
|
||||||
|
#endif /* CONFIG_PPC64 */
|
||||||
|
|
||||||
spin_unlock_irqrestore(&rtasd_log_lock, s);
|
spin_unlock_irqrestore(&rtasd_log_lock, s);
|
||||||
error = wait_event_interruptible(rtas_log_wait, rtas_log_size);
|
error = wait_event_interruptible(rtas_log_wait, rtas_log_size);
|
||||||
|
@ -427,14 +432,11 @@ static void rtas_event_scan(struct work_struct *w)
|
||||||
put_online_cpus();
|
put_online_cpus();
|
||||||
}
|
}
|
||||||
|
|
||||||
static void start_event_scan(void)
|
#ifdef CONFIG_PPC64
|
||||||
|
static void retreive_nvram_error_log(void)
|
||||||
{
|
{
|
||||||
unsigned int err_type;
|
unsigned int err_type ;
|
||||||
int rc;
|
int rc ;
|
||||||
|
|
||||||
printk(KERN_DEBUG "RTAS daemon started\n");
|
|
||||||
pr_debug("rtasd: will sleep for %d milliseconds\n",
|
|
||||||
(30000 / rtas_event_scan_rate));
|
|
||||||
|
|
||||||
/* See if we have any error stored in NVRAM */
|
/* See if we have any error stored in NVRAM */
|
||||||
memset(logdata, 0, rtas_error_log_max);
|
memset(logdata, 0, rtas_error_log_max);
|
||||||
|
@ -442,12 +444,26 @@ static void start_event_scan(void)
|
||||||
&err_type, &error_log_cnt);
|
&err_type, &error_log_cnt);
|
||||||
/* We can use rtas_log_buf now */
|
/* We can use rtas_log_buf now */
|
||||||
logging_enabled = 1;
|
logging_enabled = 1;
|
||||||
|
|
||||||
if (!rc) {
|
if (!rc) {
|
||||||
if (err_type != ERR_FLAG_ALREADY_LOGGED) {
|
if (err_type != ERR_FLAG_ALREADY_LOGGED) {
|
||||||
pSeries_log_error(logdata, err_type | ERR_FLAG_BOOT, 0);
|
pSeries_log_error(logdata, err_type | ERR_FLAG_BOOT, 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
#else /* CONFIG_PPC64 */
|
||||||
|
static void retreive_nvram_error_log(void)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
#endif /* CONFIG_PPC64 */
|
||||||
|
|
||||||
|
static void start_event_scan(void)
|
||||||
|
{
|
||||||
|
printk(KERN_DEBUG "RTAS daemon started\n");
|
||||||
|
pr_debug("rtasd: will sleep for %d milliseconds\n",
|
||||||
|
(30000 / rtas_event_scan_rate));
|
||||||
|
|
||||||
|
/* Retreive errors from nvram if any */
|
||||||
|
retreive_nvram_error_log();
|
||||||
|
|
||||||
schedule_delayed_work_on(first_cpu(cpu_online_map), &event_scan_work,
|
schedule_delayed_work_on(first_cpu(cpu_online_map), &event_scan_work,
|
||||||
event_scan_delay);
|
event_scan_delay);
|
||||||
|
@ -457,13 +473,13 @@ static int __init rtas_init(void)
|
||||||
{
|
{
|
||||||
struct proc_dir_entry *entry;
|
struct proc_dir_entry *entry;
|
||||||
|
|
||||||
if (!machine_is(pseries))
|
if (!machine_is(pseries) && !machine_is(chrp))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
/* No RTAS */
|
/* No RTAS */
|
||||||
event_scan = rtas_token("event-scan");
|
event_scan = rtas_token("event-scan");
|
||||||
if (event_scan == RTAS_UNKNOWN_SERVICE) {
|
if (event_scan == RTAS_UNKNOWN_SERVICE) {
|
||||||
printk(KERN_DEBUG "rtasd: no event-scan on system\n");
|
printk(KERN_INFO "rtasd: No event-scan on system\n");
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -483,7 +499,7 @@ static int __init rtas_init(void)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
}
|
}
|
||||||
|
|
||||||
entry = proc_create("ppc64/rtas/error_log", S_IRUSR, NULL,
|
entry = proc_create("powerpc/rtas/error_log", S_IRUSR, NULL,
|
||||||
&proc_rtas_log_operations);
|
&proc_rtas_log_operations);
|
||||||
if (!entry)
|
if (!entry)
|
||||||
printk(KERN_ERR "Failed to create error_log proc entry\n");
|
printk(KERN_ERR "Failed to create error_log proc entry\n");
|
||||||
|
@ -492,11 +508,16 @@ static int __init rtas_init(void)
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
__initcall(rtas_init);
|
||||||
|
|
||||||
static int __init surveillance_setup(char *str)
|
static int __init surveillance_setup(char *str)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
|
/* We only do surveillance on pseries */
|
||||||
|
if (!machine_is(pseries))
|
||||||
|
return 0;
|
||||||
|
|
||||||
if (get_option(&str,&i)) {
|
if (get_option(&str,&i)) {
|
||||||
if (i >= 0 && i <= 255)
|
if (i >= 0 && i <= 255)
|
||||||
surveillance_timeout = i;
|
surveillance_timeout = i;
|
||||||
|
@ -504,6 +525,7 @@ static int __init surveillance_setup(char *str)
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
__setup("surveillance=", surveillance_setup);
|
||||||
|
|
||||||
static int __init rtasmsgs_setup(char *str)
|
static int __init rtasmsgs_setup(char *str)
|
||||||
{
|
{
|
||||||
|
@ -514,6 +536,4 @@ static int __init rtasmsgs_setup(char *str)
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
__initcall(rtas_init);
|
|
||||||
__setup("surveillance=", surveillance_setup);
|
|
||||||
__setup("rtasmsgs=", rtasmsgs_setup);
|
__setup("rtasmsgs=", rtasmsgs_setup);
|
|
@ -86,6 +86,11 @@ config RTAS_ERROR_LOGGING
|
||||||
depends on PPC_RTAS
|
depends on PPC_RTAS
|
||||||
default n
|
default n
|
||||||
|
|
||||||
|
config PPC_RTAS_DAEMON
|
||||||
|
bool
|
||||||
|
depends on PPC_RTAS
|
||||||
|
default n
|
||||||
|
|
||||||
config RTAS_PROC
|
config RTAS_PROC
|
||||||
bool "Proc interface to RTAS"
|
bool "Proc interface to RTAS"
|
||||||
depends on PPC_RTAS
|
depends on PPC_RTAS
|
||||||
|
|
|
@ -5,6 +5,8 @@ config PPC_CHRP
|
||||||
select PPC_I8259
|
select PPC_I8259
|
||||||
select PPC_INDIRECT_PCI
|
select PPC_INDIRECT_PCI
|
||||||
select PPC_RTAS
|
select PPC_RTAS
|
||||||
|
select PPC_RTAS_DAEMON
|
||||||
|
select RTAS_ERROR_LOGGING
|
||||||
select PPC_MPC106
|
select PPC_MPC106
|
||||||
select PPC_UDBG_16550
|
select PPC_UDBG_16550
|
||||||
select PPC_NATIVE
|
select PPC_NATIVE
|
||||||
|
|
|
@ -364,19 +364,6 @@ void __init chrp_setup_arch(void)
|
||||||
if (ppc_md.progress) ppc_md.progress("Linux/PPC "UTS_RELEASE"\n", 0x0);
|
if (ppc_md.progress) ppc_md.progress("Linux/PPC "UTS_RELEASE"\n", 0x0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
|
||||||
chrp_event_scan(unsigned long unused)
|
|
||||||
{
|
|
||||||
unsigned char log[1024];
|
|
||||||
int ret = 0;
|
|
||||||
|
|
||||||
/* XXX: we should loop until the hardware says no more error logs -- Cort */
|
|
||||||
rtas_call(rtas_token("event-scan"), 4, 1, &ret, 0xffffffff, 0,
|
|
||||||
__pa(log), 1024);
|
|
||||||
mod_timer(&__get_cpu_var(heartbeat_timer),
|
|
||||||
jiffies + event_scan_interval);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void chrp_8259_cascade(unsigned int irq, struct irq_desc *desc)
|
static void chrp_8259_cascade(unsigned int irq, struct irq_desc *desc)
|
||||||
{
|
{
|
||||||
unsigned int cascade_irq = i8259_irq();
|
unsigned int cascade_irq = i8259_irq();
|
||||||
|
@ -568,9 +555,6 @@ void __init chrp_init_IRQ(void)
|
||||||
void __init
|
void __init
|
||||||
chrp_init2(void)
|
chrp_init2(void)
|
||||||
{
|
{
|
||||||
struct device_node *device;
|
|
||||||
const unsigned int *p = NULL;
|
|
||||||
|
|
||||||
#ifdef CONFIG_NVRAM
|
#ifdef CONFIG_NVRAM
|
||||||
chrp_nvram_init();
|
chrp_nvram_init();
|
||||||
#endif
|
#endif
|
||||||
|
@ -582,40 +566,6 @@ chrp_init2(void)
|
||||||
request_region(0x80,0x10,"dma page reg");
|
request_region(0x80,0x10,"dma page reg");
|
||||||
request_region(0xc0,0x20,"dma2");
|
request_region(0xc0,0x20,"dma2");
|
||||||
|
|
||||||
/* Get the event scan rate for the rtas so we know how
|
|
||||||
* often it expects a heartbeat. -- Cort
|
|
||||||
*/
|
|
||||||
device = of_find_node_by_name(NULL, "rtas");
|
|
||||||
if (device)
|
|
||||||
p = of_get_property(device, "rtas-event-scan-rate", NULL);
|
|
||||||
if (p && *p) {
|
|
||||||
/*
|
|
||||||
* Arrange to call chrp_event_scan at least *p times
|
|
||||||
* per minute. We use 59 rather than 60 here so that
|
|
||||||
* the rate will be slightly higher than the minimum.
|
|
||||||
* This all assumes we don't do hotplug CPU on any
|
|
||||||
* machine that needs the event scans done.
|
|
||||||
*/
|
|
||||||
unsigned long interval, offset;
|
|
||||||
int cpu, ncpus;
|
|
||||||
struct timer_list *timer;
|
|
||||||
|
|
||||||
interval = HZ * 59 / *p;
|
|
||||||
offset = HZ;
|
|
||||||
ncpus = num_online_cpus();
|
|
||||||
event_scan_interval = ncpus * interval;
|
|
||||||
for (cpu = 0; cpu < ncpus; ++cpu) {
|
|
||||||
timer = &per_cpu(heartbeat_timer, cpu);
|
|
||||||
setup_timer(timer, chrp_event_scan, 0);
|
|
||||||
timer->expires = jiffies + offset;
|
|
||||||
add_timer_on(timer, cpu);
|
|
||||||
offset += interval;
|
|
||||||
}
|
|
||||||
printk("RTAS Event Scan Rate: %u (%lu jiffies)\n",
|
|
||||||
*p, interval);
|
|
||||||
}
|
|
||||||
of_node_put(device);
|
|
||||||
|
|
||||||
if (ppc_md.progress)
|
if (ppc_md.progress)
|
||||||
ppc_md.progress(" Have fun! ", 0x7777);
|
ppc_md.progress(" Have fun! ", 0x7777);
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,6 +4,7 @@ config PPC_PSERIES
|
||||||
select MPIC
|
select MPIC
|
||||||
select PPC_I8259
|
select PPC_I8259
|
||||||
select PPC_RTAS
|
select PPC_RTAS
|
||||||
|
select PPC_RTAS_DAEMON
|
||||||
select RTAS_ERROR_LOGGING
|
select RTAS_ERROR_LOGGING
|
||||||
select PPC_UDBG_16550
|
select PPC_UDBG_16550
|
||||||
select PPC_NATIVE
|
select PPC_NATIVE
|
||||||
|
|
|
@ -7,7 +7,7 @@ EXTRA_CFLAGS += -DDEBUG
|
||||||
endif
|
endif
|
||||||
|
|
||||||
obj-y := lpar.o hvCall.o nvram.o reconfig.o \
|
obj-y := lpar.o hvCall.o nvram.o reconfig.o \
|
||||||
setup.o iommu.o ras.o rtasd.o \
|
setup.o iommu.o ras.o \
|
||||||
firmware.o power.o
|
firmware.o power.o
|
||||||
obj-$(CONFIG_SMP) += smp.o
|
obj-$(CONFIG_SMP) += smp.o
|
||||||
obj-$(CONFIG_XICS) += xics.o
|
obj-$(CONFIG_XICS) += xics.o
|
||||||
|
|
Loading…
Reference in New Issue