Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>

+46 -24
+1 -1
arch/powerpc/platforms/chrp/chrp.h
··· 8 8 extern long chrp_time_init(void); 9 9 10 10 extern void chrp_find_bridges(void); 11 - extern void chrp_event_scan(void); 11 + extern void chrp_event_scan(unsigned long);
+45 -19
arch/powerpc/platforms/chrp/setup.c
··· 35 35 #include <linux/root_dev.h> 36 36 #include <linux/initrd.h> 37 37 #include <linux/module.h> 38 + #include <linux/timer.h> 38 39 39 40 #include <asm/io.h> 40 41 #include <asm/pgtable.h> ··· 61 60 EXPORT_SYMBOL(_chrp_type); 62 61 63 62 struct mpic *chrp_mpic; 63 + 64 + /* Used for doing CHRP event-scans */ 65 + DEFINE_PER_CPU(struct timer_list, heartbeat_timer); 66 + unsigned long event_scan_interval; 64 67 65 68 /* 66 69 * XXX this should be in xmon.h, but putting it there means xmon.h ··· 234 229 { 235 230 struct device_node *root = find_path_device ("/"); 236 231 char *machine = NULL; 237 - struct device_node *device; 238 - unsigned int *p = NULL; 239 232 240 233 /* init to some ~sane value until calibrate_delay() runs */ 241 234 loops_per_jiffy = 50000000/HZ; ··· 290 287 */ 291 288 sio_init(); 292 289 293 - /* Get the event scan rate for the rtas so we know how 294 - * often it expects a heartbeat. -- Cort 295 - */ 296 - device = find_devices("rtas"); 297 - if (device) 298 - p = (unsigned int *) get_property 299 - (device, "rtas-event-scan-rate", NULL); 300 - if (p && *p) { 301 - ppc_md.heartbeat = chrp_event_scan; 302 - ppc_md.heartbeat_reset = HZ / (*p * 30) - 1; 303 - ppc_md.heartbeat_count = 1; 304 - printk("RTAS Event Scan Rate: %u (%lu jiffies)\n", 305 - *p, ppc_md.heartbeat_reset); 306 - } 307 - 308 290 pci_create_OF_bus_map(); 309 291 310 292 /* ··· 300 312 } 301 313 302 314 void 303 - chrp_event_scan(void) 315 + chrp_event_scan(unsigned long unused) 304 316 { 305 317 unsigned char log[1024]; 306 318 int ret = 0; ··· 308 320 /* XXX: we should loop until the hardware says no more error logs -- Cort */ 309 321 rtas_call(rtas_token("event-scan"), 4, 1, &ret, 0xffffffff, 0, 310 322 __pa(log), 1024); 311 - ppc_md.heartbeat_count = ppc_md.heartbeat_reset; 323 + mod_timer(&__get_cpu_var(heartbeat_timer), 324 + jiffies + event_scan_interval); 312 325 } 313 326 314 327 /* ··· 454 465 void __init 455 466 chrp_init2(void) 456 467 { 468 + struct device_node *device; 469 + unsigned int *p = NULL; 470 + 457 471 #ifdef CONFIG_NVRAM 458 472 chrp_nvram_init(); 459 473 #endif ··· 467 475 request_region(0x40,0x20,"timer"); 468 476 request_region(0x80,0x10,"dma page reg"); 469 477 request_region(0xc0,0x20,"dma2"); 478 + 479 + /* Get the event scan rate for the rtas so we know how 480 + * often it expects a heartbeat. -- Cort 481 + */ 482 + device = find_devices("rtas"); 483 + if (device) 484 + p = (unsigned int *) get_property 485 + (device, "rtas-event-scan-rate", NULL); 486 + if (p && *p) { 487 + /* 488 + * Arrange to call chrp_event_scan at least *p times 489 + * per minute. We use 59 rather than 60 here so that 490 + * the rate will be slightly higher than the minimum. 491 + * This all assumes we don't do hotplug CPU on any 492 + * machine that needs the event scans done. 493 + */ 494 + unsigned long interval, offset; 495 + int cpu, ncpus; 496 + struct timer_list *timer; 497 + 498 + interval = HZ * 59 / *p; 499 + offset = HZ; 500 + ncpus = num_online_cpus(); 501 + event_scan_interval = ncpus * interval; 502 + for (cpu = 0; cpu < ncpus; ++cpu) { 503 + timer = &per_cpu(heartbeat_timer, cpu); 504 + setup_timer(timer, chrp_event_scan, 0); 505 + timer->expires = jiffies + offset; 506 + add_timer_on(timer, cpu); 507 + offset += interval; 508 + } 509 + printk("RTAS Event Scan Rate: %u (%lu jiffies)\n", 510 + *p, interval); 511 + } 470 512 471 513 if (ppc_md.progress) 472 514 ppc_md.progress(" Have fun! ", 0x7777);
-4
include/asm-powerpc/machdep.h
··· 176 176 May be NULL. */ 177 177 void (*init)(void); 178 178 179 - void (*heartbeat)(void); 180 - unsigned long heartbeat_reset; 181 - unsigned long heartbeat_count; 182 - 183 179 void (*setup_io_mappings)(void); 184 180 185 181 void (*early_serial_map)(void);