Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 3d541c4b authored by Benjamin Herrenschmidt's avatar Benjamin Herrenschmidt
Browse files

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: default avatarBenjamin Herrenschmidt <benh@kernel.crashing.org>
parent 188917e1
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -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
+34 −14
Original line number Diff line number Diff line
@@ -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;

@@ -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
@@ -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;
@@ -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) {
@@ -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);
@@ -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));

	/* 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);
@@ -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;
	}

@@ -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");
@@ -492,11 +508,16 @@ 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;
@@ -504,6 +525,7 @@ static int __init surveillance_setup(char *str)

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

static int __init rtasmsgs_setup(char *str)
{
@@ -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 −0
Original line number Diff line number Diff line
@@ -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
+2 −0
Original line number Diff line number Diff line
@@ -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
+0 −50
Original line number Diff line number Diff line
@@ -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();
@@ -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
@@ -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);
}
Loading