Skip to content

Commit

Permalink
powerpc/chrp: Use the same RTAS daemon as pSeries
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Benjamin Herrenschmidt committed Oct 30, 2009
1 parent 188917e commit 3d541c4
Show file tree
Hide file tree
Showing 7 changed files with 44 additions and 65 deletions.
1 change: 1 addition & 0 deletions arch/powerpc/kernel/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ procfs-y := proc_powerpc.o
obj-$(CONFIG_PROC_FS) += $(procfs-y)
rtaspci-$(CONFIG_PPC64)-$(CONFIG_PCI) := rtas_pci.o
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_PROC) += rtas-proc.o
obj-$(CONFIG_LPARCFG) += lparcfg.o
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ static unsigned long rtas_log_start;
static unsigned long rtas_log_size;

static int surveillance_timeout = -1;

static unsigned int rtas_error_log_max;
static unsigned int rtas_error_log_buffer_max;

Expand Down Expand Up @@ -213,9 +214,11 @@ void pSeries_log_error(char *buf, unsigned int err_type, int fatal)
return;
}

#ifdef CONFIG_PPC64
/* Write error to NVRAM */
if (logging_enabled && !(err_type & ERR_FLAG_BOOT))
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
Expand Down Expand Up @@ -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)
{
return 0;
Expand Down Expand Up @@ -300,6 +302,7 @@ static ssize_t rtas_log_read(struct file * file, char __user * buf,
return -ENOMEM;

spin_lock_irqsave(&rtasd_log_lock, s);

/* if it's 0, then we know we got the last one (the one in NVRAM) */
while (rtas_log_size == 0) {
if (file->f_flags & O_NONBLOCK) {
Expand All @@ -313,7 +316,9 @@ static ssize_t rtas_log_read(struct file * file, char __user * buf,
error = -ENODATA;
goto out;
}
#ifdef CONFIG_PPC64
nvram_clear_error_log();
#endif /* CONFIG_PPC64 */

spin_unlock_irqrestore(&rtasd_log_lock, s);
error = wait_event_interruptible(rtas_log_wait, rtas_log_size);
Expand Down Expand Up @@ -427,27 +432,38 @@ static void rtas_event_scan(struct work_struct *w)
put_online_cpus();
}

static void start_event_scan(void)
#ifdef CONFIG_PPC64
static void retreive_nvram_error_log(void)
{
unsigned int err_type;
int rc;

printk(KERN_DEBUG "RTAS daemon started\n");
pr_debug("rtasd: will sleep for %d milliseconds\n",
(30000 / rtas_event_scan_rate));
unsigned int err_type ;
int rc ;

/* See if we have any error stored in NVRAM */
memset(logdata, 0, rtas_error_log_max);
rc = nvram_read_error_log(logdata, rtas_error_log_max,
&err_type, &error_log_cnt);
/* We can use rtas_log_buf now */
logging_enabled = 1;

if (!rc) {
if (err_type != ERR_FLAG_ALREADY_LOGGED) {
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,
event_scan_delay);
Expand All @@ -457,13 +473,13 @@ static int __init rtas_init(void)
{
struct proc_dir_entry *entry;

if (!machine_is(pseries))
if (!machine_is(pseries) && !machine_is(chrp))
return 0;

/* No RTAS */
event_scan = rtas_token("event-scan");
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;
}

Expand All @@ -483,7 +499,7 @@ static int __init rtas_init(void)
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);
if (!entry)
printk(KERN_ERR "Failed to create error_log proc entry\n");
Expand All @@ -492,18 +508,24 @@ static int __init rtas_init(void)

return 0;
}
__initcall(rtas_init);

static int __init surveillance_setup(char *str)
{
int i;

/* We only do surveillance on pseries */
if (!machine_is(pseries))
return 0;

if (get_option(&str,&i)) {
if (i >= 0 && i <= 255)
surveillance_timeout = i;
}

return 1;
}
__setup("surveillance=", surveillance_setup);

static int __init rtasmsgs_setup(char *str)
{
Expand All @@ -514,6 +536,4 @@ static int __init rtasmsgs_setup(char *str)

return 1;
}
__initcall(rtas_init);
__setup("surveillance=", surveillance_setup);
__setup("rtasmsgs=", rtasmsgs_setup);
5 changes: 5 additions & 0 deletions arch/powerpc/platforms/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,11 @@ config RTAS_ERROR_LOGGING
depends on PPC_RTAS
default n

config PPC_RTAS_DAEMON
bool
depends on PPC_RTAS
default n

config RTAS_PROC
bool "Proc interface to RTAS"
depends on PPC_RTAS
Expand Down
2 changes: 2 additions & 0 deletions arch/powerpc/platforms/chrp/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ config PPC_CHRP
select PPC_I8259
select PPC_INDIRECT_PCI
select PPC_RTAS
select PPC_RTAS_DAEMON
select RTAS_ERROR_LOGGING
select PPC_MPC106
select PPC_UDBG_16550
select PPC_NATIVE
Expand Down
50 changes: 0 additions & 50 deletions arch/powerpc/platforms/chrp/setup.c
Original file line number Diff line number Diff line change
Expand Up @@ -364,19 +364,6 @@ void __init chrp_setup_arch(void)
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)
{
unsigned int cascade_irq = i8259_irq();
Expand Down Expand Up @@ -568,9 +555,6 @@ void __init chrp_init_IRQ(void)
void __init
chrp_init2(void)
{
struct device_node *device;
const unsigned int *p = NULL;

#ifdef CONFIG_NVRAM
chrp_nvram_init();
#endif
Expand All @@ -582,40 +566,6 @@ chrp_init2(void)
request_region(0x80,0x10,"dma page reg");
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)
ppc_md.progress(" Have fun! ", 0x7777);
}
Expand Down
1 change: 1 addition & 0 deletions arch/powerpc/platforms/pseries/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ config PPC_PSERIES
select MPIC
select PPC_I8259
select PPC_RTAS
select PPC_RTAS_DAEMON
select RTAS_ERROR_LOGGING
select PPC_UDBG_16550
select PPC_NATIVE
Expand Down
2 changes: 1 addition & 1 deletion arch/powerpc/platforms/pseries/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ EXTRA_CFLAGS += -DDEBUG
endif

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
obj-$(CONFIG_SMP) += smp.o
obj-$(CONFIG_XICS) += xics.o
Expand Down

0 comments on commit 3d541c4

Please sign in to comment.