aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPavel Machek <pavel@ucw.cz>2005-06-25 17:55:11 -0400
committerLinus Torvalds <torvalds@ppc970.osdl.org>2005-06-25 19:24:33 -0400
commit620b03276488c3cf103caf1e326bd21f00d3df84 (patch)
treee2de713c76ddb42b091305b88aa7ca4938081789
parent5ce47e59c9688d8480ae41100117d8188c191401 (diff)
[PATCH] properly stop devices before poweroff
Without this patch, Linux provokes emergency disk shutdowns and similar nastiness. It was in SuSE kernels for some time, IIRC. Signed-off-by: Pavel Machek <pavel@suse.cz> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
-rw-r--r--include/linux/pm.h33
-rw-r--r--kernel/sys.c3
2 files changed, 24 insertions, 12 deletions
diff --git a/include/linux/pm.h b/include/linux/pm.h
index ed2b76e75199..14479325e3f3 100644
--- a/include/linux/pm.h
+++ b/include/linux/pm.h
@@ -103,7 +103,8 @@ extern int pm_active;
103/* 103/*
104 * Register a device with power management 104 * Register a device with power management
105 */ 105 */
106struct pm_dev __deprecated *pm_register(pm_dev_t type, unsigned long id, pm_callback callback); 106struct pm_dev __deprecated *
107pm_register(pm_dev_t type, unsigned long id, pm_callback callback);
107 108
108/* 109/*
109 * Unregister a device with power management 110 * Unregister a device with power management
@@ -190,17 +191,18 @@ typedef u32 __bitwise pm_message_t;
190/* 191/*
191 * There are 4 important states driver can be in: 192 * There are 4 important states driver can be in:
192 * ON -- driver is working 193 * ON -- driver is working
193 * FREEZE -- stop operations and apply whatever policy is applicable to a suspended driver 194 * FREEZE -- stop operations and apply whatever policy is applicable to a
194 * of that class, freeze queues for block like IDE does, drop packets for 195 * suspended driver of that class, freeze queues for block like IDE
195 * ethernet, etc... stop DMA engine too etc... so a consistent image can be 196 * does, drop packets for ethernet, etc... stop DMA engine too etc...
196 * saved; but do not power any hardware down. 197 * so a consistent image can be saved; but do not power any hardware
197 * SUSPEND - like FREEZE, but hardware is doing as much powersaving as possible. Roughly 198 * down.
198 * pci D3. 199 * SUSPEND - like FREEZE, but hardware is doing as much powersaving as
200 * possible. Roughly pci D3.
199 * 201 *
200 * Unfortunately, current drivers only recognize numeric values 0 (ON) and 3 (SUSPEND). 202 * Unfortunately, current drivers only recognize numeric values 0 (ON) and 3
201 * We'll need to fix the drivers. So yes, putting 3 to all diferent defines is intentional, 203 * (SUSPEND). We'll need to fix the drivers. So yes, putting 3 to all different
202 * and will go away as soon as drivers are fixed. Also note that typedef is neccessary, 204 * defines is intentional, and will go away as soon as drivers are fixed. Also
203 * we'll probably want to switch to 205 * note that typedef is neccessary, we'll probably want to switch to
204 * typedef struct pm_message_t { int event; int flags; } pm_message_t 206 * typedef struct pm_message_t { int event; int flags; } pm_message_t
205 * or something similar soon. 207 * or something similar soon.
206 */ 208 */
@@ -222,11 +224,18 @@ struct dev_pm_info {
222 224
223extern void device_pm_set_parent(struct device * dev, struct device * parent); 225extern void device_pm_set_parent(struct device * dev, struct device * parent);
224 226
225extern int device_suspend(pm_message_t state);
226extern int device_power_down(pm_message_t state); 227extern int device_power_down(pm_message_t state);
227extern void device_power_up(void); 228extern void device_power_up(void);
228extern void device_resume(void); 229extern void device_resume(void);
229 230
231#ifdef CONFIG_PM
232extern int device_suspend(pm_message_t state);
233#else
234static inline int device_suspend(pm_message_t state)
235{
236 return 0;
237}
238#endif
230 239
231#endif /* __KERNEL__ */ 240#endif /* __KERNEL__ */
232 241
diff --git a/kernel/sys.c b/kernel/sys.c
index da24bc1292db..dac10161ca23 100644
--- a/kernel/sys.c
+++ b/kernel/sys.c
@@ -405,6 +405,7 @@ asmlinkage long sys_reboot(int magic1, int magic2, unsigned int cmd, void __user
405 case LINUX_REBOOT_CMD_HALT: 405 case LINUX_REBOOT_CMD_HALT:
406 notifier_call_chain(&reboot_notifier_list, SYS_HALT, NULL); 406 notifier_call_chain(&reboot_notifier_list, SYS_HALT, NULL);
407 system_state = SYSTEM_HALT; 407 system_state = SYSTEM_HALT;
408 device_suspend(PMSG_SUSPEND);
408 device_shutdown(); 409 device_shutdown();
409 printk(KERN_EMERG "System halted.\n"); 410 printk(KERN_EMERG "System halted.\n");
410 machine_halt(); 411 machine_halt();
@@ -415,6 +416,7 @@ asmlinkage long sys_reboot(int magic1, int magic2, unsigned int cmd, void __user
415 case LINUX_REBOOT_CMD_POWER_OFF: 416 case LINUX_REBOOT_CMD_POWER_OFF:
416 notifier_call_chain(&reboot_notifier_list, SYS_POWER_OFF, NULL); 417 notifier_call_chain(&reboot_notifier_list, SYS_POWER_OFF, NULL);
417 system_state = SYSTEM_POWER_OFF; 418 system_state = SYSTEM_POWER_OFF;
419 device_suspend(PMSG_SUSPEND);
418 device_shutdown(); 420 device_shutdown();
419 printk(KERN_EMERG "Power down.\n"); 421 printk(KERN_EMERG "Power down.\n");
420 machine_power_off(); 422 machine_power_off();
@@ -431,6 +433,7 @@ asmlinkage long sys_reboot(int magic1, int magic2, unsigned int cmd, void __user
431 433
432 notifier_call_chain(&reboot_notifier_list, SYS_RESTART, buffer); 434 notifier_call_chain(&reboot_notifier_list, SYS_RESTART, buffer);
433 system_state = SYSTEM_RESTART; 435 system_state = SYSTEM_RESTART;
436 device_suspend(PMSG_FREEZE);
434 device_shutdown(); 437 device_shutdown();
435 printk(KERN_EMERG "Restarting system with command '%s'.\n", buffer); 438 printk(KERN_EMERG "Restarting system with command '%s'.\n", buffer);
436 machine_restart(buffer); 439 machine_restart(buffer);