aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc/platforms/chrp/setup.c
diff options
context:
space:
mode:
authorPaul Mackerras <paulus@samba.org>2006-03-27 05:48:57 -0500
committerPaul Mackerras <paulus@samba.org>2006-03-27 05:48:57 -0500
commit9618edab82fda8dbce5ea3abcdac9ded07abb2d4 (patch)
tree8edacdcf4d0ecdd8a7b5b0f88f3cf68c393afbc5 /arch/powerpc/platforms/chrp/setup.c
parentd0cc0dfa2dcf18854144b16a74502bd25c4eaedf (diff)
powerpc: Fix event-scan code for 32-bit CHRP
On CHRP machines we are supposed to call into firmware (RTAS) periodically, to give it a chance to check for errors and other events. Under ppc we had some special code in timer_interrupt to do this, but that didn't get transferred over to arch/powerpc. Instead, we use an array of timer_list structs, one per CPU, and use add_timer_on to make sure each one gets called on the appropriate CPU. With this we can remove the heartbeat_* elements of the ppc_md struct. Signed-off-by: Paul Mackerras <paulus@samba.org>
Diffstat (limited to 'arch/powerpc/platforms/chrp/setup.c')
-rw-r--r--arch/powerpc/platforms/chrp/setup.c64
1 files changed, 45 insertions, 19 deletions
diff --git a/arch/powerpc/platforms/chrp/setup.c b/arch/powerpc/platforms/chrp/setup.c
index 8bf4307e323..9c718bb2305 100644
--- a/arch/powerpc/platforms/chrp/setup.c
+++ b/arch/powerpc/platforms/chrp/setup.c
@@ -35,6 +35,7 @@
35#include <linux/root_dev.h> 35#include <linux/root_dev.h>
36#include <linux/initrd.h> 36#include <linux/initrd.h>
37#include <linux/module.h> 37#include <linux/module.h>
38#include <linux/timer.h>
38 39
39#include <asm/io.h> 40#include <asm/io.h>
40#include <asm/pgtable.h> 41#include <asm/pgtable.h>
@@ -61,6 +62,10 @@ EXPORT_SYMBOL(_chrp_type);
61 62
62struct mpic *chrp_mpic; 63struct mpic *chrp_mpic;
63 64
65/* Used for doing CHRP event-scans */
66DEFINE_PER_CPU(struct timer_list, heartbeat_timer);
67unsigned long event_scan_interval;
68
64/* 69/*
65 * XXX this should be in xmon.h, but putting it there means xmon.h 70 * XXX this should be in xmon.h, but putting it there means xmon.h
66 * has to include <linux/interrupt.h> (to get irqreturn_t), which 71 * has to include <linux/interrupt.h> (to get irqreturn_t), which
@@ -229,8 +234,6 @@ void __init chrp_setup_arch(void)
229{ 234{
230 struct device_node *root = find_path_device ("/"); 235 struct device_node *root = find_path_device ("/");
231 char *machine = NULL; 236 char *machine = NULL;
232 struct device_node *device;
233 unsigned int *p = NULL;
234 237
235 /* init to some ~sane value until calibrate_delay() runs */ 238 /* init to some ~sane value until calibrate_delay() runs */
236 loops_per_jiffy = 50000000/HZ; 239 loops_per_jiffy = 50000000/HZ;
@@ -287,21 +290,6 @@ void __init chrp_setup_arch(void)
287 */ 290 */
288 sio_init(); 291 sio_init();
289 292
290 /* Get the event scan rate for the rtas so we know how
291 * often it expects a heartbeat. -- Cort
292 */
293 device = find_devices("rtas");
294 if (device)
295 p = (unsigned int *) get_property
296 (device, "rtas-event-scan-rate", NULL);
297 if (p && *p) {
298 ppc_md.heartbeat = chrp_event_scan;
299 ppc_md.heartbeat_reset = HZ / (*p * 30) - 1;
300 ppc_md.heartbeat_count = 1;
301 printk("RTAS Event Scan Rate: %u (%lu jiffies)\n",
302 *p, ppc_md.heartbeat_reset);
303 }
304
305 pci_create_OF_bus_map(); 293 pci_create_OF_bus_map();
306 294
307 /* 295 /*
@@ -312,7 +300,7 @@ void __init chrp_setup_arch(void)
312} 300}
313 301
314void 302void
315chrp_event_scan(void) 303chrp_event_scan(unsigned long unused)
316{ 304{
317 unsigned char log[1024]; 305 unsigned char log[1024];
318 int ret = 0; 306 int ret = 0;
@@ -320,7 +308,8 @@ chrp_event_scan(void)
320 /* XXX: we should loop until the hardware says no more error logs -- Cort */ 308 /* XXX: we should loop until the hardware says no more error logs -- Cort */
321 rtas_call(rtas_token("event-scan"), 4, 1, &ret, 0xffffffff, 0, 309 rtas_call(rtas_token("event-scan"), 4, 1, &ret, 0xffffffff, 0,
322 __pa(log), 1024); 310 __pa(log), 1024);
323 ppc_md.heartbeat_count = ppc_md.heartbeat_reset; 311 mod_timer(&__get_cpu_var(heartbeat_timer),
312 jiffies + event_scan_interval);
324} 313}
325 314
326/* 315/*
@@ -465,6 +454,9 @@ void __init chrp_init_IRQ(void)
465void __init 454void __init
466chrp_init2(void) 455chrp_init2(void)
467{ 456{
457 struct device_node *device;
458 unsigned int *p = NULL;
459
468#ifdef CONFIG_NVRAM 460#ifdef CONFIG_NVRAM
469 chrp_nvram_init(); 461 chrp_nvram_init();
470#endif 462#endif
@@ -476,6 +468,40 @@ chrp_init2(void)
476 request_region(0x80,0x10,"dma page reg"); 468 request_region(0x80,0x10,"dma page reg");
477 request_region(0xc0,0x20,"dma2"); 469 request_region(0xc0,0x20,"dma2");
478 470
471 /* Get the event scan rate for the rtas so we know how
472 * often it expects a heartbeat. -- Cort
473 */
474 device = find_devices("rtas");
475 if (device)
476 p = (unsigned int *) get_property
477 (device, "rtas-event-scan-rate", NULL);
478 if (p && *p) {
479 /*
480 * Arrange to call chrp_event_scan at least *p times
481 * per minute. We use 59 rather than 60 here so that
482 * the rate will be slightly higher than the minimum.
483 * This all assumes we don't do hotplug CPU on any
484 * machine that needs the event scans done.
485 */
486 unsigned long interval, offset;
487 int cpu, ncpus;
488 struct timer_list *timer;
489
490 interval = HZ * 59 / *p;
491 offset = HZ;
492 ncpus = num_online_cpus();
493 event_scan_interval = ncpus * interval;
494 for (cpu = 0; cpu < ncpus; ++cpu) {
495 timer = &per_cpu(heartbeat_timer, cpu);
496 setup_timer(timer, chrp_event_scan, 0);
497 timer->expires = jiffies + offset;
498 add_timer_on(timer, cpu);
499 offset += interval;
500 }
501 printk("RTAS Event Scan Rate: %u (%lu jiffies)\n",
502 *p, interval);
503 }
504
479 if (ppc_md.progress) 505 if (ppc_md.progress)
480 ppc_md.progress(" Have fun! ", 0x7777); 506 ppc_md.progress(" Have fun! ", 0x7777);
481} 507}