Index: 2.6-git2/arch/powerpc/kernel/rtas.c =================================================================== --- 2.6-git2.orig/arch/powerpc/kernel/rtas.c 2006-11-29 12:00:26.000000000 -0800 +++ 2.6-git2/arch/powerpc/kernel/rtas.c 2006-12-05 13:35:22.000000000 -0800 @@ -601,14 +601,32 @@ for (;;); } +/** + * rtas_power_off - tell firmware about how to power off the system. + * + * This function calls either the power-off rtas token in normal cases + * or the ibm,power-off-ups token (if present & requested) in case of + * a power failure. If power-off token is used, power on will only be + * possible with power button press. If ibm,power-off-ups token is used + * it will allow auto poweron after power is restored. + */ void rtas_power_off(void) { - if (rtas_flash_term_hook) - rtas_flash_term_hook(SYS_POWER_OFF); - /* allow power on only with power button press */ - printk("RTAS power-off returned %d\n", - rtas_call(rtas_token("power-off"), 2, 1, NULL, -1, -1)); - for (;;); + int rc; + int rtas_poweroff_ups_token = rtas_token("ibm,power-off-ups"); + + if (rtas_flash_term_hook) + rtas_flash_term_hook(SYS_POWER_OFF); + + if (rtas_poweron_auto == 0 || + rtas_poweroff_ups_token == RTAS_UNKNOWN_SERVICE) { + rc = rtas_call(rtas_token("power-off"), 2, 1, NULL, -1, -1); + printk(KERN_INFO "RTAS power-off returned %d\n", rc); + } else { + rc = rtas_call(rtas_poweroff_ups_token, 0, 1, NULL); + printk(KERN_INFO "RTAS ibm,power-off-ups returned %d\n", rc); + } + for (;;); } void rtas_halt(void) Index: 2.6-git2/arch/powerpc/kernel/rtas-proc.c =================================================================== --- 2.6-git2.orig/arch/powerpc/kernel/rtas-proc.c 2006-11-29 11:51:49.000000000 -0800 +++ 2.6-git2/arch/powerpc/kernel/rtas-proc.c 2006-12-05 12:00:47.000000000 -0800 @@ -122,6 +122,7 @@ static unsigned long rtas_tone_frequency = 1000; static unsigned long rtas_tone_volume = 0; +unsigned long rtas_poweron_auto; /* default and normal state is 0 */ /* ****************STRUCTS******************************************* */ struct individual_sensor { @@ -154,6 +155,9 @@ const char __user *buf, size_t count, loff_t *ppos); static int ppc_rtas_tone_volume_show(struct seq_file *m, void *v); static int ppc_rtas_rmo_buf_show(struct seq_file *m, void *v); +static int ppc_rtas_poweron_auto_show(struct seq_file *m, void *v); +static ssize_t ppc_rtas_poweron_auto_write(struct file *file, + const char __user *buf, size_t count, loff_t *ppos); static int sensors_open(struct inode *inode, struct file *file) { @@ -244,6 +248,18 @@ .release = single_release, }; +static int poweron_auto_open(struct inode *inode, struct file *file) +{ + return single_open(file, ppc_rtas_poweron_auto_show, NULL); +} + +struct file_operations ppc_rtas_poweron_auto_operations = { + .open = poweron_auto_open, + .read = seq_read, + .write = ppc_rtas_poweron_auto_write, + .release = single_release, +}; + static int ppc_rtas_find_all_sensors(void); static void ppc_rtas_process_sensor(struct seq_file *m, struct individual_sensor *s, int state, int error, const char *loc); @@ -293,6 +309,10 @@ if (entry) entry->proc_fops = &ppc_rtas_rmo_buf_ops; + entry = create_proc_entry("ppc64/rtas/poweron_auto", S_IRUGO|S_IWUSR, NULL); + if (entry) + entry->proc_fops = &ppc_rtas_poweron_auto_operations; + return 0; } @@ -805,3 +825,24 @@ seq_printf(m, "%016lx %x\n", rtas_rmo_buf, RTAS_RMOBUF_MAX); return 0; } + +static ssize_t ppc_rtas_poweron_auto_write(struct file *file, + const char __user *buf, size_t count, loff_t *ppos) +{ + unsigned long ups_restart; + int error = parse_number(buf, count, &ups_restart); + if (error) + return error; + + if (ups_restart) + rtas_poweron_auto = 1; + + return count; +} + +static int ppc_rtas_poweron_auto_show(struct seq_file *m, void *v) +{ + seq_printf(m, "%lu\n", rtas_poweron_auto); + return 0; + +} Index: 2.6-git2/include/asm-powerpc/rtas.h =================================================================== --- 2.6-git2.orig/include/asm-powerpc/rtas.h 2006-11-28 14:41:17.000000000 -0800 +++ 2.6-git2/include/asm-powerpc/rtas.h 2006-11-30 10:42:35.000000000 -0800 @@ -228,6 +228,9 @@ /* RMO buffer reserved for user-space RTAS use */ extern unsigned long rtas_rmo_buf; +/* Poweron buffer used for enabling auto ups restart */ +extern unsigned long rtas_poweron_auto; + #define GLOBAL_INTERRUPT_QUEUE 9005 /**