Sophie

Sophie

distrib > Scientific%20Linux > 5x > x86_64 > by-pkgid > fc11cd6e1c513a17304da94a5390f3cd > files > 3000

kernel-2.6.18-194.11.1.el5.src.rpm

From: Scott Moser <smoser@redhat.com>
Subject: [RHEL5.1 PATCH] bz184681 [PPC] Support for ibm,power-off-ups RTAS  call
Date: Thu, 10 May 2007 11:53:58 -0400 (EDT)
Bugzilla: 184681
Message-Id: <Pine.LNX.4.64.0705101151010.9606@squad1-lp1.lab.boston.redhat.com>
Changelog: [PPC64] Support for ibm,power-off-ups RTAS  call


RHBZ#: 184681 [FEATURE]
------
https://bugzilla.redhat.com/bugzilla/show_bug.cgi?id=184681

Description:
------------
During power outages, the ups notifies the system for a shutdown. In the
current setup, it isn't possible to poweron when power is restored. This
patch fixes the issue by calling the right ibm,power-off-ups token during
such events. It also adds a sysfs interface so that rc.powerfail can parse
the epow events and modify the power-off behavior accordingly to enable
the right token to be called.

This has very low risk of causing issues in the system. The generic method
already is in place and if this new feature is somehow not enabled it will
revert back to the current method of providing service.

This feature enables auto-poweron in pseries systems only.
It adds a new interface in sysfs as /sys/power/auto_poweron

RHEL Version Found:
-------------------
requested as a feature for 5.1

Upstream Status:
----------------
This bug is present in uptream since 2007/02/08 (commit
5d30bf309717a518d0c4180af41650d4dcd3bb38)
http://git.kernel.org/gitweb.cgi?p=linux/kernel/git/torvalds/linux-2.6.git;a=commit;h=5d30bf309717a518d0c4180af41650d4dcd3bb38

Test Status:
------------
This code has been tested by Manish Ahuja of IBM using the following test:
 
1. Make sure that default shutdown works as defined and nothing different
happens.

2. Generate a epow event from vsp and send to partition and check
behaviour. This should allow ability to reboot when power is restored,
when the firmware policy for the system is set to reboot when power is
restored.

Test Results:
Both test cases work as defined above. This code tests out okay. 
For any issues please open a bugzilla entry for it.

Proposed Patch:
----------------
Please review and ACK for RHEL5.1

-- 
 arch/powerpc/platforms/pseries/Makefile |    2 
 arch/powerpc/platforms/pseries/power.c  |   87 ++++++++++++++++++++++++++++++++
 arch/powerpc/platforms/pseries/setup.c  |   30 ++++++++++-
 include/asm-powerpc/rtas.h              |    3 +
 4 files changed, 120 insertions(+), 2 deletions(-)

Index: b/arch/powerpc/platforms/pseries/power.c
===================================================================
--- /dev/null
+++ b/arch/powerpc/platforms/pseries/power.c
@@ -0,0 +1,87 @@
+/*
+ *  Interface for power-management for ppc64 compliant platform
+ *
+ *  Manish Ahuja <mahuja@us.ibm.com>
+ *
+ *  Feb 2007
+ *
+ *  Copyright (C) 2007 IBM Corporation.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; version 2 of the License.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include <linux/kobject.h>
+#include <linux/string.h>
+#include <linux/errno.h>
+#include <linux/init.h>
+
+unsigned long rtas_poweron_auto; /* default and normal state is 0 */
+
+static ssize_t auto_poweron_show(struct subsystem * subsys, char * buf)
+{
+        return sprintf(buf, "%lu\n", rtas_poweron_auto);
+}
+
+static ssize_t
+auto_poweron_store(struct subsystem * subsys, const char * buf, size_t n)
+{
+	int ret;
+	unsigned long ups_restart;
+	ret = sscanf(buf, "%lu", &ups_restart);
+
+	if ((ret == 1) && ((ups_restart == 1) || (ups_restart == 0))){
+		rtas_poweron_auto = ups_restart;
+		return n;
+	}
+	return -EINVAL;
+}
+
+static struct subsys_attribute auto_poweron_attr = {
+        .attr   = {
+                .name = __stringify(auto_poweron),
+                .mode = 0644,
+        },
+        .show   = auto_poweron_show,
+        .store  = auto_poweron_store,
+};
+
+#ifndef CONFIG_PM
+decl_subsys(power,NULL,NULL);
+
+static struct attribute * g[] = {
+        &auto_poweron_attr.attr,
+        NULL,
+};
+
+static struct attribute_group attr_group = {
+        .attrs = g,
+};
+
+static int __init pm_init(void)
+{
+        int error = subsystem_register(&power_subsys);
+        if (!error)
+                error = sysfs_create_group(&power_subsys.kset.kobj,&attr_group);
+        return error;
+}
+core_initcall(pm_init);
+#else
+extern struct subsystem power_subsys;
+
+static int __init apo_pm_init(void)
+{
+	return(subsys_create_file(&power_subsys, &auto_poweron_attr));
+}
+__initcall(apo_pm_init);
+#endif
Index: b/arch/powerpc/platforms/pseries/Makefile
===================================================================
--- a/arch/powerpc/platforms/pseries/Makefile
+++ b/arch/powerpc/platforms/pseries/Makefile
@@ -4,7 +4,7 @@ endif
 
 obj-y			:= pci.o lpar.o hvCall.o nvram.o reconfig.o \
 			   setup.o iommu.o ras.o rtasd.o pci_dlpar.o \
-			   firmware.o
+			   firmware.o power.o
 obj-$(CONFIG_SMP)	+= smp.o
 obj-$(CONFIG_XICS)	+= xics.o
 obj-$(CONFIG_SCANLOG)	+= scanlog.o
Index: b/arch/powerpc/platforms/pseries/setup.c
===================================================================
--- a/arch/powerpc/platforms/pseries/setup.c
+++ b/arch/powerpc/platforms/pseries/setup.c
@@ -549,6 +549,34 @@ static int pSeries_pci_probe_mode(struct
 	return PCI_PROBE_NORMAL;
 }
 
+/**
+ * pSeries_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 pSeries_power_off(void)
+{
+	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 (;;);
+}
+
 define_machine(pseries) {
 	.name			= "pSeries",
 	.probe			= pSeries_probe,
@@ -560,7 +588,7 @@ define_machine(pseries) {
 	.pci_probe_mode		= pSeries_pci_probe_mode,
 	.irq_bus_setup		= pSeries_irq_bus_setup,
 	.restart		= rtas_restart,
-	.power_off		= rtas_power_off,
+	.power_off		= pSeries_power_off,
 	.halt			= rtas_halt,
 	.panic			= rtas_os_term,
 	.cpu_die		= pSeries_mach_cpu_die,
Index: b/include/asm-powerpc/rtas.h
===================================================================
--- a/include/asm-powerpc/rtas.h
+++ b/include/asm-powerpc/rtas.h
@@ -225,6 +225,9 @@ extern char rtas_data_buf[RTAS_DATA_BUF_
 
 extern void rtas_stop_self(void);
 
+/* Poweron buffer used for enabling auto ups restart */
+extern unsigned long rtas_poweron_auto;
+
 /* RMO buffer reserved for user-space RTAS use */
 extern unsigned long rtas_rmo_buf;