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

[POWERPC] PS3: Save power in busy loops on halt

PS3 save power on halt:
- Replace infinite busy loops by smarter loops calling
lv1_pause() to save power.
- Add ps3_halt() and ps3_sys_manager_halt().
- Add __noreturn annotations.

Signed-off-by: Geert Uytterhoeven <Geert.Uytterhoeven@sonycom.com>
Signed-off-by: Geoff Levand <geoffrey.levand@am.sony.com>
Signed-off-by: Paul Mackerras <paulus@samba.org>

authored by

Geert Uytterhoeven and committed by
Paul Mackerras
ca052f79 5761eaa3

+44 -19
+11 -1
arch/powerpc/platforms/ps3/setup.c
··· 95 95 ps3_sys_manager_power_off(); /* never returns */ 96 96 } 97 97 98 + static void ps3_halt(void) 99 + { 100 + DBG("%s:%d\n", __func__, __LINE__); 101 + 102 + smp_send_stop(); 103 + ps3_sys_manager_halt(); /* never returns */ 104 + } 105 + 98 106 static void ps3_panic(char *str) 99 107 { 100 108 DBG("%s:%d %s\n", __func__, __LINE__, str); ··· 113 105 printk(" Please press POWER button.\n"); 114 106 printk("\n"); 115 107 116 - while(1); 108 + while(1) 109 + lv1_pause(1); 117 110 } 118 111 119 112 #if defined(CONFIG_FB_PS3) || defined(CONFIG_FB_PS3_MODULE) || \ ··· 275 266 .progress = ps3_progress, 276 267 .restart = ps3_restart, 277 268 .power_off = ps3_power_off, 269 + .halt = ps3_halt, 278 270 #if defined(CONFIG_KEXEC) 279 271 .kexec_cpu_down = ps3_kexec_cpu_down, 280 272 .machine_kexec = default_machine_kexec,
+20 -10
drivers/ps3/ps3-sys-manager.c
··· 24 24 #include <linux/reboot.h> 25 25 26 26 #include <asm/firmware.h> 27 + #include <asm/lv1call.h> 27 28 #include <asm/ps3.h> 28 29 29 30 #include "vuart.h" ··· 582 581 return -EIO; 583 582 } 584 583 584 + static void ps3_sys_manager_fin(struct ps3_system_bus_device *dev) 585 + { 586 + ps3_sys_manager_send_request_shutdown(dev); 587 + 588 + pr_emerg("System Halted, OK to turn off power\n"); 589 + 590 + while (ps3_sys_manager_handle_msg(dev)) { 591 + /* pause until next DEC interrupt */ 592 + lv1_pause(0); 593 + } 594 + 595 + while (1) { 596 + /* pause, ignoring DEC interrupt */ 597 + lv1_pause(1); 598 + } 599 + } 600 + 585 601 /** 586 602 * ps3_sys_manager_final_power_off - The final platform machine_power_off routine. 587 603 * ··· 620 602 621 603 ps3_sys_manager_send_next_op(dev, PS3_SM_NEXT_OP_SYS_SHUTDOWN, 622 604 PS3_SM_WAKE_DEFAULT); 623 - ps3_sys_manager_send_request_shutdown(dev); 624 605 625 - pr_emerg("System Halted, OK to turn off power\n"); 626 - 627 - while (1) 628 - ps3_sys_manager_handle_msg(dev); 606 + ps3_sys_manager_fin(dev); 629 607 } 630 608 631 609 /** ··· 653 639 ps3_sys_manager_send_attr(dev, 0); 654 640 ps3_sys_manager_send_next_op(dev, PS3_SM_NEXT_OP_SYS_REBOOT, 655 641 PS3_SM_WAKE_DEFAULT); 656 - ps3_sys_manager_send_request_shutdown(dev); 657 642 658 - pr_emerg("System Halted, OK to turn off power\n"); 659 - 660 - while (1) 661 - ps3_sys_manager_handle_msg(dev); 643 + ps3_sys_manager_fin(dev); 662 644 } 663 645 664 646 /**
+10 -6
drivers/ps3/sys-manager-core.c
··· 19 19 */ 20 20 21 21 #include <linux/kernel.h> 22 + #include <asm/lv1call.h> 22 23 #include <asm/ps3.h> 23 24 24 25 /** ··· 51 50 if (ps3_sys_manager_ops.power_off) 52 51 ps3_sys_manager_ops.power_off(ps3_sys_manager_ops.dev); 53 52 54 - printk(KERN_EMERG "System Halted, OK to turn off power\n"); 55 - local_irq_disable(); 56 - while (1) 57 - (void)0; 53 + ps3_sys_manager_halt(); 58 54 } 59 55 60 56 void ps3_sys_manager_restart(void) ··· 59 61 if (ps3_sys_manager_ops.restart) 60 62 ps3_sys_manager_ops.restart(ps3_sys_manager_ops.dev); 61 63 62 - printk(KERN_EMERG "System Halted, OK to turn off power\n"); 64 + ps3_sys_manager_halt(); 65 + } 66 + 67 + void ps3_sys_manager_halt(void) 68 + { 69 + pr_emerg("System Halted, OK to turn off power\n"); 63 70 local_irq_disable(); 64 71 while (1) 65 - (void)0; 72 + lv1_pause(1); 66 73 } 74 +
+3 -2
include/asm-powerpc/ps3.h
··· 434 434 }; 435 435 436 436 void ps3_sys_manager_register_ops(const struct ps3_sys_manager_ops *ops); 437 - void ps3_sys_manager_power_off(void); 438 - void ps3_sys_manager_restart(void); 437 + void __noreturn ps3_sys_manager_power_off(void); 438 + void __noreturn ps3_sys_manager_restart(void); 439 + void __noreturn ps3_sys_manager_halt(void); 439 440 440 441 struct ps3_prealloc { 441 442 const char *name;