LinuxPPC-Dev Archive on lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 30/44] acpi: Register poweroff handler with kernel poweroff handler
From: Guenter Roeck @ 2014-10-07  5:28 UTC (permalink / raw)
  To: linux-kernel
  Cc: linux-m32r-ja, linux-mips, linux-efi, linux-ia64, linux-xtensa,
	devel, linux-s390, lguest, linux-c6x-dev, linux-hexagon, linux-sh,
	linux-acpi, xen-devel, Guenter Roeck, Len Brown, devicetree,
	user-mode-linux-devel, linux-pm, adi-buildroot-devel, linux-m68k,
	linux-am33-list, linux-tegra, openipmi-developer, linux-metag,
	linux-arm-kernel, linux-parisc, linux-cris-kernel,
	Rafael J. Wysocki, linux-alpha, linuxppc-dev
In-Reply-To: <1412659726-29957-1-git-send-email-linux@roeck-us.net>

Register with kernel poweroff handler instead of setting pm_power_off
directly. Register with high priority value of 192 to reflect that
the driver explicitly overrides existing poweroff handlers.

Cc: Rafael J. Wysocki <rjw@rjwysocki.net>
Cc: Len Brown <lenb@kernel.org>
Signed-off-by: Guenter Roeck <linux@roeck-us.net>
---
 drivers/acpi/sleep.c | 15 +++++++++++++--
 1 file changed, 13 insertions(+), 2 deletions(-)

diff --git a/drivers/acpi/sleep.c b/drivers/acpi/sleep.c
index 54da4a3..25aad22 100644
--- a/drivers/acpi/sleep.c
+++ b/drivers/acpi/sleep.c
@@ -15,6 +15,8 @@
 #include <linux/dmi.h>
 #include <linux/device.h>
 #include <linux/suspend.h>
+#include <linux/notifier.h>
+#include <linux/pm.h>
 #include <linux/reboot.h>
 #include <linux/acpi.h>
 #include <linux/module.h>
@@ -811,14 +813,22 @@ static void acpi_power_off_prepare(void)
 	acpi_disable_all_gpes();
 }
 
-static void acpi_power_off(void)
+static int acpi_power_off(struct notifier_block *this,
+			  unsigned long unused1, void *unused2)
 {
 	/* acpi_sleep_prepare(ACPI_STATE_S5) should have already been called */
 	printk(KERN_DEBUG "%s called\n", __func__);
 	local_irq_disable();
 	acpi_enter_sleep_state(ACPI_STATE_S5);
+
+	return NOTIFY_DONE;
 }
 
+static struct notifier_block acpi_poweroff_nb = {
+	.notifier_call = acpi_power_off,
+	.priority = 192,
+};
+
 int __init acpi_sleep_init(void)
 {
 	char supported[ACPI_S_STATE_COUNT * 3 + 1];
@@ -835,7 +845,8 @@ int __init acpi_sleep_init(void)
 	if (acpi_sleep_state_supported(ACPI_STATE_S5)) {
 		sleep_states[ACPI_STATE_S5] = 1;
 		pm_power_off_prepare = acpi_power_off_prepare;
-		pm_power_off = acpi_power_off;
+		if (register_poweroff_handler(&acpi_poweroff_nb))
+			pr_err("acpi: Failed to register poweroff handler\n");
 	}
 
 	supported[0] = 0;
-- 
1.9.1

^ permalink raw reply related

* [PATCH 28/44] x86: olpc: Register xo1 poweroff handler with kernel poweroff handler
From: Guenter Roeck @ 2014-10-07  5:28 UTC (permalink / raw)
  To: linux-kernel
  Cc: linux-m32r-ja, linux-mips, linux-efi, linux-ia64, linux-xtensa,
	H. Peter Anvin, Thomas Gleixner, devel, linux-s390, lguest,
	linux-c6x-dev, linux-hexagon, linux-sh, linux-acpi, Ingo Molnar,
	xen-devel, Guenter Roeck, devicetree, user-mode-linux-devel,
	linux-pm, adi-buildroot-devel, linux-m68k, linux-am33-list,
	linux-tegra, openipmi-developer, linux-metag, linux-arm-kernel,
	linux-parisc, linux-cris-kernel, linux-alpha, linuxppc-dev
In-Reply-To: <1412659726-29957-1-git-send-email-linux@roeck-us.net>

Register with kernel poweroff handler instead of setting pm_power_off
directly. Register with high priority value of 192 to reflect that
the driver explicitly wants to override default poweroff handlers.

Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: Ingo Molnar <mingo@redhat.com>
Cc: H. Peter Anvin <hpa@zytor.com>
Signed-off-by: Guenter Roeck <linux@roeck-us.net>
---
 arch/x86/platform/olpc/olpc-xo1-pm.c | 20 +++++++++++++++++---
 1 file changed, 17 insertions(+), 3 deletions(-)

diff --git a/arch/x86/platform/olpc/olpc-xo1-pm.c b/arch/x86/platform/olpc/olpc-xo1-pm.c
index a9acde7..96fba36 100644
--- a/arch/x86/platform/olpc/olpc-xo1-pm.c
+++ b/arch/x86/platform/olpc/olpc-xo1-pm.c
@@ -15,6 +15,7 @@
 #include <linux/cs5535.h>
 #include <linux/platform_device.h>
 #include <linux/export.h>
+#include <linux/notifier.h>
 #include <linux/pm.h>
 #include <linux/mfd/core.h>
 #include <linux/suspend.h>
@@ -92,7 +93,8 @@ asmlinkage __visible int xo1_do_sleep(u8 sleep_state)
 	return 0;
 }
 
-static void xo1_power_off(void)
+static int xo1_power_off(struct notifier_block *this, unsigned long unused1,
+			 void *unused2)
 {
 	printk(KERN_INFO "OLPC XO-1 power off sequence...\n");
 
@@ -108,8 +110,15 @@ static void xo1_power_off(void)
 
 	/* Write SLP_EN bit to start the machinery */
 	outl(0x00002000, acpi_base + CS5536_PM1_CNT);
+
+	return NOTIFY_DONE;
 }
 
+static struct notifier_block xo1_poweroff_nb = {
+	.notifier_call = xo1_power_off,
+	.priority = 192,
+};
+
 static int xo1_power_state_valid(suspend_state_t pm_state)
 {
 	/* suspend-to-RAM only */
@@ -146,8 +155,12 @@ static int xo1_pm_probe(struct platform_device *pdev)
 
 	/* If we have both addresses, we can override the poweroff hook */
 	if (pms_base && acpi_base) {
+		err = register_poweroff_handler(&xo1_poweroff_nb);
+		if (err) {
+			dev_err(&pdev->dev, "Failed to register poweroff handler\n");
+			return err;
+		}
 		suspend_set_ops(&xo1_suspend_ops);
-		pm_power_off = xo1_power_off;
 		printk(KERN_INFO "OLPC XO-1 support registered\n");
 	}
 
@@ -158,12 +171,13 @@ static int xo1_pm_remove(struct platform_device *pdev)
 {
 	mfd_cell_disable(pdev);
 
+	unregister_poweroff_handler(&xo1_poweroff_nb);
+
 	if (strcmp(pdev->name, "cs5535-pms") == 0)
 		pms_base = 0;
 	else if (strcmp(pdev->name, "olpc-xo1-pm-acpi") == 0)
 		acpi_base = 0;
 
-	pm_power_off = NULL;
 	return 0;
 }
 
-- 
1.9.1

^ permalink raw reply related

* [PATCH 29/44] staging: nvec: Register with kernel poweroff handler
From: Guenter Roeck @ 2014-10-07  5:28 UTC (permalink / raw)
  To: linux-kernel
  Cc: linux-m32r-ja, linux-mips, linux-efi, linux-ia64, linux-xtensa,
	devel, linux-s390, lguest, linux-c6x-dev, linux-hexagon, linux-sh,
	linux-acpi, xen-devel, Guenter Roeck, devicetree,
	user-mode-linux-devel, linux-pm, Julian Andres Klode,
	adi-buildroot-devel, linux-m68k, linux-am33-list, linux-tegra,
	openipmi-developer, linux-metag, linux-arm-kernel, linux-parisc,
	linux-cris-kernel, Greg Kroah-Hartman, linux-alpha, linuxppc-dev
In-Reply-To: <1412659726-29957-1-git-send-email-linux@roeck-us.net>

Register with kernel poweroff handler instead of setting pm_power_off
directly. Register with default priority value of 128 since we don't know
any better.

Cc: Julian Andres Klode <jak@jak-linux.org>
Cc: Marc Dietrich <marvin24@gmx.de>
Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Signed-off-by: Guenter Roeck <linux@roeck-us.net>
---
 drivers/staging/nvec/nvec.c | 24 +++++++++++++++---------
 drivers/staging/nvec/nvec.h |  2 ++
 2 files changed, 17 insertions(+), 9 deletions(-)

diff --git a/drivers/staging/nvec/nvec.c b/drivers/staging/nvec/nvec.c
index a93208a..33d406c 100644
--- a/drivers/staging/nvec/nvec.c
+++ b/drivers/staging/nvec/nvec.c
@@ -33,6 +33,7 @@
 #include <linux/mfd/core.h>
 #include <linux/mutex.h>
 #include <linux/notifier.h>
+#include <linux/pm.h>
 #include <linux/slab.h>
 #include <linux/spinlock.h>
 #include <linux/workqueue.h>
@@ -80,8 +81,6 @@ enum nvec_sleep_subcmds {
 #define LID_SWITCH BIT(1)
 #define PWR_BUTTON BIT(15)
 
-static struct nvec_chip *nvec_power_handle;
-
 static const struct mfd_cell nvec_devices[] = {
 	{
 		.name = "nvec-kbd",
@@ -759,12 +758,17 @@ static void nvec_disable_i2c_slave(struct nvec_chip *nvec)
 }
 #endif
 
-static void nvec_power_off(void)
+static int nvec_power_off(struct notifier_block *this, unsigned long unused1,
+			  void *unused2)
 {
+	struct nvec_chip *nvec = container_of(this, struct nvec_chip,
+					      poweroff_nb);
 	char ap_pwr_down[] = { NVEC_SLEEP, AP_PWR_DOWN };
 
-	nvec_toggle_global_events(nvec_power_handle, false);
-	nvec_write_async(nvec_power_handle, ap_pwr_down, 2);
+	nvec_toggle_global_events(nvec, false);
+	nvec_write_async(nvec, ap_pwr_down, 2);
+
+	return NOTIFY_DONE;
 }
 
 /*
@@ -878,8 +882,11 @@ static int tegra_nvec_probe(struct platform_device *pdev)
 	nvec->nvec_status_notifier.notifier_call = nvec_status_notifier;
 	nvec_register_notifier(nvec, &nvec->nvec_status_notifier, 0);
 
-	nvec_power_handle = nvec;
-	pm_power_off = nvec_power_off;
+	nvec->poweroff_nb.notifier_call = nvec_power_off;
+	nvec->poweroff_nb.priority = 128;
+	ret = register_poweroff_handler(&nvec->poweroff_nb);
+	if (ret)
+		dev_err(nvec->dev, "Failed to register poweroff handler\n");
 
 	/* Get Firmware Version */
 	msg = nvec_write_sync(nvec, get_firmware_version, 2);
@@ -914,13 +921,12 @@ static int tegra_nvec_remove(struct platform_device *pdev)
 {
 	struct nvec_chip *nvec = platform_get_drvdata(pdev);
 
+	unregister_poweroff_handler(&nvec->poweroff_nb);
 	nvec_toggle_global_events(nvec, false);
 	mfd_remove_devices(nvec->dev);
 	nvec_unregister_notifier(nvec, &nvec->nvec_status_notifier);
 	cancel_work_sync(&nvec->rx_work);
 	cancel_work_sync(&nvec->tx_work);
-	/* FIXME: needs check wether nvec is responsible for power off */
-	pm_power_off = NULL;
 
 	return 0;
 }
diff --git a/drivers/staging/nvec/nvec.h b/drivers/staging/nvec/nvec.h
index e271375..e5ee2af 100644
--- a/drivers/staging/nvec/nvec.h
+++ b/drivers/staging/nvec/nvec.h
@@ -163,6 +163,8 @@ struct nvec_chip {
 	struct nvec_msg *last_sync_msg;
 
 	int state;
+
+	struct notifier_block poweroff_nb;
 };
 
 extern int nvec_write_async(struct nvec_chip *nvec, const unsigned char *data,
-- 
1.9.1

^ permalink raw reply related

* [PATCH 32/44] arm64: psci: Register with kernel poweroff handler
From: Guenter Roeck @ 2014-10-07  5:28 UTC (permalink / raw)
  To: linux-kernel
  Cc: linux-m32r-ja, linux-mips, linux-efi, linux-ia64, linux-xtensa,
	Catalin Marinas, Will Deacon, devel, linux-s390, lguest,
	linux-c6x-dev, linux-hexagon, linux-sh, linux-acpi, xen-devel,
	Guenter Roeck, devicetree, user-mode-linux-devel, linux-pm,
	adi-buildroot-devel, linux-m68k, linux-am33-list, linux-tegra,
	openipmi-developer, linux-metag, linux-arm-kernel, linux-parisc,
	linux-cris-kernel, linux-alpha, linuxppc-dev
In-Reply-To: <1412659726-29957-1-git-send-email-linux@roeck-us.net>

Register with kernel poweroff handler instead of setting pm_power_off
directly.

Cc: Catalin Marinas <catalin.marinas@arm.com>
Cc: Will Deacon <will.deacon@arm.com>
Signed-off-by: Guenter Roeck <linux@roeck-us.net>
---
 arch/arm64/kernel/psci.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/arch/arm64/kernel/psci.c b/arch/arm64/kernel/psci.c
index 5539547..c1f3d09 100644
--- a/arch/arm64/kernel/psci.c
+++ b/arch/arm64/kernel/psci.c
@@ -286,7 +286,7 @@ static int __init psci_0_2_init(struct device_node *np)
 
 	arm_pm_restart = psci_sys_reset;
 
-	pm_power_off = psci_sys_poweroff;
+	register_poweroff_handler_simple(psci_sys_poweroff, 128);
 
 out_put_node:
 	of_node_put(np);
-- 
1.9.1

^ permalink raw reply related

* [PATCH 33/44] avr32: atngw100: Register with kernel poweroff handler
From: Guenter Roeck @ 2014-10-07  5:28 UTC (permalink / raw)
  To: linux-kernel
  Cc: linux-m32r-ja, linux-mips, linux-efi, linux-ia64, linux-xtensa,
	Hans-Christian Egtvedt, devel, linux-s390, lguest, linux-c6x-dev,
	linux-hexagon, linux-sh, linux-acpi, xen-devel, Guenter Roeck,
	Haavard Skinnemoen, devicetree, user-mode-linux-devel, linux-pm,
	adi-buildroot-devel, linux-m68k, linux-am33-list, linux-tegra,
	openipmi-developer, linux-metag, linux-arm-kernel, linux-parisc,
	linux-cris-kernel, linux-alpha, linuxppc-dev
In-Reply-To: <1412659726-29957-1-git-send-email-linux@roeck-us.net>

Register with kernel poweroff handler instead of setting pm_power_off
directly.

Cc: Haavard Skinnemoen <hskinnemoen@gmail.com>
Cc: Hans-Christian Egtvedt <egtvedt@samfundet.no>
Signed-off-by: Guenter Roeck <linux@roeck-us.net>
---
 arch/avr32/boards/atngw100/mrmt.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/arch/avr32/boards/atngw100/mrmt.c b/arch/avr32/boards/atngw100/mrmt.c
index 91146b4..54d0c27 100644
--- a/arch/avr32/boards/atngw100/mrmt.c
+++ b/arch/avr32/boards/atngw100/mrmt.c
@@ -274,7 +274,7 @@ static int __init mrmt1_init(void)
 {
 	gpio_set_value( PIN_PWR_ON, 1 );	/* Ensure PWR_ON is enabled */
 
-	pm_power_off = mrmt_power_off;
+	register_poweroff_handler_simple(mrmt_power_off, 128);
 
 	/* Setup USARTS (other than console) */
 	at32_map_usart(2, 1, 0);	/* USART 2: /dev/ttyS1, RMT1:DB9M */
-- 
1.9.1

^ permalink raw reply related

* [PATCH 31/44] arm: Register with kernel poweroff handler
From: Guenter Roeck @ 2014-10-07  5:28 UTC (permalink / raw)
  To: linux-kernel
  Cc: linux-m32r-ja, linux-mips, linux-efi, linux-ia64, Anton Vorontsov,
	Stephen Warren, linux-xtensa, Tony Lindgren, Linus Walleij,
	Nicolas Ferre, Andrew Lunn, Kukjin Kim, Robert Jarzmik,
	Stefano Stabellini, devel, linux-s390, lguest, Russell King,
	linux-c6x-dev, Marek Vasut, linux-hexagon, linux-sh,
	Andrew Victor, linux-acpi, Shawn Guo, xen-devel,
	Jean-Christophe Plagniol-Villard, Rob Herring, Guenter Roeck,
	Sebastian Hesselbarth, devicetree, Jason Cooper,
	user-mode-linux-devel, linux-pm, adi-buildroot-devel, Matt Porter,
	linux-m68k, linux-am33-list, Haojian Zhuang, Ben Dooks,
	linux-tegra, openipmi-developer, linux-metag, linux-arm-kernel,
	Eric Miao, linux-parisc, linux-cris-kernel, Christian Daudt,
	Tony Prisk, Sascha Hauer, linux-alpha, linuxppc-dev,
	Krzysztof Halasa
In-Reply-To: <1412659726-29957-1-git-send-email-linux@roeck-us.net>

Register with kernel poweroff handler instead of setting pm_power_off
directly. Always use register_poweroff_handler_simple as there is no
indication that more than one poweroff handler is registered.

If the poweroff handler only resets the system or puts the CPU in sleep mode,
select a priority of 0 to indicate that the poweroff handler is one of last
resort. If the poweroff handler powers off the system, select a priority
of 128.

Cc: Russell King <linux@arm.linux.org.uk>
Cc: Andrew Victor <linux@maxim.org.za>
Cc: Nicolas Ferre <nicolas.ferre@atmel.com>
Cc: Jean-Christophe Plagniol-Villard <plagnioj@jcrosoft.com>
Cc: Stephen Warren <swarren@wwwdotorg.org>
Cc: Christian Daudt <bcm@fixthebug.org>
Cc: Matt Porter <mporter@linaro.org>
Cc: Anton Vorontsov <anton@enomsg.org>
Cc: Rob Herring <robh@kernel.org>
Cc: Shawn Guo <shawn.guo@freescale.com>
Cc: Sascha Hauer <kernel@pengutronix.de>
Cc: Imre Kaloz <kaloz@openwrt.org>
Cc: Krzysztof Halasa <khc@pm.waw.pl>
Cc: Tony Lindgren <tony@atomide.com>
Cc: Jason Cooper <jason@lakedaemon.net>
Cc: Andrew Lunn <andrew@lunn.ch>
Cc: Sebastian Hesselbarth <sebastian.hesselbarth@gmail.com>
Cc: Eric Miao <eric.y.miao@gmail.com>
Cc: Haojian Zhuang <haojian.zhuang@gmail.com>
Cc: Robert Jarzmik <robert.jarzmik@free.fr>
Cc: Marek Vasut <marek.vasut@gmail.com>
Cc: Ben Dooks <ben-linux@fluff.org>
Cc: Kukjin Kim <kgene.kim@samsung.com>
Cc: Linus Walleij <linus.walleij@linaro.org>
Cc: Tony Prisk <linux@prisktech.co.nz>
Cc: Stefano Stabellini <stefano.stabellini@eu.citrix.com>
Signed-off-by: Guenter Roeck <linux@roeck-us.net>
---
 arch/arm/kernel/psci.c                         | 2 +-
 arch/arm/mach-at91/board-gsia18s.c             | 2 +-
 arch/arm/mach-at91/setup.c                     | 4 ++--
 arch/arm/mach-bcm/board_bcm2835.c              | 2 +-
 arch/arm/mach-cns3xxx/cns3420vb.c              | 2 +-
 arch/arm/mach-cns3xxx/core.c                   | 2 +-
 arch/arm/mach-highbank/highbank.c              | 2 +-
 arch/arm/mach-imx/mach-mx31moboard.c           | 2 +-
 arch/arm/mach-iop32x/em7210.c                  | 2 +-
 arch/arm/mach-iop32x/glantank.c                | 2 +-
 arch/arm/mach-iop32x/iq31244.c                 | 2 +-
 arch/arm/mach-iop32x/n2100.c                   | 2 +-
 arch/arm/mach-ixp4xx/dsmg600-setup.c           | 2 +-
 arch/arm/mach-ixp4xx/nas100d-setup.c           | 2 +-
 arch/arm/mach-ixp4xx/nslu2-setup.c             | 2 +-
 arch/arm/mach-omap2/board-omap3touchbook.c     | 2 +-
 arch/arm/mach-orion5x/board-mss2.c             | 2 +-
 arch/arm/mach-orion5x/dns323-setup.c           | 6 +++---
 arch/arm/mach-orion5x/kurobox_pro-setup.c      | 2 +-
 arch/arm/mach-orion5x/ls-chl-setup.c           | 2 +-
 arch/arm/mach-orion5x/ls_hgl-setup.c           | 2 +-
 arch/arm/mach-orion5x/lsmini-setup.c           | 2 +-
 arch/arm/mach-orion5x/mv2120-setup.c           | 2 +-
 arch/arm/mach-orion5x/net2big-setup.c          | 2 +-
 arch/arm/mach-orion5x/terastation_pro2-setup.c | 2 +-
 arch/arm/mach-orion5x/ts209-setup.c            | 2 +-
 arch/arm/mach-orion5x/ts409-setup.c            | 2 +-
 arch/arm/mach-pxa/corgi.c                      | 2 +-
 arch/arm/mach-pxa/mioa701.c                    | 2 +-
 arch/arm/mach-pxa/poodle.c                     | 2 +-
 arch/arm/mach-pxa/spitz.c                      | 2 +-
 arch/arm/mach-pxa/tosa.c                       | 2 +-
 arch/arm/mach-pxa/viper.c                      | 2 +-
 arch/arm/mach-pxa/z2.c                         | 6 +++---
 arch/arm/mach-pxa/zeus.c                       | 6 +++---
 arch/arm/mach-s3c24xx/mach-gta02.c             | 2 +-
 arch/arm/mach-s3c24xx/mach-jive.c              | 2 +-
 arch/arm/mach-s3c24xx/mach-vr1000.c            | 2 +-
 arch/arm/mach-s3c64xx/mach-smartq.c            | 2 +-
 arch/arm/mach-sa1100/generic.c                 | 2 +-
 arch/arm/mach-sa1100/simpad.c                  | 2 +-
 arch/arm/mach-u300/regulator.c                 | 2 +-
 arch/arm/mach-vt8500/vt8500.c                  | 2 +-
 arch/arm/xen/enlighten.c                       | 2 +-
 44 files changed, 51 insertions(+), 51 deletions(-)

diff --git a/arch/arm/kernel/psci.c b/arch/arm/kernel/psci.c
index f73891b..dd58d86 100644
--- a/arch/arm/kernel/psci.c
+++ b/arch/arm/kernel/psci.c
@@ -264,7 +264,7 @@ static int psci_0_2_init(struct device_node *np)
 
 	arm_pm_restart = psci_sys_reset;
 
-	pm_power_off = psci_sys_poweroff;
+	register_poweroff_handler_simple(psci_sys_poweroff, 128);
 
 out_put_node:
 	of_node_put(np);
diff --git a/arch/arm/mach-at91/board-gsia18s.c b/arch/arm/mach-at91/board-gsia18s.c
index b729dd1..6722e66 100644
--- a/arch/arm/mach-at91/board-gsia18s.c
+++ b/arch/arm/mach-at91/board-gsia18s.c
@@ -521,7 +521,7 @@ static void gsia18s_power_off(void)
 
 static int __init gsia18s_power_off_init(void)
 {
-	pm_power_off = gsia18s_power_off;
+	register_poweroff_handler_simple(gsia18s_power_off, 128);
 	return 0;
 }
 
diff --git a/arch/arm/mach-at91/setup.c b/arch/arm/mach-at91/setup.c
index f7a07a5..9989e88 100644
--- a/arch/arm/mach-at91/setup.c
+++ b/arch/arm/mach-at91/setup.c
@@ -329,7 +329,7 @@ void __init at91_ioremap_shdwc(u32 base_addr)
 	at91_shdwc_base = ioremap(base_addr, 16);
 	if (!at91_shdwc_base)
 		panic("Impossible to ioremap at91_shdwc_base\n");
-	pm_power_off = at91sam9_poweroff;
+	register_poweroff_handler_simple(at91sam9_poweroff, 128);
 }
 
 void __iomem *at91_rstc_base;
@@ -482,7 +482,7 @@ static void at91_dt_shdwc(void)
 	at91_shdwc_write(AT91_SHDW_MR, wakeup_mode | mode);
 
 end:
-	pm_power_off = at91sam9_poweroff;
+	register_poweroff_handler_simple(at91sam9_poweroff, 128);
 
 	of_node_put(np);
 }
diff --git a/arch/arm/mach-bcm/board_bcm2835.c b/arch/arm/mach-bcm/board_bcm2835.c
index 70f2f39..7d5784f 100644
--- a/arch/arm/mach-bcm/board_bcm2835.c
+++ b/arch/arm/mach-bcm/board_bcm2835.c
@@ -111,7 +111,7 @@ static void __init bcm2835_init(void)
 
 	bcm2835_setup_restart();
 	if (wdt_regs)
-		pm_power_off = bcm2835_power_off;
+		register_poweroff_handler_simple(bcm2835_power_off, 0);
 
 	bcm2835_init_clocks();
 
diff --git a/arch/arm/mach-cns3xxx/cns3420vb.c b/arch/arm/mach-cns3xxx/cns3420vb.c
index d863d87..136b7c6 100644
--- a/arch/arm/mach-cns3xxx/cns3420vb.c
+++ b/arch/arm/mach-cns3xxx/cns3420vb.c
@@ -224,7 +224,7 @@ static void __init cns3420_init(void)
 	cns3xxx_ahci_init();
 	cns3xxx_sdhci_init();
 
-	pm_power_off = cns3xxx_power_off;
+	register_poweroff_handler_simple(cns3xxx_power_off, 128);
 }
 
 static struct map_desc cns3420_io_desc[] __initdata = {
diff --git a/arch/arm/mach-cns3xxx/core.c b/arch/arm/mach-cns3xxx/core.c
index f85449a..79e6ead 100644
--- a/arch/arm/mach-cns3xxx/core.c
+++ b/arch/arm/mach-cns3xxx/core.c
@@ -386,7 +386,7 @@ static void __init cns3xxx_init(void)
 		cns3xxx_pwr_soft_rst(CNS3XXX_PWR_SOFTWARE_RST(SDIO));
 	}
 
-	pm_power_off = cns3xxx_power_off;
+	register_poweroff_handler_simple(cns3xxx_power_off, 128);
 
 	of_platform_populate(NULL, of_default_bus_match_table,
                         cns3xxx_auxdata, NULL);
diff --git a/arch/arm/mach-highbank/highbank.c b/arch/arm/mach-highbank/highbank.c
index 8c35ae4..25d0134 100644
--- a/arch/arm/mach-highbank/highbank.c
+++ b/arch/arm/mach-highbank/highbank.c
@@ -155,7 +155,7 @@ static void __init highbank_init(void)
 	sregs_base = of_iomap(np, 0);
 	WARN_ON(!sregs_base);
 
-	pm_power_off = highbank_power_off;
+	register_poweroff_handler_simple(highbank_power_off, 0);
 	highbank_pm_init();
 
 	bus_register_notifier(&platform_bus_type, &highbank_platform_nb);
diff --git a/arch/arm/mach-imx/mach-mx31moboard.c b/arch/arm/mach-imx/mach-mx31moboard.c
index bb6f8a5..9b3616f 100644
--- a/arch/arm/mach-imx/mach-mx31moboard.c
+++ b/arch/arm/mach-imx/mach-mx31moboard.c
@@ -559,7 +559,7 @@ static void __init mx31moboard_init(void)
 
 	imx_add_platform_device("imx_mc13783", 0, NULL, 0, NULL, 0);
 
-	pm_power_off = mx31moboard_poweroff;
+	register_poweroff_handler_simple(mx31moboard_poweroff, 128);
 
 	switch (mx31moboard_baseboard) {
 	case MX31NOBOARD:
diff --git a/arch/arm/mach-iop32x/em7210.c b/arch/arm/mach-iop32x/em7210.c
index 77e1ff0..beeeb0c2 100644
--- a/arch/arm/mach-iop32x/em7210.c
+++ b/arch/arm/mach-iop32x/em7210.c
@@ -201,7 +201,7 @@ static int __init em7210_request_gpios(void)
 		return 0;
 	}
 
-	pm_power_off = em7210_power_off;
+	register_poweroff_handler_simple(em7210_power_off, 128);
 
 	return 0;
 }
diff --git a/arch/arm/mach-iop32x/glantank.c b/arch/arm/mach-iop32x/glantank.c
index 547b234..050a8e6 100644
--- a/arch/arm/mach-iop32x/glantank.c
+++ b/arch/arm/mach-iop32x/glantank.c
@@ -199,7 +199,7 @@ static void __init glantank_init_machine(void)
 	i2c_register_board_info(0, glantank_i2c_devices,
 		ARRAY_SIZE(glantank_i2c_devices));
 
-	pm_power_off = glantank_power_off;
+	register_poweroff_handler_simple(glantank_power_off, 128);
 }
 
 MACHINE_START(GLANTANK, "GLAN Tank")
diff --git a/arch/arm/mach-iop32x/iq31244.c b/arch/arm/mach-iop32x/iq31244.c
index 0e1392b..4e9b972 100644
--- a/arch/arm/mach-iop32x/iq31244.c
+++ b/arch/arm/mach-iop32x/iq31244.c
@@ -293,7 +293,7 @@ static void __init iq31244_init_machine(void)
 	platform_device_register(&iop3xx_dma_1_channel);
 
 	if (is_ep80219())
-		pm_power_off = ep80219_power_off;
+		register_poweroff_handler_simple(ep80219_power_off, 128);
 
 	if (!is_80219())
 		platform_device_register(&iop3xx_aau_channel);
diff --git a/arch/arm/mach-iop32x/n2100.c b/arch/arm/mach-iop32x/n2100.c
index c1cd80e..171d496 100644
--- a/arch/arm/mach-iop32x/n2100.c
+++ b/arch/arm/mach-iop32x/n2100.c
@@ -356,7 +356,7 @@ static void __init n2100_init_machine(void)
 	i2c_register_board_info(0, n2100_i2c_devices,
 		ARRAY_SIZE(n2100_i2c_devices));
 
-	pm_power_off = n2100_power_off;
+	register_poweroff_handler_simple(n2100_power_off, 128);
 }
 
 MACHINE_START(N2100, "Thecus N2100")
diff --git a/arch/arm/mach-ixp4xx/dsmg600-setup.c b/arch/arm/mach-ixp4xx/dsmg600-setup.c
index 43ee06d..6fb5072 100644
--- a/arch/arm/mach-ixp4xx/dsmg600-setup.c
+++ b/arch/arm/mach-ixp4xx/dsmg600-setup.c
@@ -281,7 +281,7 @@ static void __init dsmg600_init(void)
 
 	platform_add_devices(dsmg600_devices, ARRAY_SIZE(dsmg600_devices));
 
-	pm_power_off = dsmg600_power_off;
+	register_poweroff_handler_simple(dsmg600_power_off, 128);
 }
 
 MACHINE_START(DSMG600, "D-Link DSM-G600 RevA")
diff --git a/arch/arm/mach-ixp4xx/nas100d-setup.c b/arch/arm/mach-ixp4xx/nas100d-setup.c
index 4e0f762..bd9a8d6 100644
--- a/arch/arm/mach-ixp4xx/nas100d-setup.c
+++ b/arch/arm/mach-ixp4xx/nas100d-setup.c
@@ -292,7 +292,7 @@ static void __init nas100d_init(void)
 
 	platform_add_devices(nas100d_devices, ARRAY_SIZE(nas100d_devices));
 
-	pm_power_off = nas100d_power_off;
+	register_poweroff_handler_simple(nas100d_power_off, 128);
 
 	if (request_irq(gpio_to_irq(NAS100D_RB_GPIO), &nas100d_reset_handler,
 		IRQF_TRIGGER_LOW, "NAS100D reset button", NULL) < 0) {
diff --git a/arch/arm/mach-ixp4xx/nslu2-setup.c b/arch/arm/mach-ixp4xx/nslu2-setup.c
index 88c025f..c4c5475 100644
--- a/arch/arm/mach-ixp4xx/nslu2-setup.c
+++ b/arch/arm/mach-ixp4xx/nslu2-setup.c
@@ -262,7 +262,7 @@ static void __init nslu2_init(void)
 
 	platform_add_devices(nslu2_devices, ARRAY_SIZE(nslu2_devices));
 
-	pm_power_off = nslu2_power_off;
+	register_poweroff_handler_simple(nslu2_power_off, 128);
 
 	if (request_irq(gpio_to_irq(NSLU2_RB_GPIO), &nslu2_reset_handler,
 		IRQF_TRIGGER_LOW, "NSLU2 reset button", NULL) < 0) {
diff --git a/arch/arm/mach-omap2/board-omap3touchbook.c b/arch/arm/mach-omap2/board-omap3touchbook.c
index 70b904c..0c0a0e2 100644
--- a/arch/arm/mach-omap2/board-omap3touchbook.c
+++ b/arch/arm/mach-omap2/board-omap3touchbook.c
@@ -344,7 +344,7 @@ static void __init omap3_touchbook_init(void)
 {
 	omap3_mux_init(board_mux, OMAP_PACKAGE_CBB);
 
-	pm_power_off = omap3_touchbook_poweroff;
+	register_poweroff_handler_simple(omap3_touchbook_poweroff, 128);
 
 	if (system_rev >= 0x20 && system_rev <= 0x34301000) {
 		omap_mux_init_gpio(23, OMAP_PIN_INPUT);
diff --git a/arch/arm/mach-orion5x/board-mss2.c b/arch/arm/mach-orion5x/board-mss2.c
index 66f9c3b..3840d66 100644
--- a/arch/arm/mach-orion5x/board-mss2.c
+++ b/arch/arm/mach-orion5x/board-mss2.c
@@ -86,5 +86,5 @@ static void mss2_power_off(void)
 void __init mss2_init(void)
 {
 	/* register mss2 specific power-off method */
-	pm_power_off = mss2_power_off;
+	register_poweroff_handler_simple(mss2_power_off, 0);
 }
diff --git a/arch/arm/mach-orion5x/dns323-setup.c b/arch/arm/mach-orion5x/dns323-setup.c
index 56edeab..353ca3d 100644
--- a/arch/arm/mach-orion5x/dns323-setup.c
+++ b/arch/arm/mach-orion5x/dns323-setup.c
@@ -669,7 +669,7 @@ static void __init dns323_init(void)
 		if (gpio_request(DNS323_GPIO_POWER_OFF, "POWEROFF") != 0 ||
 		    gpio_direction_output(DNS323_GPIO_POWER_OFF, 0) != 0)
 			pr_err("DNS-323: failed to setup power-off GPIO\n");
-		pm_power_off = dns323a_power_off;
+		register_poweroff_handler_simple(dns323a_power_off, 128);
 		break;
 	case DNS323_REV_B1:
 		/* 5182 built-in SATA init */
@@ -686,7 +686,7 @@ static void __init dns323_init(void)
 		if (gpio_request(DNS323_GPIO_POWER_OFF, "POWEROFF") != 0 ||
 		    gpio_direction_output(DNS323_GPIO_POWER_OFF, 0) != 0)
 			pr_err("DNS-323: failed to setup power-off GPIO\n");
-		pm_power_off = dns323b_power_off;
+		register_poweroff_handler_simple(dns323b_power_off, 128);
 		break;
 	case DNS323_REV_C1:
 		/* 5182 built-in SATA init */
@@ -696,7 +696,7 @@ static void __init dns323_init(void)
 		if (gpio_request(DNS323C_GPIO_POWER_OFF, "POWEROFF") != 0 ||
 		    gpio_direction_output(DNS323C_GPIO_POWER_OFF, 0) != 0)
 			pr_err("DNS-323: failed to setup power-off GPIO\n");
-		pm_power_off = dns323c_power_off;
+		register_poweroff_handler_simple(dns323c_power_off, 128);
 
 		/* Now, -this- should theorically be done by the sata_mv driver
 		 * once I figure out what's going on there. Maybe the behaviour
diff --git a/arch/arm/mach-orion5x/kurobox_pro-setup.c b/arch/arm/mach-orion5x/kurobox_pro-setup.c
index fe6a48a..c4101f1 100644
--- a/arch/arm/mach-orion5x/kurobox_pro-setup.c
+++ b/arch/arm/mach-orion5x/kurobox_pro-setup.c
@@ -376,7 +376,7 @@ static void __init kurobox_pro_init(void)
 	i2c_register_board_info(0, &kurobox_pro_i2c_rtc, 1);
 
 	/* register Kurobox Pro specific power-off method */
-	pm_power_off = kurobox_pro_power_off;
+	register_poweroff_handler_simple(kurobox_pro_power_off, 128);
 }
 
 #ifdef CONFIG_MACH_KUROBOX_PRO
diff --git a/arch/arm/mach-orion5x/ls-chl-setup.c b/arch/arm/mach-orion5x/ls-chl-setup.c
index 028ea03..005bb04 100644
--- a/arch/arm/mach-orion5x/ls-chl-setup.c
+++ b/arch/arm/mach-orion5x/ls-chl-setup.c
@@ -312,7 +312,7 @@ static void __init lschl_init(void)
 	gpio_set_value(LSCHL_GPIO_USB_POWER, 1);
 
 	/* register power-off method */
-	pm_power_off = lschl_power_off;
+	register_poweroff_handler_simple(lschl_power_off, 0);
 
 	pr_info("%s: finished\n", __func__);
 }
diff --git a/arch/arm/mach-orion5x/ls_hgl-setup.c b/arch/arm/mach-orion5x/ls_hgl-setup.c
index 32b7129..37c29a0 100644
--- a/arch/arm/mach-orion5x/ls_hgl-setup.c
+++ b/arch/arm/mach-orion5x/ls_hgl-setup.c
@@ -259,7 +259,7 @@ static void __init ls_hgl_init(void)
 	gpio_set_value(LS_HGL_GPIO_USB_POWER, 1);
 
 	/* register power-off method */
-	pm_power_off = ls_hgl_power_off;
+	register_poweroff_handler_simple(ls_hgl_power_off, 0);
 
 	pr_info("%s: finished\n", __func__);
 }
diff --git a/arch/arm/mach-orion5x/lsmini-setup.c b/arch/arm/mach-orion5x/lsmini-setup.c
index a6493e7..ffec72f 100644
--- a/arch/arm/mach-orion5x/lsmini-setup.c
+++ b/arch/arm/mach-orion5x/lsmini-setup.c
@@ -260,7 +260,7 @@ static void __init lsmini_init(void)
 	gpio_set_value(LSMINI_GPIO_USB_POWER, 1);
 
 	/* register power-off method */
-	pm_power_off = lsmini_power_off;
+	register_poweroff_handler_simple(lsmini_power_off, 0);
 
 	pr_info("%s: finished\n", __func__);
 }
diff --git a/arch/arm/mach-orion5x/mv2120-setup.c b/arch/arm/mach-orion5x/mv2120-setup.c
index e032f01..dadc2b9 100644
--- a/arch/arm/mach-orion5x/mv2120-setup.c
+++ b/arch/arm/mach-orion5x/mv2120-setup.c
@@ -225,7 +225,7 @@ static void __init mv2120_init(void)
 	if (gpio_request(MV2120_GPIO_POWER_OFF, "POWEROFF") != 0 ||
 	    gpio_direction_output(MV2120_GPIO_POWER_OFF, 1) != 0)
 		pr_err("mv2120: failed to setup power-off GPIO\n");
-	pm_power_off = mv2120_power_off;
+	register_poweroff_handler_simple(mv2120_power_off, 128);
 }
 
 /* Warning: HP uses a wrong mach-type (=526) in their bootloader */
diff --git a/arch/arm/mach-orion5x/net2big-setup.c b/arch/arm/mach-orion5x/net2big-setup.c
index ba73dc7..3a73dce 100644
--- a/arch/arm/mach-orion5x/net2big-setup.c
+++ b/arch/arm/mach-orion5x/net2big-setup.c
@@ -413,7 +413,7 @@ static void __init net2big_init(void)
 
 	if (gpio_request(NET2BIG_GPIO_POWER_OFF, "power-off") == 0 &&
 	    gpio_direction_output(NET2BIG_GPIO_POWER_OFF, 0) == 0)
-		pm_power_off = net2big_power_off;
+		register_poweroff_handler_simple(net2big_power_off, 128);
 	else
 		pr_err("net2big: failed to configure power-off GPIO\n");
 
diff --git a/arch/arm/mach-orion5x/terastation_pro2-setup.c b/arch/arm/mach-orion5x/terastation_pro2-setup.c
index 6208d12..2a234cb 100644
--- a/arch/arm/mach-orion5x/terastation_pro2-setup.c
+++ b/arch/arm/mach-orion5x/terastation_pro2-setup.c
@@ -353,7 +353,7 @@ static void __init tsp2_init(void)
 	i2c_register_board_info(0, &tsp2_i2c_rtc, 1);
 
 	/* register Terastation Pro II specific power-off method */
-	pm_power_off = tsp2_power_off;
+	register_poweroff_handler_simple(tsp2_power_off, 128);
 }
 
 MACHINE_START(TERASTATION_PRO2, "Buffalo Terastation Pro II/Live")
diff --git a/arch/arm/mach-orion5x/ts209-setup.c b/arch/arm/mach-orion5x/ts209-setup.c
index 9136797..50bdfbc 100644
--- a/arch/arm/mach-orion5x/ts209-setup.c
+++ b/arch/arm/mach-orion5x/ts209-setup.c
@@ -318,7 +318,7 @@ static void __init qnap_ts209_init(void)
 	i2c_register_board_info(0, &qnap_ts209_i2c_rtc, 1);
 
 	/* register tsx09 specific power-off method */
-	pm_power_off = qnap_tsx09_power_off;
+	register_poweroff_handler_simple(qnap_tsx09_power_off, 128);
 }
 
 MACHINE_START(TS209, "QNAP TS-109/TS-209")
diff --git a/arch/arm/mach-orion5x/ts409-setup.c b/arch/arm/mach-orion5x/ts409-setup.c
index 5c079d31..06a7cc0 100644
--- a/arch/arm/mach-orion5x/ts409-setup.c
+++ b/arch/arm/mach-orion5x/ts409-setup.c
@@ -307,7 +307,7 @@ static void __init qnap_ts409_init(void)
 	platform_device_register(&ts409_leds);
 
 	/* register tsx09 specific power-off method */
-	pm_power_off = qnap_tsx09_power_off;
+	register_poweroff_handler_simple(qnap_tsx09_power_off, 128);
 }
 
 MACHINE_START(TS409, "QNAP TS-409")
diff --git a/arch/arm/mach-pxa/corgi.c b/arch/arm/mach-pxa/corgi.c
index 06022b2..a93bac0 100644
--- a/arch/arm/mach-pxa/corgi.c
+++ b/arch/arm/mach-pxa/corgi.c
@@ -718,7 +718,7 @@ static void corgi_restart(enum reboot_mode mode, const char *cmd)
 
 static void __init corgi_init(void)
 {
-	pm_power_off = corgi_poweroff;
+	register_poweroff_handler_simple(corgi_poweroff, 0);
 
 	/* Stop 3.6MHz and drive HIGH to PCMCIA and CS */
 	PCFR |= PCFR_OPDE;
diff --git a/arch/arm/mach-pxa/mioa701.c b/arch/arm/mach-pxa/mioa701.c
index 29997bd..c4345a4 100644
--- a/arch/arm/mach-pxa/mioa701.c
+++ b/arch/arm/mach-pxa/mioa701.c
@@ -750,7 +750,7 @@ static void __init mioa701_machine_init(void)
 	pxa_set_keypad_info(&mioa701_keypad_info);
 	pxa_set_udc_info(&mioa701_udc_info);
 	pxa_set_ac97_info(&mioa701_ac97_info);
-	pm_power_off = mioa701_poweroff;
+	register_poweroff_handler_simple(mioa701_poweroff, 0);
 	platform_add_devices(devices, ARRAY_SIZE(devices));
 	gsm_init();
 
diff --git a/arch/arm/mach-pxa/poodle.c b/arch/arm/mach-pxa/poodle.c
index 1319916..c9536ed 100644
--- a/arch/arm/mach-pxa/poodle.c
+++ b/arch/arm/mach-pxa/poodle.c
@@ -432,7 +432,7 @@ static void __init poodle_init(void)
 {
 	int ret = 0;
 
-	pm_power_off = poodle_poweroff;
+	register_poweroff_handler_simple(poodle_poweroff, 0);
 
 	PCFR |= PCFR_OPDE;
 
diff --git a/arch/arm/mach-pxa/spitz.c b/arch/arm/mach-pxa/spitz.c
index 840c3a4..09f0de8 100644
--- a/arch/arm/mach-pxa/spitz.c
+++ b/arch/arm/mach-pxa/spitz.c
@@ -944,7 +944,7 @@ static void spitz_restart(enum reboot_mode mode, const char *cmd)
 static void __init spitz_init(void)
 {
 	init_gpio_reset(SPITZ_GPIO_ON_RESET, 1, 0);
-	pm_power_off = spitz_poweroff;
+	register_poweroff_handler_simple(spitz_poweroff, 0);
 
 	PMCR = 0x00;
 
diff --git a/arch/arm/mach-pxa/tosa.c b/arch/arm/mach-pxa/tosa.c
index c158a6e..3a4af1d 100644
--- a/arch/arm/mach-pxa/tosa.c
+++ b/arch/arm/mach-pxa/tosa.c
@@ -940,7 +940,7 @@ static void __init tosa_init(void)
 
 	init_gpio_reset(TOSA_GPIO_ON_RESET, 0, 0);
 
-	pm_power_off = tosa_poweroff;
+	register_poweroff_handler_simple(tosa_poweroff, 0);
 
 	PCFR |= PCFR_OPDE;
 
diff --git a/arch/arm/mach-pxa/viper.c b/arch/arm/mach-pxa/viper.c
index de3b080..679c8ea 100644
--- a/arch/arm/mach-pxa/viper.c
+++ b/arch/arm/mach-pxa/viper.c
@@ -919,7 +919,7 @@ static void __init viper_init(void)
 {
 	u8 version;
 
-	pm_power_off = viper_power_off;
+	register_poweroff_handler_simple(viper_power_off, 128);
 
 	pxa2xx_mfp_config(ARRAY_AND_SIZE(viper_pin_config));
 
diff --git a/arch/arm/mach-pxa/z2.c b/arch/arm/mach-pxa/z2.c
index e1a121b..e0195ac 100644
--- a/arch/arm/mach-pxa/z2.c
+++ b/arch/arm/mach-pxa/z2.c
@@ -693,8 +693,6 @@ static void z2_power_off(void)
 	pxa27x_set_pwrmode(PWRMODE_DEEPSLEEP);
 	pxa27x_cpu_pm_enter(PM_SUSPEND_MEM);
 }
-#else
-#define z2_power_off   NULL
 #endif
 
 /******************************************************************************
@@ -719,7 +717,9 @@ static void __init z2_init(void)
 	z2_keys_init();
 	z2_pmic_init();
 
-	pm_power_off = z2_power_off;
+#ifdef CONFIG_PM
+	register_poweroff_handler_simple(z2_power_off, 0);
+#endif
 }
 
 MACHINE_START(ZIPIT2, "Zipit Z2")
diff --git a/arch/arm/mach-pxa/zeus.c b/arch/arm/mach-pxa/zeus.c
index 205f9bf..6118fd5 100644
--- a/arch/arm/mach-pxa/zeus.c
+++ b/arch/arm/mach-pxa/zeus.c
@@ -690,8 +690,6 @@ static void zeus_power_off(void)
 	local_irq_disable();
 	cpu_suspend(PWRMODE_DEEPSLEEP, pxa27x_finish_suspend);
 }
-#else
-#define zeus_power_off   NULL
 #endif
 
 #ifdef CONFIG_APM_EMULATION
@@ -847,7 +845,9 @@ static void __init zeus_init(void)
 	__raw_writel(msc0, MSC0);
 	__raw_writel(msc1, MSC1);
 
-	pm_power_off = zeus_power_off;
+#ifdef CONFIG_PM
+	register_poweroff_handler_simple(zeus_power_off, 0);
+#endif
 	zeus_setup_apm();
 
 	pxa2xx_mfp_config(ARRAY_AND_SIZE(zeus_pin_config));
diff --git a/arch/arm/mach-s3c24xx/mach-gta02.c b/arch/arm/mach-s3c24xx/mach-gta02.c
index fc3a08d..ca78150 100644
--- a/arch/arm/mach-s3c24xx/mach-gta02.c
+++ b/arch/arm/mach-s3c24xx/mach-gta02.c
@@ -579,7 +579,7 @@ static void __init gta02_machine_init(void)
 	i2c_register_board_info(0, gta02_i2c_devs, ARRAY_SIZE(gta02_i2c_devs));
 
 	platform_add_devices(gta02_devices, ARRAY_SIZE(gta02_devices));
-	pm_power_off = gta02_poweroff;
+	register_poweroff_handler_simple(gta02_poweroff, 128);
 
 	regulator_has_full_constraints();
 }
diff --git a/arch/arm/mach-s3c24xx/mach-jive.c b/arch/arm/mach-s3c24xx/mach-jive.c
index 7804d3c..5a828a3 100644
--- a/arch/arm/mach-s3c24xx/mach-jive.c
+++ b/arch/arm/mach-s3c24xx/mach-jive.c
@@ -657,7 +657,7 @@ static void __init jive_machine_init(void)
 	s3c_i2c0_set_platdata(&jive_i2c_cfg);
 	i2c_register_board_info(0, jive_i2c_devs, ARRAY_SIZE(jive_i2c_devs));
 
-	pm_power_off = jive_power_off;
+	register_poweroff_handler_simple(jive_power_off, 128);
 
 	platform_add_devices(jive_devices, ARRAY_SIZE(jive_devices));
 }
diff --git a/arch/arm/mach-s3c24xx/mach-vr1000.c b/arch/arm/mach-s3c24xx/mach-vr1000.c
index f88c584..40d7655 100644
--- a/arch/arm/mach-s3c24xx/mach-vr1000.c
+++ b/arch/arm/mach-s3c24xx/mach-vr1000.c
@@ -306,7 +306,7 @@ static void vr1000_power_off(void)
 
 static void __init vr1000_map_io(void)
 {
-	pm_power_off = vr1000_power_off;
+	register_poweroff_handler_simple(vr1000_power_off, 128);
 
 	s3c24xx_init_io(vr1000_iodesc, ARRAY_SIZE(vr1000_iodesc));
 	s3c24xx_init_uarts(vr1000_uartcfgs, ARRAY_SIZE(vr1000_uartcfgs));
diff --git a/arch/arm/mach-s3c64xx/mach-smartq.c b/arch/arm/mach-s3c64xx/mach-smartq.c
index b3d1353..61f0893 100644
--- a/arch/arm/mach-s3c64xx/mach-smartq.c
+++ b/arch/arm/mach-s3c64xx/mach-smartq.c
@@ -291,7 +291,7 @@ static int __init smartq_power_off_init(void)
 	/* leave power on */
 	gpio_direction_output(S3C64XX_GPK(15), 0);
 
-	pm_power_off = smartq_power_off;
+	register_poweroff_handler_simple(smartq_power_off, 128);
 
 	return ret;
 }
diff --git a/arch/arm/mach-sa1100/generic.c b/arch/arm/mach-sa1100/generic.c
index d4ea142..6b839cf 100644
--- a/arch/arm/mach-sa1100/generic.c
+++ b/arch/arm/mach-sa1100/generic.c
@@ -311,7 +311,7 @@ static struct platform_device *sa11x0_devices[] __initdata = {
 
 static int __init sa1100_init(void)
 {
-	pm_power_off = sa1100_power_off;
+	register_poweroff_handler_simple(sa1100_power_off, 0);
 	return platform_add_devices(sa11x0_devices, ARRAY_SIZE(sa11x0_devices));
 }
 
diff --git a/arch/arm/mach-sa1100/simpad.c b/arch/arm/mach-sa1100/simpad.c
index 41e476e..a65ca58 100644
--- a/arch/arm/mach-sa1100/simpad.c
+++ b/arch/arm/mach-sa1100/simpad.c
@@ -373,7 +373,7 @@ static int __init simpad_init(void)
 	if (ret)
 		printk(KERN_WARNING "simpad: Unable to register cs3 GPIO device");
 
-	pm_power_off = simpad_power_off;
+	register_poweroff_handler_simple(simpad_power_off, 0);
 
 	sa11x0_ppc_configure_mcp();
 	sa11x0_register_mtd(&simpad_flash_data, simpad_flash_resources,
diff --git a/arch/arm/mach-u300/regulator.c b/arch/arm/mach-u300/regulator.c
index 0493a84..c98eb6e 100644
--- a/arch/arm/mach-u300/regulator.c
+++ b/arch/arm/mach-u300/regulator.c
@@ -98,7 +98,7 @@ static int __init __u300_init_boardpower(struct platform_device *pdev)
 			   U300_SYSCON_PMCR_DCON_ENABLE, 0);
 
 	/* Register globally exported PM poweroff hook */
-	pm_power_off = u300_pm_poweroff;
+	register_poweroff_handler_simple(u300_pm_poweroff, 128);
 
 	return 0;
 }
diff --git a/arch/arm/mach-vt8500/vt8500.c b/arch/arm/mach-vt8500/vt8500.c
index 2da7be3..515946b 100644
--- a/arch/arm/mach-vt8500/vt8500.c
+++ b/arch/arm/mach-vt8500/vt8500.c
@@ -155,7 +155,7 @@ static void __init vt8500_init(void)
 			pr_err("%s:ioremap(power_off) failed\n", __func__);
 	}
 	if (pmc_base)
-		pm_power_off = &vt8500_power_off;
+		register_poweroff_handler_simple(vt8500_power_off, 0);
 	else
 		pr_err("%s: PMC Hibernation register could not be remapped, not enabling power off!\n", __func__);
 
diff --git a/arch/arm/xen/enlighten.c b/arch/arm/xen/enlighten.c
index 0e15f01..0da639b 100644
--- a/arch/arm/xen/enlighten.c
+++ b/arch/arm/xen/enlighten.c
@@ -336,7 +336,7 @@ static int __init xen_pm_init(void)
 	if (!xen_domain())
 		return -ENODEV;
 
-	pm_power_off = xen_power_off;
+	register_poweroff_handler_simple(xen_power_off, 128);
 	arm_pm_restart = xen_restart;
 
 	return 0;
-- 
1.9.1

^ permalink raw reply related

* [PATCH 34/44] ia64: Register with kernel poweroff handler
From: Guenter Roeck @ 2014-10-07  5:28 UTC (permalink / raw)
  To: linux-kernel
  Cc: linux-m32r-ja, linux-mips, linux-efi, linux-ia64, linux-xtensa,
	devel, linux-s390, lguest, linux-c6x-dev, linux-hexagon, linux-sh,
	linux-acpi, xen-devel, Guenter Roeck, devicetree,
	user-mode-linux-devel, linux-pm, adi-buildroot-devel, linux-m68k,
	linux-am33-list, linux-tegra, openipmi-developer, linux-metag,
	linux-arm-kernel, Tony Luck, linux-parisc, linux-cris-kernel,
	Fenghua Yu, linux-alpha, linuxppc-dev
In-Reply-To: <1412659726-29957-1-git-send-email-linux@roeck-us.net>

Register with kernel poweroff handler instead of setting pm_power_off
directly. Register with lower priority of 64 to reflect that the call
is expected to be replaced at some point.

Cc: Tony Luck <tony.luck@intel.com>
Cc: Fenghua Yu <fenghua.yu@intel.com>
Signed-off-by: Guenter Roeck <linux@roeck-us.net>
---
 arch/ia64/sn/kernel/setup.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/arch/ia64/sn/kernel/setup.c b/arch/ia64/sn/kernel/setup.c
index 36182c8..6c83425 100644
--- a/arch/ia64/sn/kernel/setup.c
+++ b/arch/ia64/sn/kernel/setup.c
@@ -488,12 +488,12 @@ void __init sn_setup(char **cmdline_p)
 	sn_timer_init();
 
 	/*
-	 * set pm_power_off to a SAL call to allow
+	 * set poweroff handler to a SAL call to allow
 	 * sn machines to power off. The SAL call can be replaced
 	 * by an ACPI interface call when ACPI is fully implemented
 	 * for sn.
 	 */
-	pm_power_off = ia64_sn_power_down;
+	register_poweroff_handler_simple(ia64_sn_power_down, 64);
 	current->thread.flags |= IA64_THREAD_MIGRATION;
 }
 
-- 
1.9.1

^ permalink raw reply related

* [PATCH 35/44] m68k: Register with kernel poweroff handler
From: Guenter Roeck @ 2014-10-07  5:28 UTC (permalink / raw)
  To: linux-kernel
  Cc: linux-m32r-ja, linux-mips, linux-efi, linux-ia64, linux-xtensa,
	devel, linux-s390, lguest, linux-c6x-dev, linux-hexagon, linux-sh,
	linux-acpi, Geert Uytterhoeven, xen-devel, Guenter Roeck,
	devicetree, user-mode-linux-devel, linux-pm, adi-buildroot-devel,
	linux-m68k, linux-am33-list, linux-tegra, openipmi-developer,
	linux-metag, linux-arm-kernel, linux-parisc, linux-cris-kernel,
	linux-alpha, linuxppc-dev, Joshua Thompson
In-Reply-To: <1412659726-29957-1-git-send-email-linux@roeck-us.net>

Register with kernel poweroff handler instead of setting pm_power_off
directly.

Cc: Geert Uytterhoeven <geert@linux-m68k.org>
Cc: Joshua Thompson <funaho@jurai.org>
Signed-off-by: Guenter Roeck <linux@roeck-us.net>
---
 arch/m68k/emu/natfeat.c | 2 +-
 arch/m68k/mac/config.c  | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/arch/m68k/emu/natfeat.c b/arch/m68k/emu/natfeat.c
index 91e2ae7..c4d5bd8 100644
--- a/arch/m68k/emu/natfeat.c
+++ b/arch/m68k/emu/natfeat.c
@@ -91,5 +91,5 @@ void __init nf_init(void)
 	pr_info("NatFeats found (%s, %lu.%lu)\n", buf, version >> 16,
 		version & 0xffff);
 
-	pm_power_off = nf_poweroff;
+	register_poweroff_handler_simple(nf_poweroff, 128);
 }
diff --git a/arch/m68k/mac/config.c b/arch/m68k/mac/config.c
index 677913ff..5d8e2e6 100644
--- a/arch/m68k/mac/config.c
+++ b/arch/m68k/mac/config.c
@@ -160,7 +160,7 @@ void __init config_mac(void)
 	mach_set_clock_mmss = mac_set_clock_mmss;
 	mach_reset = mac_reset;
 	mach_halt = mac_poweroff;
-	pm_power_off = mac_poweroff;
+	register_poweroff_handler_simple(mac_poweroff, 128);
 	mach_max_dma_address = 0xffffffff;
 #if defined(CONFIG_INPUT_M68K_BEEP) || defined(CONFIG_INPUT_M68K_BEEP_MODULE)
 	mach_beep = mac_mksound;
-- 
1.9.1

^ permalink raw reply related

* [PATCH 37/44] sh: Register with kernel poweroff handler
From: Guenter Roeck @ 2014-10-07  5:28 UTC (permalink / raw)
  To: linux-kernel
  Cc: linux-m32r-ja, linux-mips, linux-efi, linux-ia64, linux-xtensa,
	devel, linux-s390, lguest, linux-c6x-dev, linux-hexagon, linux-sh,
	linux-acpi, xen-devel, Guenter Roeck, devicetree,
	user-mode-linux-devel, linux-pm, adi-buildroot-devel, linux-m68k,
	linux-am33-list, linux-tegra, openipmi-developer, linux-metag,
	linux-arm-kernel, linux-parisc, linux-cris-kernel, linux-alpha,
	linuxppc-dev
In-Reply-To: <1412659726-29957-1-git-send-email-linux@roeck-us.net>

Register with kernel poweroff handler instead of setting pm_power_off
directly.

Signed-off-by: Guenter Roeck <linux@roeck-us.net>
---
 arch/sh/boards/board-sh7785lcr.c       | 2 +-
 arch/sh/boards/board-urquell.c         | 2 +-
 arch/sh/boards/mach-highlander/setup.c | 2 +-
 arch/sh/boards/mach-landisk/setup.c    | 2 +-
 arch/sh/boards/mach-r2d/setup.c        | 2 +-
 arch/sh/boards/mach-sdk7786/setup.c    | 2 +-
 6 files changed, 6 insertions(+), 6 deletions(-)

diff --git a/arch/sh/boards/board-sh7785lcr.c b/arch/sh/boards/board-sh7785lcr.c
index 2c4771e..c092402 100644
--- a/arch/sh/boards/board-sh7785lcr.c
+++ b/arch/sh/boards/board-sh7785lcr.c
@@ -332,7 +332,7 @@ static void __init sh7785lcr_setup(char **cmdline_p)
 
 	printk(KERN_INFO "Renesas Technology Corp. R0P7785LC0011RL support.\n");
 
-	pm_power_off = sh7785lcr_power_off;
+	register_poweroff_handler_simple(sh7785lcr_power_off, 128);
 
 	/* sm501 DRAM configuration */
 	sm501_reg = ioremap_nocache(SM107_REG_ADDR, SM501_DRAM_CONTROL);
diff --git a/arch/sh/boards/board-urquell.c b/arch/sh/boards/board-urquell.c
index b52abcc..b3fa56f 100644
--- a/arch/sh/boards/board-urquell.c
+++ b/arch/sh/boards/board-urquell.c
@@ -204,7 +204,7 @@ static void __init urquell_setup(char **cmdline_p)
 {
 	printk(KERN_INFO "Renesas Technology Corp. Urquell support.\n");
 
-	pm_power_off = urquell_power_off;
+	register_poweroff_handler_simple(urquell_power_off, 128);
 
 	register_smp_ops(&shx3_smp_ops);
 }
diff --git a/arch/sh/boards/mach-highlander/setup.c b/arch/sh/boards/mach-highlander/setup.c
index 4a52590..998f1a5 100644
--- a/arch/sh/boards/mach-highlander/setup.c
+++ b/arch/sh/boards/mach-highlander/setup.c
@@ -385,7 +385,7 @@ static void __init highlander_setup(char **cmdline_p)
 
 	__raw_writew(__raw_readw(PA_IVDRCTL) | 0x01, PA_IVDRCTL);	/* Si13112 */
 
-	pm_power_off = r7780rp_power_off;
+	register_poweroff_handler_simple(r7780rp_power_off, 128);
 }
 
 static unsigned char irl2irq[HL_NR_IRL];
diff --git a/arch/sh/boards/mach-landisk/setup.c b/arch/sh/boards/mach-landisk/setup.c
index f1147ca..c817d80 100644
--- a/arch/sh/boards/mach-landisk/setup.c
+++ b/arch/sh/boards/mach-landisk/setup.c
@@ -89,7 +89,7 @@ static void __init landisk_setup(char **cmdline_p)
 	__raw_writeb(__raw_readb(PA_LED) | 0x03, PA_LED);
 
 	printk(KERN_INFO "I-O DATA DEVICE, INC. \"LANDISK Series\" support.\n");
-	pm_power_off = landisk_power_off;
+	register_poweroff_handler_simple(landisk_power_off, 128);
 }
 
 /*
diff --git a/arch/sh/boards/mach-r2d/setup.c b/arch/sh/boards/mach-r2d/setup.c
index 4b98a52..a759d39 100644
--- a/arch/sh/boards/mach-r2d/setup.c
+++ b/arch/sh/boards/mach-r2d/setup.c
@@ -279,7 +279,7 @@ static void __init rts7751r2d_setup(char **cmdline_p)
 					(ver >> 4) & 0xf, ver & 0xf);
 
 	__raw_writew(0x0000, PA_OUTPORT);
-	pm_power_off = rts7751r2d_power_off;
+	register_poweroff_handler_simple(rts7751r2d_power_off, 128);
 
 	/* sm501 dram configuration:
 	 * ColSizeX = 11 - External Memory Column Size: 256 words.
diff --git a/arch/sh/boards/mach-sdk7786/setup.c b/arch/sh/boards/mach-sdk7786/setup.c
index c29268b..cb26336 100644
--- a/arch/sh/boards/mach-sdk7786/setup.c
+++ b/arch/sh/boards/mach-sdk7786/setup.c
@@ -252,7 +252,7 @@ static void __init sdk7786_setup(char **cmdline_p)
 	pr_info("\tPCB revision:\t%d\n", fpga_read_reg(PCBRR) & 0xf);
 
 	machine_ops.restart = sdk7786_restart;
-	pm_power_off = sdk7786_power_off;
+	register_poweroff_handler_simple(sdk7786_power_off, 128);
 
 	register_smp_ops(&shx3_smp_ops);
 }
-- 
1.9.1

^ permalink raw reply related

* [PATCH 38/44] x86: lguest: Register with kernel poweroff handler
From: Guenter Roeck @ 2014-10-07  5:28 UTC (permalink / raw)
  To: linux-kernel
  Cc: linux-m32r-ja, linux-mips, linux-efi, linux-ia64, linux-xtensa,
	H. Peter Anvin, Thomas Gleixner, devel, linux-s390, lguest,
	linux-c6x-dev, linux-hexagon, linux-sh, linux-acpi, Ingo Molnar,
	xen-devel, Guenter Roeck, devicetree, user-mode-linux-devel,
	linux-pm, Rusty Russell, adi-buildroot-devel, linux-m68k,
	linux-am33-list, linux-tegra, openipmi-developer, linux-metag,
	linux-arm-kernel, linux-parisc, linux-cris-kernel, linux-alpha,
	linuxppc-dev
In-Reply-To: <1412659726-29957-1-git-send-email-linux@roeck-us.net>

Register with kernel poweroff handler instead of setting pm_power_off
directly.

Cc: Rusty Russell <rusty@rustcorp.com.au>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: Ingo Molnar <mingo@redhat.com>
Cc: H. Peter Anvin <hpa@zytor.com>
Signed-off-by: Guenter Roeck <linux@roeck-us.net>
---
 arch/x86/lguest/boot.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/arch/x86/lguest/boot.c b/arch/x86/lguest/boot.c
index aae9413..083a999 100644
--- a/arch/x86/lguest/boot.c
+++ b/arch/x86/lguest/boot.c
@@ -1441,7 +1441,7 @@ __init void lguest_init(void)
 	 * the Guest routine to power off, and the reboot hook to our restart
 	 * routine.
 	 */
-	pm_power_off = lguest_power_off;
+	register_poweroff_handler_simple(lguest_power_off, 128);
 	machine_ops.restart = lguest_restart;
 
 	/*
-- 
1.9.1

^ permalink raw reply related

* [PATCH 36/44] mips: Register with kernel poweroff handler
From: Guenter Roeck @ 2014-10-07  5:28 UTC (permalink / raw)
  To: linux-kernel
  Cc: linux-m32r-ja, linux-mips, linux-efi, linux-ia64, linux-xtensa,
	Maciej W. Rozycki, devel, linux-s390, lguest, linux-c6x-dev,
	linux-hexagon, linux-sh, linux-acpi, xen-devel, Guenter Roeck,
	devicetree, user-mode-linux-devel, linux-pm, adi-buildroot-devel,
	linux-m68k, linux-am33-list, linux-tegra, openipmi-developer,
	linux-metag, linux-arm-kernel, linux-parisc, linux-cris-kernel,
	Ralf Baechle, linux-alpha, linuxppc-dev
In-Reply-To: <1412659726-29957-1-git-send-email-linux@roeck-us.net>

Register with kernel poweroff handler instead of setting pm_power_off
directly.

If there is an indication that there can be more than one poweroff handler,
use register_poweroff_handler, otherwise use register_poweroff_handler_simple
to register the poweroff handler.

If the poweroff handler only resets or stops the system, select a priority of
0 to indicate that the poweroff handler is one of last resort. If the poweroff
handler powers off the system, select a priority of 128, unless the poweroff
handler installation code suggests that there can be more than one poweroff
handler and the new handler is only installed conditionally. In this case,
select a priority of 64.

Cc: Ralf Baechle <ralf@linux-mips.org>
Cc: Maciej W. Rozycki <macro@linux-mips.org>
Signed-off-by: Guenter Roeck <linux@roeck-us.net>
---
 arch/mips/alchemy/board-gpr.c          |  2 +-
 arch/mips/alchemy/board-mtx1.c         |  2 +-
 arch/mips/alchemy/board-xxs1500.c      |  2 +-
 arch/mips/alchemy/devboards/platform.c | 17 +++++++++++++++--
 arch/mips/ar7/setup.c                  |  2 +-
 arch/mips/ath79/setup.c                |  2 +-
 arch/mips/bcm47xx/setup.c              |  2 +-
 arch/mips/bcm63xx/setup.c              |  2 +-
 arch/mips/cobalt/setup.c               |  2 +-
 arch/mips/dec/setup.c                  |  2 +-
 arch/mips/emma/markeins/setup.c        |  2 +-
 arch/mips/jz4740/reset.c               |  2 +-
 arch/mips/lantiq/falcon/reset.c        |  2 +-
 arch/mips/lantiq/xway/reset.c          |  2 +-
 arch/mips/lasat/reset.c                |  2 +-
 arch/mips/loongson/common/reset.c      |  2 +-
 arch/mips/loongson1/common/reset.c     |  2 +-
 arch/mips/mti-malta/malta-reset.c      |  2 +-
 arch/mips/mti-sead3/sead3-reset.c      |  2 +-
 arch/mips/netlogic/xlp/setup.c         |  2 +-
 arch/mips/netlogic/xlr/setup.c         |  2 +-
 arch/mips/pmcs-msp71xx/msp_setup.c     |  2 +-
 arch/mips/pnx833x/common/setup.c       |  2 +-
 arch/mips/ralink/reset.c               |  2 +-
 arch/mips/rb532/setup.c                |  2 +-
 arch/mips/sgi-ip22/ip22-reset.c        |  2 +-
 arch/mips/sgi-ip27/ip27-reset.c        |  2 +-
 arch/mips/sgi-ip32/ip32-reset.c        |  2 +-
 arch/mips/sibyte/common/cfe.c          |  2 +-
 arch/mips/sni/setup.c                  |  2 +-
 arch/mips/txx9/generic/setup.c         |  2 +-
 arch/mips/vr41xx/common/pmu.c          |  2 +-
 32 files changed, 46 insertions(+), 33 deletions(-)

diff --git a/arch/mips/alchemy/board-gpr.c b/arch/mips/alchemy/board-gpr.c
index acf9a2a..56190a3 100644
--- a/arch/mips/alchemy/board-gpr.c
+++ b/arch/mips/alchemy/board-gpr.c
@@ -89,7 +89,7 @@ void __init board_setup(void)
 {
 	printk(KERN_INFO "Trapeze ITS GPR board\n");
 
-	pm_power_off = gpr_power_off;
+	register_poweroff_handler_simple(gpr_power_off, 0);
 	_machine_halt = gpr_power_off;
 	_machine_restart = gpr_reset;
 
diff --git a/arch/mips/alchemy/board-mtx1.c b/arch/mips/alchemy/board-mtx1.c
index 1e3b102..e2b06b5 100644
--- a/arch/mips/alchemy/board-mtx1.c
+++ b/arch/mips/alchemy/board-mtx1.c
@@ -98,7 +98,7 @@ void __init board_setup(void)
 	alchemy_gpio_direction_output(211, 1);	/* green on */
 	alchemy_gpio_direction_output(212, 0);	/* red off */
 
-	pm_power_off = mtx1_power_off;
+	register_poweroff_handler_simple(mtx1_power_off, 0);
 	_machine_halt = mtx1_power_off;
 	_machine_restart = mtx1_reset;
 
diff --git a/arch/mips/alchemy/board-xxs1500.c b/arch/mips/alchemy/board-xxs1500.c
index 0fc53e0..aaa5f5f 100644
--- a/arch/mips/alchemy/board-xxs1500.c
+++ b/arch/mips/alchemy/board-xxs1500.c
@@ -79,7 +79,7 @@ void __init board_setup(void)
 {
 	u32 pin_func;
 
-	pm_power_off = xxs1500_power_off;
+	register_poweroff_handler_simple(xxs1500_power_off, 0);
 	_machine_halt = xxs1500_power_off;
 	_machine_restart = xxs1500_reset;
 
diff --git a/arch/mips/alchemy/devboards/platform.c b/arch/mips/alchemy/devboards/platform.c
index 8df86eb..1734f72 100644
--- a/arch/mips/alchemy/devboards/platform.c
+++ b/arch/mips/alchemy/devboards/platform.c
@@ -6,6 +6,7 @@
 #include <linux/mtd/mtd.h>
 #include <linux/mtd/map.h>
 #include <linux/mtd/physmap.h>
+#include <linux/notifier.h>
 #include <linux/slab.h>
 #include <linux/platform_device.h>
 #include <linux/pm.h>
@@ -61,10 +62,22 @@ static void db1x_reset(char *c)
 	bcsr_write(BCSR_SYSTEM, 0);
 }
 
+static int db1x_power_off_notify(struct notifier *this,
+				 unsigned long unused1, void *unused2)
+{
+	db1x_power_off();
+	return NOTIFY_DONE;
+}
+
+static struct notifier_block db1x_poweroff_nb = {
+	.notifier_call = db1x_power_off_notify,
+	.priority = 64,
+}
+
 static int __init db1x_late_setup(void)
 {
-	if (!pm_power_off)
-		pm_power_off = db1x_power_off;
+	if (register_poweroff_handler(&db1x_poweroff_nb))
+		pr_err("dbx1: Failed to register poweroff handler\n");
 	if (!_machine_halt)
 		_machine_halt = db1x_power_off;
 	if (!_machine_restart)
diff --git a/arch/mips/ar7/setup.c b/arch/mips/ar7/setup.c
index 820b7a3..464067e 100644
--- a/arch/mips/ar7/setup.c
+++ b/arch/mips/ar7/setup.c
@@ -91,7 +91,7 @@ void __init plat_mem_setup(void)
 
 	_machine_restart = ar7_machine_restart;
 	_machine_halt = ar7_machine_halt;
-	pm_power_off = ar7_machine_power_off;
+	register_poweroff_handler_simple(ar7_machine_power_off, 128);
 
 	io_base = (unsigned long)ioremap(AR7_REGS_BASE, 0x10000);
 	if (!io_base)
diff --git a/arch/mips/ath79/setup.c b/arch/mips/ath79/setup.c
index 64807a4..ce9754e 100644
--- a/arch/mips/ath79/setup.c
+++ b/arch/mips/ath79/setup.c
@@ -203,7 +203,7 @@ void __init plat_mem_setup(void)
 
 	_machine_restart = ath79_restart;
 	_machine_halt = ath79_halt;
-	pm_power_off = ath79_halt;
+	register_poweroff_handler_simple(ath79_halt, 0);
 }
 
 void __init plat_time_init(void)
diff --git a/arch/mips/bcm47xx/setup.c b/arch/mips/bcm47xx/setup.c
index ad439c2..d0841f6 100644
--- a/arch/mips/bcm47xx/setup.c
+++ b/arch/mips/bcm47xx/setup.c
@@ -242,7 +242,7 @@ void __init plat_mem_setup(void)
 
 	_machine_restart = bcm47xx_machine_restart;
 	_machine_halt = bcm47xx_machine_halt;
-	pm_power_off = bcm47xx_machine_halt;
+	register_poweroff_handler_simple(bcm47xx_machine_halt, 0);
 	bcm47xx_board_detect();
 	mips_set_machine_name(bcm47xx_board_get_name());
 }
diff --git a/arch/mips/bcm63xx/setup.c b/arch/mips/bcm63xx/setup.c
index 6660c7d..80a5893 100644
--- a/arch/mips/bcm63xx/setup.c
+++ b/arch/mips/bcm63xx/setup.c
@@ -149,7 +149,7 @@ void __init plat_mem_setup(void)
 
 	_machine_halt = bcm63xx_machine_halt;
 	_machine_restart = __bcm63xx_machine_reboot;
-	pm_power_off = bcm63xx_machine_halt;
+	register_poweroff_handler_simple(bcm63xx_machine_halt, 0);
 
 	set_io_port_base(0);
 	ioport_resource.start = 0;
diff --git a/arch/mips/cobalt/setup.c b/arch/mips/cobalt/setup.c
index 9a8c2fe..146406f 100644
--- a/arch/mips/cobalt/setup.c
+++ b/arch/mips/cobalt/setup.c
@@ -78,7 +78,7 @@ void __init plat_mem_setup(void)
 
 	_machine_restart = cobalt_machine_restart;
 	_machine_halt = cobalt_machine_halt;
-	pm_power_off = cobalt_machine_halt;
+	register_poweroff_handler_simple(cobalt_machine_halt, 0);
 
 	set_io_port_base(CKSEG1ADDR(GT_DEF_PCI0_IO_BASE));
 
diff --git a/arch/mips/dec/setup.c b/arch/mips/dec/setup.c
index 41bbffd..8aea997 100644
--- a/arch/mips/dec/setup.c
+++ b/arch/mips/dec/setup.c
@@ -158,7 +158,7 @@ void __init plat_mem_setup(void)
 
 	_machine_restart = dec_machine_restart;
 	_machine_halt = dec_machine_halt;
-	pm_power_off = dec_machine_power_off;
+	register_poweroff_handler_simple(dec_machine_power_off, 128);
 
 	ioport_resource.start = ~0UL;
 	ioport_resource.end = 0UL;
diff --git a/arch/mips/emma/markeins/setup.c b/arch/mips/emma/markeins/setup.c
index 9100122..e2ec2e5 100644
--- a/arch/mips/emma/markeins/setup.c
+++ b/arch/mips/emma/markeins/setup.c
@@ -103,7 +103,7 @@ void __init plat_mem_setup(void)
 
 	_machine_restart = markeins_machine_restart;
 	_machine_halt = markeins_machine_halt;
-	pm_power_off = markeins_machine_power_off;
+	register_poweroff_handler_simple(markeins_machine_power_off, 0);
 
 	/* setup resource limits */
 	ioport_resource.start = EMMA2RH_PCI_IO_BASE;
diff --git a/arch/mips/jz4740/reset.c b/arch/mips/jz4740/reset.c
index b6c6343..3659e62 100644
--- a/arch/mips/jz4740/reset.c
+++ b/arch/mips/jz4740/reset.c
@@ -114,5 +114,5 @@ void jz4740_reset_init(void)
 {
 	_machine_restart = jz4740_restart;
 	_machine_halt = jz4740_halt;
-	pm_power_off = jz4740_power_off;
+	register_poweroff_handler_simple(jz4740_power_off, 128);
 }
diff --git a/arch/mips/lantiq/falcon/reset.c b/arch/mips/lantiq/falcon/reset.c
index 5682482..efd4ee2 100644
--- a/arch/mips/lantiq/falcon/reset.c
+++ b/arch/mips/lantiq/falcon/reset.c
@@ -83,7 +83,7 @@ static int __init mips_reboot_setup(void)
 {
 	_machine_restart = machine_restart;
 	_machine_halt = machine_halt;
-	pm_power_off = machine_power_off;
+	register_poweroff_handler_simple(machine_power_off, 0);
 	return 0;
 }
 
diff --git a/arch/mips/lantiq/xway/reset.c b/arch/mips/lantiq/xway/reset.c
index 1fa0f17..b698032 100644
--- a/arch/mips/lantiq/xway/reset.c
+++ b/arch/mips/lantiq/xway/reset.c
@@ -157,7 +157,7 @@ static int __init mips_reboot_setup(void)
 
 	_machine_restart = ltq_machine_restart;
 	_machine_halt = ltq_machine_halt;
-	pm_power_off = ltq_machine_power_off;
+	register_poweroff_handler_simple(ltq_machine_power_off, 0);
 
 	return 0;
 }
diff --git a/arch/mips/lasat/reset.c b/arch/mips/lasat/reset.c
index e21f0b9..9a07a88 100644
--- a/arch/mips/lasat/reset.c
+++ b/arch/mips/lasat/reset.c
@@ -56,5 +56,5 @@ void lasat_reboot_setup(void)
 {
 	_machine_restart = lasat_machine_restart;
 	_machine_halt = lasat_machine_halt;
-	pm_power_off = lasat_machine_halt;
+	register_poweroff_handler_simple(lasat_machine_halt, 0);
 }
diff --git a/arch/mips/loongson/common/reset.c b/arch/mips/loongson/common/reset.c
index a60715e..e251519 100644
--- a/arch/mips/loongson/common/reset.c
+++ b/arch/mips/loongson/common/reset.c
@@ -84,7 +84,7 @@ static int __init mips_reboot_setup(void)
 {
 	_machine_restart = loongson_restart;
 	_machine_halt = loongson_halt;
-	pm_power_off = loongson_poweroff;
+	register_poweroff_handler_simple(loongson_poweroff, 128);
 
 	return 0;
 }
diff --git a/arch/mips/loongson1/common/reset.c b/arch/mips/loongson1/common/reset.c
index 547f34b..fbb563a 100644
--- a/arch/mips/loongson1/common/reset.c
+++ b/arch/mips/loongson1/common/reset.c
@@ -38,7 +38,7 @@ static int __init ls1x_reboot_setup(void)
 {
 	_machine_restart = ls1x_restart;
 	_machine_halt = ls1x_halt;
-	pm_power_off = ls1x_power_off;
+	register_poweroff_handler_simple(ls1x_power_off, 0);
 
 	return 0;
 }
diff --git a/arch/mips/mti-malta/malta-reset.c b/arch/mips/mti-malta/malta-reset.c
index 2fd2cc2..632ce7c 100644
--- a/arch/mips/mti-malta/malta-reset.c
+++ b/arch/mips/mti-malta/malta-reset.c
@@ -40,7 +40,7 @@ static int __init mips_reboot_setup(void)
 {
 	_machine_restart = mips_machine_restart;
 	_machine_halt = mips_machine_halt;
-	pm_power_off = mips_machine_power_off;
+	register_poweroff_handler_simple(mips_machine_power_off, 128);
 
 	return 0;
 }
diff --git a/arch/mips/mti-sead3/sead3-reset.c b/arch/mips/mti-sead3/sead3-reset.c
index e6fb244..d1df04f 100644
--- a/arch/mips/mti-sead3/sead3-reset.c
+++ b/arch/mips/mti-sead3/sead3-reset.c
@@ -33,7 +33,7 @@ static int __init mips_reboot_setup(void)
 {
 	_machine_restart = mips_machine_restart;
 	_machine_halt = mips_machine_halt;
-	pm_power_off = mips_machine_halt;
+	register_poweroff_handler_simple(mips_machine_halt, 0);
 
 	return 0;
 }
diff --git a/arch/mips/netlogic/xlp/setup.c b/arch/mips/netlogic/xlp/setup.c
index 4fdd9fd..4982302 100644
--- a/arch/mips/netlogic/xlp/setup.c
+++ b/arch/mips/netlogic/xlp/setup.c
@@ -106,7 +106,7 @@ void __init plat_mem_setup(void)
 #endif
 	_machine_restart = (void (*)(char *))nlm_linux_exit;
 	_machine_halt	= nlm_linux_exit;
-	pm_power_off	= nlm_linux_exit;
+	register_poweroff_handler_simple(nlm_linux_exit, 0);
 
 	/* memory and bootargs from DT */
 	xlp_early_init_devtree();
diff --git a/arch/mips/netlogic/xlr/setup.c b/arch/mips/netlogic/xlr/setup.c
index d118b9a..5149dd4 100644
--- a/arch/mips/netlogic/xlr/setup.c
+++ b/arch/mips/netlogic/xlr/setup.c
@@ -75,7 +75,7 @@ void __init plat_mem_setup(void)
 {
 	_machine_restart = (void (*)(char *))nlm_linux_exit;
 	_machine_halt	= nlm_linux_exit;
-	pm_power_off	= nlm_linux_exit;
+	register_poweroff_handler_simple(nlm_linux_exit, 0);
 }
 
 const char *get_system_type(void)
diff --git a/arch/mips/pmcs-msp71xx/msp_setup.c b/arch/mips/pmcs-msp71xx/msp_setup.c
index 4f925e0..67699e30 100644
--- a/arch/mips/pmcs-msp71xx/msp_setup.c
+++ b/arch/mips/pmcs-msp71xx/msp_setup.c
@@ -144,7 +144,7 @@ void __init plat_mem_setup(void)
 {
 	_machine_restart = msp_restart;
 	_machine_halt = msp_halt;
-	pm_power_off = msp_power_off;
+	register_poweroff_handler_simple(msp_power_off, 0);
 }
 
 void __init prom_init(void)
diff --git a/arch/mips/pnx833x/common/setup.c b/arch/mips/pnx833x/common/setup.c
index 99b4d94..7c12665 100644
--- a/arch/mips/pnx833x/common/setup.c
+++ b/arch/mips/pnx833x/common/setup.c
@@ -51,7 +51,7 @@ int __init plat_mem_setup(void)
 
 	_machine_restart = pnx833x_machine_restart;
 	_machine_halt = pnx833x_machine_halt;
-	pm_power_off = pnx833x_machine_power_off;
+	register_poweroff_handler_simple(pnx833x_machine_power_off, 128);
 
 	/* IO/MEM resources. */
 	set_io_port_base(KSEG1);
diff --git a/arch/mips/ralink/reset.c b/arch/mips/ralink/reset.c
index 55c7ec5..e640e9e 100644
--- a/arch/mips/ralink/reset.c
+++ b/arch/mips/ralink/reset.c
@@ -98,7 +98,7 @@ static int __init mips_reboot_setup(void)
 {
 	_machine_restart = ralink_restart;
 	_machine_halt = ralink_halt;
-	pm_power_off = ralink_halt;
+	register_poweroff_handler_simple(ralink_halt, 0);
 
 	return 0;
 }
diff --git a/arch/mips/rb532/setup.c b/arch/mips/rb532/setup.c
index d0c64e7..c71a623 100644
--- a/arch/mips/rb532/setup.c
+++ b/arch/mips/rb532/setup.c
@@ -44,7 +44,7 @@ void __init plat_mem_setup(void)
 
 	_machine_restart = rb_machine_restart;
 	_machine_halt = rb_machine_halt;
-	pm_power_off = rb_machine_halt;
+	register_poweroff_handler-simple(rb_machine_halt, 0);
 
 	set_io_port_base(KSEG1);
 
diff --git a/arch/mips/sgi-ip22/ip22-reset.c b/arch/mips/sgi-ip22/ip22-reset.c
index 063c2dd..466e710 100644
--- a/arch/mips/sgi-ip22/ip22-reset.c
+++ b/arch/mips/sgi-ip22/ip22-reset.c
@@ -188,7 +188,7 @@ static int __init reboot_setup(void)
 
 	_machine_restart = sgi_machine_restart;
 	_machine_halt = sgi_machine_halt;
-	pm_power_off = sgi_machine_power_off;
+	register_poweroff_handler_simple(sgi_machine_power_off, 128);
 
 	res = request_irq(SGI_PANEL_IRQ, panel_int, 0, "Front Panel", NULL);
 	if (res) {
diff --git a/arch/mips/sgi-ip27/ip27-reset.c b/arch/mips/sgi-ip27/ip27-reset.c
index ac37e54..c26f04a 100644
--- a/arch/mips/sgi-ip27/ip27-reset.c
+++ b/arch/mips/sgi-ip27/ip27-reset.c
@@ -76,5 +76,5 @@ void ip27_reboot_setup(void)
 {
 	_machine_restart = ip27_machine_restart;
 	_machine_halt = ip27_machine_halt;
-	pm_power_off = ip27_machine_power_off;
+	register_poweroff_handler_simple(ip27_machine_power_off, 0);
 }
diff --git a/arch/mips/sgi-ip32/ip32-reset.c b/arch/mips/sgi-ip32/ip32-reset.c
index 1f823da..88d8692 100644
--- a/arch/mips/sgi-ip32/ip32-reset.c
+++ b/arch/mips/sgi-ip32/ip32-reset.c
@@ -189,7 +189,7 @@ static __init int ip32_reboot_setup(void)
 
 	_machine_restart = ip32_machine_restart;
 	_machine_halt = ip32_machine_halt;
-	pm_power_off = ip32_machine_power_off;
+	register_poweroff_handler_simple(ip32_machine_power_off, 0);
 
 	init_timer(&blink_timer);
 	blink_timer.function = blink_timeout;
diff --git a/arch/mips/sibyte/common/cfe.c b/arch/mips/sibyte/common/cfe.c
index 588e180..069de27 100644
--- a/arch/mips/sibyte/common/cfe.c
+++ b/arch/mips/sibyte/common/cfe.c
@@ -245,7 +245,7 @@ void __init prom_init(void)
 
 	_machine_restart   = cfe_linux_restart;
 	_machine_halt	   = cfe_linux_halt;
-	pm_power_off = cfe_linux_halt;
+	register_poweroff_handler_simple(cfe_linux_halt, 0);
 
 	/*
 	 * Check if a loader was used; if NOT, the 4 arguments are
diff --git a/arch/mips/sni/setup.c b/arch/mips/sni/setup.c
index efad85c..5242bd9 100644
--- a/arch/mips/sni/setup.c
+++ b/arch/mips/sni/setup.c
@@ -225,7 +225,7 @@ void __init plat_mem_setup(void)
 	}
 
 	_machine_restart = sni_machine_restart;
-	pm_power_off = sni_machine_power_off;
+	register_poweroff_handler_simple(sni_machine_power_off, 128);
 
 	sni_display_setup();
 	sni_console_setup();
diff --git a/arch/mips/txx9/generic/setup.c b/arch/mips/txx9/generic/setup.c
index 9ff200a..c429a4f 100644
--- a/arch/mips/txx9/generic/setup.c
+++ b/arch/mips/txx9/generic/setup.c
@@ -555,7 +555,7 @@ void __init plat_mem_setup(void)
 	/* fallback restart/halt routines */
 	_machine_restart = (void (*)(char *))txx9_machine_halt;
 	_machine_halt = txx9_machine_halt;
-	pm_power_off = txx9_machine_halt;
+	register_poweroff_handler_simple(txx9_machine_halt, 0);
 
 #ifdef CONFIG_PCI
 	pcibios_plat_setup = txx9_pcibios_setup;
diff --git a/arch/mips/vr41xx/common/pmu.c b/arch/mips/vr41xx/common/pmu.c
index d7f7558..4d947ab 100644
--- a/arch/mips/vr41xx/common/pmu.c
+++ b/arch/mips/vr41xx/common/pmu.c
@@ -127,7 +127,7 @@ static int __init vr41xx_pmu_init(void)
 	cpu_wait = vr41xx_cpu_wait;
 	_machine_restart = vr41xx_restart;
 	_machine_halt = vr41xx_halt;
-	pm_power_off = vr41xx_halt;
+	register_poweroff_handler_simple(vr41xx_halt, 0);
 
 	return 0;
 }
-- 
1.9.1

^ permalink raw reply related

* [PATCH 39/44] x86: ce4100: Register with kernel poweroff handler
From: Guenter Roeck @ 2014-10-07  5:28 UTC (permalink / raw)
  To: linux-kernel
  Cc: linux-m32r-ja, linux-mips, linux-efi, linux-ia64, linux-xtensa,
	H. Peter Anvin, Thomas Gleixner, devel, linux-s390, lguest,
	linux-c6x-dev, linux-hexagon, linux-sh, linux-acpi, Ingo Molnar,
	xen-devel, Guenter Roeck, devicetree, user-mode-linux-devel,
	linux-pm, adi-buildroot-devel, linux-m68k, linux-am33-list,
	linux-tegra, openipmi-developer, linux-metag, linux-arm-kernel,
	linux-parisc, linux-cris-kernel, linux-alpha, linuxppc-dev
In-Reply-To: <1412659726-29957-1-git-send-email-linux@roeck-us.net>

Register with kernel poweroff handler instead of setting pm_power_off
directly.

Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: Ingo Molnar <mingo@redhat.com>
Cc: H. Peter Anvin <hpa@zytor.com>
Signed-off-by: Guenter Roeck <linux@roeck-us.net>
---
 arch/x86/platform/ce4100/ce4100.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/arch/x86/platform/ce4100/ce4100.c b/arch/x86/platform/ce4100/ce4100.c
index 701fd58..4a7f3d6 100644
--- a/arch/x86/platform/ce4100/ce4100.c
+++ b/arch/x86/platform/ce4100/ce4100.c
@@ -164,5 +164,5 @@ void __init x86_ce4100_early_setup(void)
 	 */
 	reboot_type = BOOT_KBD;
 
-	pm_power_off = ce4100_power_off;
+	register_poweroff_handler_simple(ce4100_power_off, 128);
 }
-- 
1.9.1

^ permalink raw reply related

* [PATCH 40/44] x86: intel-mid: Drop registration of dummy poweroff handlers
From: Guenter Roeck @ 2014-10-07  5:28 UTC (permalink / raw)
  To: linux-kernel
  Cc: linux-m32r-ja, linux-mips, linux-efi, linux-ia64, linux-xtensa,
	H. Peter Anvin, Thomas Gleixner, devel, linux-s390, lguest,
	linux-c6x-dev, linux-hexagon, linux-sh, linux-acpi, Ingo Molnar,
	xen-devel, Guenter Roeck, devicetree, user-mode-linux-devel,
	linux-pm, adi-buildroot-devel, linux-m68k, linux-am33-list,
	linux-tegra, openipmi-developer, linux-metag, linux-arm-kernel,
	linux-parisc, linux-cris-kernel, linux-alpha, linuxppc-dev
In-Reply-To: <1412659726-29957-1-git-send-email-linux@roeck-us.net>

A dummy poweroff handler does not serve any purpose. Drop it.

Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: Ingo Molnar <mingo@redhat.com>
Cc: H. Peter Anvin <hpa@zytor.com>
Signed-off-by: Guenter Roeck <linux@roeck-us.net>
---
 arch/x86/platform/intel-mid/intel-mid.c | 5 -----
 arch/x86/platform/intel-mid/mfld.c      | 5 -----
 2 files changed, 10 deletions(-)

diff --git a/arch/x86/platform/intel-mid/intel-mid.c b/arch/x86/platform/intel-mid/intel-mid.c
index 1bbedc4..4b70666 100644
--- a/arch/x86/platform/intel-mid/intel-mid.c
+++ b/arch/x86/platform/intel-mid/intel-mid.c
@@ -67,10 +67,6 @@ static void *(*get_intel_mid_ops[])(void) = INTEL_MID_OPS_INIT;
 enum intel_mid_cpu_type __intel_mid_cpu_chip;
 EXPORT_SYMBOL_GPL(__intel_mid_cpu_chip);
 
-static void intel_mid_power_off(void)
-{
-};
-
 static void intel_mid_reboot(void)
 {
 	intel_scu_ipc_simple_command(IPCMSG_COLD_BOOT, 0);
@@ -183,7 +179,6 @@ void __init x86_intel_mid_early_setup(void)
 
 	legacy_pic = &null_legacy_pic;
 
-	pm_power_off = intel_mid_power_off;
 	machine_ops.emergency_restart  = intel_mid_reboot;
 
 	/* Avoid searching for BIOS MP tables */
diff --git a/arch/x86/platform/intel-mid/mfld.c b/arch/x86/platform/intel-mid/mfld.c
index 23381d2..cf6842f 100644
--- a/arch/x86/platform/intel-mid/mfld.c
+++ b/arch/x86/platform/intel-mid/mfld.c
@@ -23,10 +23,6 @@ static struct intel_mid_ops penwell_ops = {
 	.arch_setup = penwell_arch_setup,
 };
 
-static void mfld_power_off(void)
-{
-}
-
 static unsigned long __init mfld_calibrate_tsc(void)
 {
 	unsigned long fast_calibrate;
@@ -61,7 +57,6 @@ static unsigned long __init mfld_calibrate_tsc(void)
 static void __init penwell_arch_setup(void)
 {
 	x86_platform.calibrate_tsc = mfld_calibrate_tsc;
-	pm_power_off = mfld_power_off;
 }
 
 void *get_penwell_ops(void)
-- 
1.9.1

^ permalink raw reply related

* [PATCH 41/44] x86: pmc_atom: Register poweroff handler with kernel poweroff handler
From: Guenter Roeck @ 2014-10-07  5:28 UTC (permalink / raw)
  To: linux-kernel
  Cc: linux-m32r-ja, linux-mips, linux-efi, linux-ia64, linux-xtensa,
	H. Peter Anvin, Thomas Gleixner, devel, linux-s390, lguest,
	linux-c6x-dev, linux-hexagon, linux-sh, linux-acpi, Ingo Molnar,
	xen-devel, Guenter Roeck, devicetree, user-mode-linux-devel,
	linux-pm, adi-buildroot-devel, linux-m68k, linux-am33-list,
	linux-tegra, openipmi-developer, linux-metag, linux-arm-kernel,
	linux-parisc, linux-cris-kernel, linux-alpha, linuxppc-dev
In-Reply-To: <1412659726-29957-1-git-send-email-linux@roeck-us.net>

Register with kernel poweroff handler instead of setting pm_power_off
directly. Register with a low priority value of 64 to reflect that
the original code only sets pm_power_off if it was not already set.

Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: Ingo Molnar <mingo@redhat.com>
Cc: H. Peter Anvin <hpa@zytor.com>
Signed-off-by: Guenter Roeck <linux@roeck-us.net>
---
 arch/x86/kernel/pmc_atom.c | 20 +++++++++++++++++---
 1 file changed, 17 insertions(+), 3 deletions(-)

diff --git a/arch/x86/kernel/pmc_atom.c b/arch/x86/kernel/pmc_atom.c
index 0c424a6..79331a2 100644
--- a/arch/x86/kernel/pmc_atom.c
+++ b/arch/x86/kernel/pmc_atom.c
@@ -20,6 +20,8 @@
 #include <linux/pci.h>
 #include <linux/device.h>
 #include <linux/debugfs.h>
+#include <linux/notifier.h>
+#include <linux/pm.h>
 #include <linux/seq_file.h>
 #include <linux/io.h>
 
@@ -92,7 +94,8 @@ static inline void pmc_reg_write(struct pmc_dev *pmc, int reg_offset, u32 val)
 	writel(val, pmc->regmap + reg_offset);
 }
 
-static void pmc_power_off(void)
+static int pmc_power_off(struct notifier_block *this, unsigned long unused1,
+			 void *unused2)
 {
 	u16	pm1_cnt_port;
 	u32	pm1_cnt_value;
@@ -107,8 +110,15 @@ static void pmc_power_off(void)
 	pm1_cnt_value |= SLEEP_ENABLE;
 
 	outl(pm1_cnt_value, pm1_cnt_port);
+
+	return NOTIFY_DONE;
 }
 
+static struct notifier_block pmc_poweroff_nb = {
+	.notifier_call = pmc_power_off,
+	.priority = 64,
+};
+
 static void pmc_hw_reg_setup(struct pmc_dev *pmc)
 {
 	/*
@@ -247,8 +257,12 @@ static int pmc_setup_dev(struct pci_dev *pdev)
 	acpi_base_addr &= ACPI_BASE_ADDR_MASK;
 
 	/* Install power off function */
-	if (acpi_base_addr != 0 && pm_power_off == NULL)
-		pm_power_off = pmc_power_off;
+	if (acpi_base_addr != 0) {
+		ret = register_poweroff_handler(&pmc_poweroff_nb);
+		if (ret)
+			dev_err(&pdev->dev,
+				"Failed to install poweroff handler\n");
+	}
 
 	pci_read_config_dword(pdev, PMC_BASE_ADDR_OFFSET, &pmc->base_addr);
 	pmc->base_addr &= PMC_BASE_ADDR_MASK;
-- 
1.9.1

^ permalink raw reply related

* [PATCH 42/44] efi: Register poweroff handler with kernel poweroff handler
From: Guenter Roeck @ 2014-10-07  5:28 UTC (permalink / raw)
  To: linux-kernel
  Cc: linux-m32r-ja, linux-mips, linux-efi, linux-ia64, linux-xtensa,
	devel, linux-s390, lguest, linux-c6x-dev, linux-hexagon, linux-sh,
	linux-acpi, xen-devel, Guenter Roeck, devicetree,
	user-mode-linux-devel, linux-pm, adi-buildroot-devel, linux-m68k,
	linux-am33-list, linux-tegra, openipmi-developer, linux-metag,
	linux-arm-kernel, Matt Fleming, linux-parisc, linux-cris-kernel,
	linux-alpha, linuxppc-dev
In-Reply-To: <1412659726-29957-1-git-send-email-linux@roeck-us.net>

Register with kernel poweroff handler instead of setting pm_power_off
directly. Register with low priority value of 64 since the efi code
states that this is a poweroff handler of last resort.

Cc: Matt Fleming <matt.fleming@intel.com>
Signed-off-by: Guenter Roeck <linux@roeck-us.net>
---
 drivers/firmware/efi/reboot.c | 23 +++++++++++++++++++----
 1 file changed, 19 insertions(+), 4 deletions(-)

diff --git a/drivers/firmware/efi/reboot.c b/drivers/firmware/efi/reboot.c
index 9c59d1c..c082439 100644
--- a/drivers/firmware/efi/reboot.c
+++ b/drivers/firmware/efi/reboot.c
@@ -3,6 +3,8 @@
  * Copyright (c) 2014 Red Hat, Inc., Mark Salter <msalter@redhat.com>
  */
 #include <linux/efi.h>
+#include <linux/notifier.h>
+#include <linux/pm.h>
 #include <linux/reboot.h>
 
 int efi_reboot_quirk_mode = -1;
@@ -38,19 +40,32 @@ bool __weak efi_poweroff_required(void)
 	return false;
 }
 
-static void efi_power_off(void)
+static int efi_power_off(struct notifier_block *this,
+			 unsigned long unused1, void *unused2)
 {
 	efi.reset_system(EFI_RESET_SHUTDOWN, EFI_SUCCESS, 0, NULL);
+
+	return NOTIFY_DONE;
 }
 
+static struct notifier_block efi_poweroff_nb = {
+	.notifier_call = efi_power_off,
+	.priority = 64,
+};
+
 static int __init efi_shutdown_init(void)
 {
+	int ret = 0;
+
 	if (!efi_enabled(EFI_RUNTIME_SERVICES))
 		return -ENODEV;
 
-	if (efi_poweroff_required())
-		pm_power_off = efi_power_off;
+	if (efi_poweroff_required()) {
+		ret = register_poweroff_handler(&efi_poweroff_nb);
+		if (ret)
+			pr_err("efi: Failed to register poweroff handler\n");
+	}
 
-	return 0;
+	return ret;
 }
 late_initcall(efi_shutdown_init);
-- 
1.9.1

^ permalink raw reply related

* [PATCH 43/44] hwmon: (ab8500) Call kernel_power_off instead of pm_power_off
From: Guenter Roeck @ 2014-10-07  5:28 UTC (permalink / raw)
  To: linux-kernel
  Cc: linux-m32r-ja, linux-mips, linux-efi, linux-ia64, linux-xtensa,
	Jean Delvare, devel, linux-s390, lguest, linux-c6x-dev,
	linux-hexagon, linux-sh, linux-acpi, xen-devel, Guenter Roeck,
	devicetree, user-mode-linux-devel, linux-pm, adi-buildroot-devel,
	linux-m68k, linux-am33-list, linux-tegra, openipmi-developer,
	linux-metag, linux-arm-kernel, linux-parisc, linux-cris-kernel,
	linux-alpha, linuxppc-dev
In-Reply-To: <1412659726-29957-1-git-send-email-linux@roeck-us.net>

Drivers should not call pm_power_off directly; it is not guaranteed
to be non-NULL. Call kernel_power_off instead.

Cc: Jean Delvare <jdelvare@suse.de>
Reviewed-by: Jean Delvare <jdelvare@suse.de>
Signed-off-by: Guenter Roeck <linux@roeck-us.net>
---
 drivers/hwmon/ab8500.c | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/drivers/hwmon/ab8500.c b/drivers/hwmon/ab8500.c
index d844dc8..8b6a4f4 100644
--- a/drivers/hwmon/ab8500.c
+++ b/drivers/hwmon/ab8500.c
@@ -6,7 +6,7 @@
  *
  * When the AB8500 thermal warning temperature is reached (threshold cannot
  * be changed by SW), an interrupt is set, and if no further action is taken
- * within a certain time frame, pm_power off will be called.
+ * within a certain time frame, kernel_power_off will be called.
  *
  * When AB8500 thermal shutdown temperature is reached a hardware shutdown of
  * the AB8500 will occur.
@@ -21,6 +21,7 @@
 #include <linux/module.h>
 #include <linux/platform_device.h>
 #include <linux/power/ab8500.h>
+#include <linux/reboot.h>
 #include <linux/slab.h>
 #include <linux/sysfs.h>
 #include "abx500.h"
@@ -106,7 +107,7 @@ static void ab8500_thermal_power_off(struct work_struct *work)
 
 	dev_warn(&abx500_data->pdev->dev, "Power off due to critical temp\n");
 
-	pm_power_off();
+	kernel_power_off();
 }
 
 static ssize_t ab8500_show_name(struct device *dev,
-- 
1.9.1

^ permalink raw reply related

* [PATCH 44/44] kernel: Remove pm_power_off
From: Guenter Roeck @ 2014-10-07  5:28 UTC (permalink / raw)
  To: linux-kernel
  Cc: linux-m32r-ja, linux-mips, linux-efi, linux-ia64, Len Brown,
	linux-xtensa, Pavel Machek, devel, linux-s390, lguest,
	linux-c6x-dev, linux-hexagon, linux-sh, linux-acpi, xen-devel,
	Guenter Roeck, devicetree, user-mode-linux-devel, linux-pm,
	adi-buildroot-devel, linux-m68k, linux-am33-list, linux-tegra,
	openipmi-developer, linux-metag, linux-arm-kernel, linux-parisc,
	linux-cris-kernel, Rafael J. Wysocki, linux-alpha, linuxppc-dev
In-Reply-To: <1412659726-29957-1-git-send-email-linux@roeck-us.net>

No users of pm_power_off are left, so it is safe to remove the function.

Cc: Rafael J. Wysocki <rjw@rjwysocki.net>
Cc: Pavel Machek <pavel@ucw.cz>
Cc: Len Brown <len.brown@intel.com>
Signed-off-by: Guenter Roeck <linux@roeck-us.net>
---
 include/linux/pm.h              |  1 -
 kernel/power/poweroff_handler.c | 10 +---------
 2 files changed, 1 insertion(+), 10 deletions(-)

diff --git a/include/linux/pm.h b/include/linux/pm.h
index 45271b5..fce7645 100644
--- a/include/linux/pm.h
+++ b/include/linux/pm.h
@@ -31,7 +31,6 @@
 /*
  * Callbacks for platform drivers to implement.
  */
-extern void (*pm_power_off)(void);
 extern void (*pm_power_off_prepare)(void);
 
 /*
diff --git a/kernel/power/poweroff_handler.c b/kernel/power/poweroff_handler.c
index 96f59ef..01a3a39 100644
--- a/kernel/power/poweroff_handler.c
+++ b/kernel/power/poweroff_handler.c
@@ -20,12 +20,6 @@
 #include <linux/types.h>
 
 /*
- * If set, calling this function will power off the system immediately.
- */
-void (*pm_power_off)(void);
-EXPORT_SYMBOL(pm_power_off);
-
-/*
  *	Notifier list for kernel code which wants to be called
  *	to power off the system.
  */
@@ -163,8 +157,6 @@ int register_poweroff_handler_simple(void (*handler)(void), int priority)
  */
 void do_kernel_poweroff(void)
 {
-	if (pm_power_off)
-		pm_power_off();
 	atomic_notifier_call_chain(&poweroff_handler_list, 0, NULL);
 }
 
@@ -175,6 +167,6 @@ void do_kernel_poweroff(void)
  */
 bool have_kernel_poweroff(void)
 {
-	return pm_power_off != NULL || poweroff_handler_list.head != NULL;
+	return poweroff_handler_list.head != NULL;
 }
 EXPORT_SYMBOL(have_kernel_poweroff);
-- 
1.9.1

^ permalink raw reply related

* Re: [PATCH v2 3/5] powerpc/powernv: Add winkle infrastructure
From: Benjamin Herrenschmidt @ 2014-10-07  5:33 UTC (permalink / raw)
  To: Shreyas B. Prabhu; +Cc: linuxppc-dev, Paul Mackerras, linux-kernel
In-Reply-To: <1412149617-3178-4-git-send-email-shreyas@linux.vnet.ibm.com>

On Wed, 2014-10-01 at 13:16 +0530, Shreyas B. Prabhu wrote:
> Winkle causes power to be gated off to the entire chiplet. Hence the
> hypervisor/firmware state in the entire chiplet is lost.
> 
> This patch adds necessary infrastructure to support waking up from
> hypervisor state loss. Specifically does following:
> - Before entering winkle, save state of registers that need to be
>   restored on wake up (SDR1, HFSCR)

 Add ... to your list, it's not exhaustive, is it ?

> - SRR1 bits 46:47 which is used to identify which power saving mode cpu
>   woke up from is '11' for both winkle and sleep. Hence introduce a flag
>   in PACA to distinguish b/w winkle and sleep.
> 
> - Upon waking up, restore all saved registers, recover slb
> 
> Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org>
> Cc: Paul Mackerras <paulus@samba.org>
> Cc: Michael Ellerman <mpe@ellerman.id.au>
> Cc: linuxppc-dev@lists.ozlabs.org
> Suggested-by: Vaidyanathan Srinivasan <svaidy@linux.vnet.ibm.com>
> Signed-off-by: Shreyas B. Prabhu <shreyas@linux.vnet.ibm.com>
> ---
>  arch/powerpc/include/asm/machdep.h     |  1 +
>  arch/powerpc/include/asm/paca.h        |  3 ++
>  arch/powerpc/include/asm/ppc-opcode.h  |  2 +
>  arch/powerpc/include/asm/processor.h   |  2 +
>  arch/powerpc/kernel/asm-offsets.c      |  1 +
>  arch/powerpc/kernel/exceptions-64s.S   |  8 ++--
>  arch/powerpc/kernel/idle.c             | 11 +++++
>  arch/powerpc/kernel/idle_power7.S      | 81 +++++++++++++++++++++++++++++++++-
>  arch/powerpc/platforms/powernv/setup.c | 24 ++++++++++
>  9 files changed, 127 insertions(+), 6 deletions(-)
> 
> diff --git a/arch/powerpc/include/asm/machdep.h b/arch/powerpc/include/asm/machdep.h
> index f37014f..0a3ced9 100644
> --- a/arch/powerpc/include/asm/machdep.h
> +++ b/arch/powerpc/include/asm/machdep.h
> @@ -301,6 +301,7 @@ struct machdep_calls {
>  	/* Idle handlers */
>  	void		(*setup_idle)(void);
>  	unsigned long	(*power7_sleep)(void);
> +	unsigned long	(*power7_winkle)(void);
>  };

Why does it need to be ppc_md ? Same comments as for sleep
 
>  extern void e500_idle(void);
> diff --git a/arch/powerpc/include/asm/paca.h b/arch/powerpc/include/asm/paca.h
> index a5139ea..3358f09 100644
> --- a/arch/powerpc/include/asm/paca.h
> +++ b/arch/powerpc/include/asm/paca.h
> @@ -158,6 +158,9 @@ struct paca_struct {
>  	 * early exception handler for use by high level C handler
>  	 */
>  	struct opal_machine_check_event *opal_mc_evt;
> +
> +	/* Flag to distinguish b/w sleep and winkle */
> +	u8 offline_state;

Not fan of the name. I'd rather you call it "wakeup_state_loss" or
something a bit more explicit about what that actually means if it's
going to be a boolean value. Otherwise make it an enumeration of
constants.

>  #endif
>  #ifdef CONFIG_PPC_BOOK3S_64
>  	/* Exclusive emergency stack pointer for machine check exception. */
> diff --git a/arch/powerpc/include/asm/ppc-opcode.h b/arch/powerpc/include/asm/ppc-opcode.h
> index 6f85362..5155be7 100644
> --- a/arch/powerpc/include/asm/ppc-opcode.h
> +++ b/arch/powerpc/include/asm/ppc-opcode.h
> @@ -194,6 +194,7 @@
>  
>  #define PPC_INST_NAP			0x4c000364
>  #define PPC_INST_SLEEP			0x4c0003a4
> +#define PPC_INST_WINKLE			0x4c0003e4
>  
>  /* A2 specific instructions */
>  #define PPC_INST_ERATWE			0x7c0001a6
> @@ -374,6 +375,7 @@
>  
>  #define PPC_NAP			stringify_in_c(.long PPC_INST_NAP)
>  #define PPC_SLEEP		stringify_in_c(.long PPC_INST_SLEEP)
> +#define PPC_WINKLE		stringify_in_c(.long PPC_INST_WINKLE)
>  
>  /* BHRB instructions */
>  #define PPC_CLRBHRB		stringify_in_c(.long PPC_INST_CLRBHRB)
> diff --git a/arch/powerpc/include/asm/processor.h b/arch/powerpc/include/asm/processor.h
> index 41953cd..00e3df9 100644
> --- a/arch/powerpc/include/asm/processor.h
> +++ b/arch/powerpc/include/asm/processor.h
> @@ -455,6 +455,8 @@ extern void arch_setup_idle(void);
>  extern void power7_nap(int check_irq);
>  extern unsigned long power7_sleep(void);
>  extern unsigned long __power7_sleep(void);
> +extern unsigned long power7_winkle(void);
> +extern unsigned long __power7_winkle(void);
>  extern void flush_instruction_cache(void);
>  extern void hard_reset_now(void);
>  extern void poweroff_now(void);
> diff --git a/arch/powerpc/kernel/asm-offsets.c b/arch/powerpc/kernel/asm-offsets.c
> index 9d7dede..ea98817 100644
> --- a/arch/powerpc/kernel/asm-offsets.c
> +++ b/arch/powerpc/kernel/asm-offsets.c
> @@ -731,6 +731,7 @@ int main(void)
>  	DEFINE(OPAL_MC_SRR0, offsetof(struct opal_machine_check_event, srr0));
>  	DEFINE(OPAL_MC_SRR1, offsetof(struct opal_machine_check_event, srr1));
>  	DEFINE(PACA_OPAL_MC_EVT, offsetof(struct paca_struct, opal_mc_evt));
> +	DEFINE(PACAOFFLINESTATE, offsetof(struct paca_struct, offline_state));
>  #endif
>  
>  	return 0;
> diff --git a/arch/powerpc/kernel/exceptions-64s.S b/arch/powerpc/kernel/exceptions-64s.S
> index c64f3cc0..261f348 100644
> --- a/arch/powerpc/kernel/exceptions-64s.S
> +++ b/arch/powerpc/kernel/exceptions-64s.S
> @@ -115,9 +115,7 @@ BEGIN_FTR_SECTION
>  #endif
>  
>  	/* Running native on arch 2.06 or later, check if we are
> -	 * waking up from nap. We only handle no state loss and
> -	 * supervisor state loss. We do -not- handle hypervisor
> -	 * state loss at this time.
> +	 * waking up from power saving mode.
>  	 */
>  	mfspr	r13,SPRN_SRR1
>  	rlwinm.	r13,r13,47-31,30,31
> @@ -133,8 +131,8 @@ BEGIN_FTR_SECTION
>  	b	power7_wakeup_noloss
>  2:	b	power7_wakeup_loss
>  
> -	/* Fast Sleep wakeup on PowerNV */
> -8:	b 	power7_wakeup_tb_loss
> +	/* Fast Sleep / Winkle wakeup on PowerNV */
> +8:	b 	power7_wakeup_hv_state_loss
>  
>  9:
>  END_FTR_SECTION_IFSET(CPU_FTR_HVMODE | CPU_FTR_ARCH_206)
> diff --git a/arch/powerpc/kernel/idle.c b/arch/powerpc/kernel/idle.c
> index 1f268e0..ed46217 100644
> --- a/arch/powerpc/kernel/idle.c
> +++ b/arch/powerpc/kernel/idle.c
> @@ -98,6 +98,17 @@ unsigned long power7_sleep(void)
>  	return ret;
>  }
>  
> +unsigned long power7_winkle(void)
> +{
> +	unsigned long ret;
> +
> +	if (ppc_md.power7_winkle)
> +		ret = ppc_md.power7_winkle();
> +	else
> +		ret = __power7_winkle();
> +	return ret;
> +}
> +
>  int powersave_nap;
>  
>  #ifdef CONFIG_SYSCTL
> diff --git a/arch/powerpc/kernel/idle_power7.S b/arch/powerpc/kernel/idle_power7.S
> index c3481c9..87b2556 100644
> --- a/arch/powerpc/kernel/idle_power7.S
> +++ b/arch/powerpc/kernel/idle_power7.S
> @@ -18,6 +18,13 @@
>  #include <asm/hw_irq.h>
>  #include <asm/kvm_book3s_asm.h>
>  #include <asm/opal.h>
> +#include <asm/mmu-hash64.h>
> +
> +/*
> + * Use volatile GPRs' space to save essential SPRs before entering winkle
> + */
> +#define _SDR1	GPR3
> +#define _TSCR	GPR4
>  
>  #undef DEBUG
>  
> @@ -39,6 +46,7 @@
>   * Pass requested state in r3:
>   * 	0 - nap
>   * 	1 - sleep
> + *	2 - winkle
>   *
>   * To check IRQ_HAPPENED in r4
>   * 	0 - don't check
> @@ -109,9 +117,27 @@ _GLOBAL(power7_enter_nap_mode)
>  #endif
>  	cmpwi	cr0,r3,1
>  	beq	2f
> +	cmpwi	cr0,r3,2
> +	beq	3f
>  	IDLE_STATE_ENTER_SEQ(PPC_NAP)
>  	/* No return */
> -2:	IDLE_STATE_ENTER_SEQ(PPC_SLEEP)
> +2:
> +	li	r4,1
> +	stb	r4,PACAOFFLINESTATE(r13)
> +	IDLE_STATE_ENTER_SEQ(PPC_SLEEP)
> +	/* No return */
> +
> +3:
> +	mfspr   r4,SPRN_SDR1
> +	std     r4,_SDR1(r1)
> +
> +	mfspr   r4,SPRN_TSCR
> +	std     r4,_TSCR(r1)
> +
> +	/* Enter winkle */
> +        li      r4,0
> +        stb     r4,PACAOFFLINESTATE(r13)
> +	IDLE_STATE_ENTER_SEQ(PPC_WINKLE)
>  	/* No return */
>  
>  _GLOBAL(power7_idle)
> @@ -187,6 +213,59 @@ ALT_FTR_SECTION_END_NESTED_IFSET(CPU_FTR_ARCH_207S, 66);		\
>  20:	nop;
>  
> 
> +_GLOBAL(__power7_winkle)
> +	li	r3,2
> +	li	r4,1
> +	b	power7_powersave_common
> +	/* No return */
> +
> +_GLOBAL(power7_wakeup_hv_state_loss)
> +	/* Check paca flag to diffentiate b/w fast sleep and winkle */
> +	lbz	r4,PACAOFFLINESTATE(13)
> +	cmpwi	cr0,r4,0
> +	bne	power7_wakeup_tb_loss
> +
> +	ld      r2,PACATOC(r13);
> +	ld      r1,PACAR1(r13)
> +
> +	bl 	__restore_cpu_power8

So if I understand correctly, you use a per-cpu flag not a per-core flag
which means we will assume a pessimistic case of having to restore stuff
even if the core didn't actually enter winkle (because the last thread
to go down went to sleep). This is sub-optimal. Also see below:

> +	/* Time base re-sync */
> +	li	r3,OPAL_RESYNC_TIMEBASE
> +	bl	opal_call_realmode;

You will also resync the timebase (and restore all the core shared SPRs)
for each thread. This is problematic, especially with KVM as you could
have a situation where:

 - The first thread comes out and starts diving into KVM

 - The other threads start coming out while the first one is doing the
above.

Thus the first thread might already be manipulating some core registers
(SDR1 etc...) while the secondaries come back and ... whack it. Worse,
the primary might have applied the TB offset using TBU40 while the
secondaries resync the timebase back to the host value, incurring a
loss of TB for the guest.

> +	/* Restore SLB  from PACA */
> +	ld	r8,PACA_SLBSHADOWPTR(r13)
> +
> +	.rept	SLB_NUM_BOLTED
> +	li	r3, SLBSHADOW_SAVEAREA
> +	LDX_BE	r5, r8, r3
> +	addi	r3, r3, 8
> +	LDX_BE	r6, r8, r3
> +	andis.	r7,r5,SLB_ESID_V@h
> +	beq	1f
> +	slbmte	r6,r5
> +1:	addi	r8,r8,16
> +	.endr
> +
> +	ld      r4,_SDR1(r1)
> +	mtspr   SPRN_SDR1,r4
> +
> +	ld      r4,_TSCR(r1)
> +	mtspr   SPRN_TSCR,r4
> +
> +	REST_NVGPRS(r1)
> +	REST_GPR(2, r1)
> +	ld      r3,_CCR(r1)
> +	ld      r4,_MSR(r1)
> +	ld      r5,_NIP(r1)
> +	addi    r1,r1,INT_FRAME_SIZE
> +	mtcr    r3
> +	mfspr   r3,SPRN_SRR1            /* Return SRR1 */
> +	mtspr   SPRN_SRR1,r4
> +	mtspr   SPRN_SRR0,r5
> +	rfid
> +
>  _GLOBAL(power7_wakeup_tb_loss)
>  	ld	r2,PACATOC(r13);
>  	ld	r1,PACAR1(r13)
> diff --git a/arch/powerpc/platforms/powernv/setup.c b/arch/powerpc/platforms/powernv/setup.c
> index 9d9a898..f45b52d 100644
> --- a/arch/powerpc/platforms/powernv/setup.c
> +++ b/arch/powerpc/platforms/powernv/setup.c
> @@ -370,6 +370,29 @@ static unsigned long pnv_power7_sleep(void)
>  	return srr1;
>  }
>  
> +/*
> + * We need to keep track of offline cpus also for calling
> + * fastsleep workaround appropriately
> + */
> +static unsigned long pnv_power7_winkle(void)
> +{
> +	int cpu, primary_thread;
> +	unsigned long srr1;
> +
> +	cpu = smp_processor_id();
> +	primary_thread = cpu_first_thread_sibling(cpu);
> +
> +	if (need_fastsleep_workaround) {
> +		pnv_apply_fastsleep_workaround(1, primary_thread);
> +		srr1 = __power7_winkle();
> +		pnv_apply_fastsleep_workaround(0, primary_thread);
> +	} else {
> +			srr1 = __power7_winkle();
> +	}
> +	return srr1;
> +}
> +
> +
>  static void __init pnv_setup_machdep_opal(void)
>  {
>  	ppc_md.get_boot_time = opal_get_boot_time;
> @@ -384,6 +407,7 @@ static void __init pnv_setup_machdep_opal(void)
>  	ppc_md.handle_hmi_exception = opal_handle_hmi_exception;
>  	ppc_md.setup_idle = pnv_setup_idle;
>  	ppc_md.power7_sleep = pnv_power7_sleep;
> +	ppc_md.power7_winkle = pnv_power7_winkle;
>  }
>  
>  #ifdef CONFIG_PPC_POWERNV_RTAS

^ permalink raw reply

* [PATCH v3 3/7] gpu/radeon: Set flag to indicate broken 64-bit MSI
From: Benjamin Herrenschmidt @ 2014-10-07  4:38 UTC (permalink / raw)
  To: Alex Deucher, Bjorn Helgaas
  Cc: linuxppc-dev, Dave Airlie, linux-pci, Anton Blanchard,
	Yijing Wang, Takashi Iwai, Brian King

Some radeon ASICs don't support all 64 address bits of MSIs despite
advertising support for 64-bit MSIs in their configuration space.

This breaks on systems such as IBM POWER7/8, where 64-bit MSIs can
be assigned with some of the high address bits set.

This makes use of the newly introduced "no_64bit_msi" flag in structure
pci_dev to allow the MSI allocation code to fallback to 32-bit MSIs
on those adapters.

Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Reviewed-by: Alex Deucher <alexander.deucher@amd.com>
CC: <stable@vger.kernel.org>
---

Adding Alex's review tag. Patch to the driver is identical to the
reviewed one, I dropped the arch/powerpc hunk rewrote the subject
and cset comment.
---
 drivers/gpu/drm/radeon/radeon_irq_kms.c | 10 ++++++++++
 1 file changed, 10 insertions(+)

diff --git a/drivers/gpu/drm/radeon/radeon_irq_kms.c b/drivers/gpu/drm/radeon/radeon_irq_kms.c
index 16807af..c74f12d 100644
--- a/drivers/gpu/drm/radeon/radeon_irq_kms.c
+++ b/drivers/gpu/drm/radeon/radeon_irq_kms.c
@@ -202,6 +202,16 @@ static bool radeon_msi_ok(struct radeon_device *rdev)
 	if (rdev->flags & RADEON_IS_AGP)
 		return false;
 
+	/*
+	 * Older chips have a HW limitation, they can only generate 40 bits
+	 * of address for "64-bit" MSIs which breaks on some platforms, notably
+	 * IBM POWER servers, so we limit them
+	 */
+	if (rdev->family < CHIP_BONAIRE) {
+		dev_info(rdev->dev, "radeon: MSI limited to 32-bit\n");
+		rdev->pdev->no_64bit_msi = 1;
+	}
+
 	/* force MSI on */
 	if (radeon_msi == 1)
 		return true;

^ permalink raw reply related

* Re: [PATCH v3 0/5] powerpc/perf: Miscellaneous fixes
From: Sukadev Bhattiprolu @ 2014-10-07  6:23 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo, ak, Jiri Olsa, peterz, eranian,
	Paul Mackerras
  Cc: linuxppc-dev, dev, linux-kernel, Michael Ellerman,
	Anshuman Khandual
In-Reply-To: <1412143402-26061-1-git-send-email-sukadev@linux.vnet.ibm.com>

[-- Attachment #1: Type: text/plain, Size: 945 bytes --]

Sukadev Bhattiprolu [sukadev@linux.vnet.ibm.com] wrote:
| Miscellaenous fixes for perf and 24x7 counters in powerpc.
| 
| Patches 1,3,4 were submitted earlier as a part of the parametrized
| events for 24x7 counters. But they are not directly related to the
| parametrized events.
| 
| Patch 2 simplifies and fixes a bug in catalog_read() which causes the
| catalog file to not read first page.
| 
| Changelog[v3]
| 	[Michael Ellerman] Cleanup patches 1 and 2 and fix a bug
| 	Add patch 5/5 to update contact info for 24x7 and GPCI counters
| 
| Changelog[v2]
| 	Rebase to perf/core tree.
| 
| Cody P Schafer (3):
|   powerpc/perf/hv-24x7: use kmem_cache instead of aligned stack
|     allocations
|   perf Documentation: sysfs events/ interfaces
|   perf Documentation: remove duplicated docs for powerpc cpu specific
|     events

Per Michael Ellerman's suggestion, attaching an informal test case to
demonstrate the bug and the fix.

Sukadev

[-- Attachment #2: cp-catalog.c --]
[-- Type: text/x-csrc, Size: 1420 bytes --]

#include <stdio.h>
#include <fcntl.h>
#include <string.h>
#include <sys/stat.h>

/*
 * Usage: cp-catalog <read_size>
 *
 * Read the catalog from beginning to end. Read 'read_size' bytes
 * on each read.
 *
 * To ensure that a bug in catalog_read() in the kernel code is fixed.
 * 	cp-catalog 5 > /tmp/catalog-5
 * 	cp-catalog  > /tmp/catalog-4096
 * 	diff /tmp/catalog-5 /tmp/catalog-4096
 *
 * If both files are identical and size is about 256K, the bug is fixed.
 */
#define CATALOG	"/sys/bus/event_source/devices/hv_24x7/interface/catalog"
#define TMP_CATALOG	"/tmp/catalog"

main(int argc, char *argv[])
{
	int read_size, rfd, wfd, rc;
	struct stat stat_buf;
	char *input_file;
	char buf[4096];
	char output_file[256];

	read_size = 4096;
	if (argc > 1)
		read_size = atoi(argv[1]);

	if (read_size > sizeof(buf))
		read_size = sizeof(buf);

	input_file = CATALOG;
	sprintf(output_file, "%s-%d", TMP_CATALOG, read_size);

	rfd = open(input_file, O_RDONLY);
	if (rfd < 0) {
		perror(input_file);
		_Exit(1);
	}

	wfd  = open(output_file, O_WRONLY|O_CREAT|O_TRUNC);
	if (wfd < 0) {
		perror(output_file);
		_Exit(1);
	}

	while(1) {
		memset(buf, 0, sizeof(buf));
		rc = read(rfd, buf, read_size);
		if (rc <= 0)
			break;
		if (write(wfd, buf, rc) != rc) {
			perror("write()");
			break;
		}
	}
	if (fstat(wfd, &stat_buf) < 0) {
		perror("fstat()");
		_Exit(1);
	}
	printf("catalog size %zd\n", stat_buf.st_size);
}

^ permalink raw reply

* Re: [PATCH 00/20] powerpc: Convert power off logic to pm_power_off
From: Michael Ellerman @ 2014-10-07  6:25 UTC (permalink / raw)
  To: Alexander Graf
  Cc: Arnd Bergmann, Geoff Levand, Alistair Popple, Scott Wood,
	Anatolij Gustschin, linuxppc-dev
In-Reply-To: <54326850.1030801@suse.de>

On Mon, 2014-10-06 at 12:00 +0200, Alexander Graf wrote:
> 
> On 03.10.14 06:42, Michael Ellerman wrote:
> > On Wed, 2014-10-01 at 15:27 +0200, Alexander Graf wrote:
> >> The generic Linux framework to power off the machine is a function pointer
> >> called pm_power_off. The trick about this pointer is that device drivers can
> >> potentially implement it rather than board files.
> >>
> >> Today on PowerPC we set pm_power_off to invoke our generic full machine power
> >> off logic which then calls ppc_md.power_off to invoke machine specific power
> >> off.
> >>
> >> To fix this up, let's get rid of the ppc_md.power_off logic and just always use
> >> pm_power_off as was intended. Then individual drivers such as the GPIO power off
> >> driver can implement power off logic via that function pointer.
> > 
> > This looks OK to me with one caveat.
> > 
> > In several of the patches you're replacing a static initialisation with a
> > runtime one, and you're doing the runtime initialisation in xxx_setup_arch().
> > That's reasonably late, so I'd prefer you did it in xxx_probe().
> 
> Heh, I had it in xxx_probe() originally and then realized that
> 
>   a) the power off function is basically a driver. Driver initialization
> happens in xxx_setup_arch() and
> 
>   b) the maple target already does overwrite its power_off callback in
> xxx_setup_arch and
> 
>   c) on all targets xxx_probe() is very slim and doesn't do much
> 
> but I'll happily change it back to put the bits in xxx_probe() instead.

Thanks.

That way you shouldn't be changing behaviour.

It may still be the case that some power off routines don't actually work until
later, but that's an existing problem. Some power off routines *do* work before
setup_arch(), so they will continue to work.


Also, how does your series interact with Guenter's that removes pm_power_off ?
It seems at the moment they are unaware of each other.

cheers

^ permalink raw reply

* Re: [RFC PATCH v3 1/3] powerpc: Fix warning reported by verify_cpu_node_mapping()
From: Michael Ellerman @ 2014-10-07  6:28 UTC (permalink / raw)
  To: Nishanth Aravamudan; +Cc: paulus, linuxppc-dev, Li Zhong, Nathan Fontenot
In-Reply-To: <20141003232606.GA9339@linux.vnet.ibm.com>

On Fri, 2014-10-03 at 16:26 -0700, Nishanth Aravamudan wrote:
> On 03.10.2014 [10:50:20 +1000], Michael Ellerman wrote:
> > On Thu, 2014-10-02 at 14:13 -0700, Nishanth Aravamudan wrote:
> > > Ben & Michael,
> > > 
> > > What's the status of these patches?
> > 
> > Been in my next for a week :)
> > 
> > https://git.kernel.org/cgit/linux/kernel/git/mpe/linux.git/log/?h=next
> 
> Ah ok, thanks -- I wasn't following your tree, my fault. 

Not really your fault, I hadn't announced my trees existence :)

> Do we want these to go back to 3.17-stable, as they fix some annoying splats
> during boot (non-fatal afaict, though)?

Up to you really, I don't know how often/bad they were. I haven't added CC
stable tags to the commits, so if you want them in stable you should send them
explicitly.

cheers

^ permalink raw reply

* [PATCH v3 2/7] pci/msi: Add device flag indicating that 64-bit MSIs don't work
From: Benjamin Herrenschmidt @ 2014-10-07  4:37 UTC (permalink / raw)
  To: Alex Deucher, Bjorn Helgaas
  Cc: linuxppc-dev, Dave Airlie, linux-pci, Anton Blanchard,
	Yijing Wang, Takashi Iwai, Brian King

This can be set by quirks/drivers to be used by the architecture code
that assigns the MSI addresses.

We additionally add verification in the core MSI code that the values
assigned by the architecture do satisfy the limitation in order to fail
gracefully if they don't (ie. the arch hasn't been updated to deal with
that quirk yet).

Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
CC: <stable@vger.kernel.org>
---
 drivers/pci/msi.c   | 26 ++++++++++++++++++++++++++
 include/linux/pci.h |  1 +
 2 files changed, 27 insertions(+)

diff --git a/drivers/pci/msi.c b/drivers/pci/msi.c
index 5a40516..6807edd 100644
--- a/drivers/pci/msi.c
+++ b/drivers/pci/msi.c
@@ -610,6 +610,20 @@ static struct msi_desc *msi_setup_entry(struct pci_dev *dev)
 	return entry;
 }
 
+static int msi_verify_entries(struct pci_dev *dev)
+{
+	struct msi_desc *entry;
+
+	list_for_each_entry(entry, &dev->msi_list, list) {
+		if (!dev->no_64bit_msi || !entry->msg.address_hi)
+			continue;
+		dev_err(&dev->dev, "Device has broken 64-bit MSI but arch"
+			" tried to assign one above 4G\n");
+		return -EIO;
+	}
+	return 0;
+}
+
 /**
  * msi_capability_init - configure device's MSI capability structure
  * @dev: pointer to the pci_dev data structure of MSI device function
@@ -647,6 +661,13 @@ static int msi_capability_init(struct pci_dev *dev, int nvec)
 		return ret;
 	}
 
+	ret = msi_verify_entries(dev);
+	if (ret) {
+		msi_mask_irq(entry, mask, ~mask);
+		free_msi_irqs(dev);
+		return ret;
+	}
+
 	ret = populate_msi_sysfs(dev);
 	if (ret) {
 		msi_mask_irq(entry, mask, ~mask);
@@ -760,6 +781,11 @@ static int msix_capability_init(struct pci_dev *dev,
 	if (ret)
 		goto out_avail;
 
+	/* Check if all MSI entries honor device restrictions */
+	ret = msi_verify_entries(dev);
+	if (ret)
+		goto out_free;
+
 	/*
 	 * Some devices require MSI-X to be enabled before we can touch the
 	 * MSI-X registers.  We need to mask all the vectors to prevent
diff --git a/include/linux/pci.h b/include/linux/pci.h
index 96453f9..6b6da8f 100644
--- a/include/linux/pci.h
+++ b/include/linux/pci.h
@@ -331,6 +331,7 @@ struct pci_dev {
 	unsigned int	is_added:1;
 	unsigned int	is_busmaster:1; /* device is busmaster */
 	unsigned int	no_msi:1;	/* device may not use msi */
+	unsigned int	no_64bit_msi:1; /* device may only use 32-bit MSIs */
 	unsigned int	block_cfg_access:1;	/* config space access is blocked */
 	unsigned int	broken_parity_status:1;	/* Device generates false positive parity */
 	unsigned int	irq_reroute_variant:2;	/* device needs IRQ rerouting variant */

^ permalink raw reply related

* Re: [PATCH 01/44] kernel: Add support for poweroff handler call chain
From: Philippe Rétornaz @ 2014-10-07  7:46 UTC (permalink / raw)
  To: Guenter Roeck, linux-kernel
  Cc: linux-m32r-ja, linux-mips, linux-efi, linux-ia64, Heiko Stuebner,
	linux-sh, devicetree, Pavel Machek, devel, linux-s390, lguest,
	linux-c6x-dev, linux-hexagon, Alexander Graf, linux-acpi,
	Geert Uytterhoeven, xen-devel, Len Brown, user-mode-linux-devel,
	linux-pm, linux-xtensa, adi-buildroot-devel, linux-m68k,
	linux-am33-list, linux-tegra, openipmi-developer, linux-metag,
	linux-arm-kernel, linux-cris-kernel, linux-parisc,
	Rafael J. Wysocki, linux-alpha, Andrew Morton, Romain Perier,
	linuxppc-dev
In-Reply-To: <1412659726-29957-2-git-send-email-linux@roeck-us.net>

Hello

This seems exactly what I would need on the mc13783 to handle cleanly 
the poweroff,
but after reading this patchset I have the following question:

[...]

> +/*
> + *	Notifier list for kernel code which wants to be called
> + *	to power off the system.
> + */
> +static ATOMIC_NOTIFIER_HEAD(poweroff_handler_list);

[...]

> +void do_kernel_poweroff(void)
> +{
> +	atomic_notifier_call_chain(&poweroff_handler_list, 0, NULL);
> +}
> +

It seems that the poweroff callback needs to be atomic as per
_atomic_notifier_call_chain documentation:

	"Calls each function in a notifier chain in turn.  The functions
	 run in an atomic context"

But this is a problem for many MFD (mc13783, twl4030 etc ...) which are
accessible on only a blocking bus (SPI, I2C).

What I am missing here ?

Thanks,

Philippe

^ permalink raw reply

* Re: [PATCH 18/44] mfd: twl4030-power: Register with kernel poweroff handler
From: Lee Jones @ 2014-10-07  7:52 UTC (permalink / raw)
  To: Guenter Roeck
  Cc: linux-m32r-ja, linux-mips, linux-efi, linux-ia64, linux-xtensa,
	devel, linux-s390, lguest, linux-c6x-dev, linux-hexagon, linux-sh,
	linux-acpi, xen-devel, devicetree, user-mode-linux-devel,
	linux-pm, adi-buildroot-devel, linux-m68k, linux-am33-list,
	linux-tegra, openipmi-developer, linux-metag, linux-arm-kernel,
	Samuel Ortiz, linux-parisc, linux-cris-kernel, linux-kernel,
	linux-alpha, linuxppc-dev
In-Reply-To: <1412659726-29957-19-git-send-email-linux@roeck-us.net>

On Mon, 06 Oct 2014, Guenter Roeck wrote:

> Register with kernel poweroff handler instead of setting pm_power_off
> directly. Register with a low priority value of 64 to reflect that
> the original code only sets pm_power_off if it was not already set.
> 
> Make twl4030_power_off static as it is only called from the twl4030-power
> driver.
> 
> Cc: Samuel Ortiz <sameo@linux.intel.com>
> Cc: Lee Jones <lee.jones@linaro.org>
> Signed-off-by: Guenter Roeck <linux@roeck-us.net>
> ---
>  drivers/mfd/twl4030-power.c | 25 +++++++++++++++++++++----
>  include/linux/i2c/twl.h     |  1 -
>  2 files changed, 21 insertions(+), 5 deletions(-)
> 
> diff --git a/drivers/mfd/twl4030-power.c b/drivers/mfd/twl4030-power.c
> index 4d3ff37..bd6b830 100644
> --- a/drivers/mfd/twl4030-power.c
> +++ b/drivers/mfd/twl4030-power.c
> @@ -25,9 +25,10 @@
>   */
>  
>  #include <linux/module.h>
> -#include <linux/pm.h>
> +#include <linux/notifier.h>
>  #include <linux/i2c/twl.h>
>  #include <linux/platform_device.h>
> +#include <linux/pm.h>
>  #include <linux/of.h>
>  #include <linux/of_device.h>
>  
> @@ -611,7 +612,8 @@ twl4030_power_configure_resources(const struct twl4030_power_data *pdata)
>   * After a successful execution, TWL shuts down the power to the SoC
>   * and all peripherals connected to it.
>   */
> -void twl4030_power_off(void)
> +static int twl4030_power_off(struct notifier_block *this, unsigned long unused1,
> +			     void *unused2)
>  {
>  	int err;
>  
> @@ -619,8 +621,15 @@ void twl4030_power_off(void)
>  			       TWL4030_PM_MASTER_P1_SW_EVENTS);
>  	if (err)
>  		pr_err("TWL4030 Unable to power off\n");
> +
> +	return NOTIFY_DONE;
>  }
>  
> +static struct notifier_block twl4030_poweroff_nb = {
> +	.notifier_call = twl4030_power_off,
> +	.priority = 64,

64 out of what?  How is this calculated?  Wouldn't it be better to
define these?

> +};
> +
>  static bool twl4030_power_use_poweroff(const struct twl4030_power_data *pdata,
>  					struct device_node *node)
>  {
> @@ -836,7 +845,7 @@ static int twl4030_power_probe(struct platform_device *pdev)
>  	}
>  
>  	/* Board has to be wired properly to use this feature */
> -	if (twl4030_power_use_poweroff(pdata, node) && !pm_power_off) {
> +	if (twl4030_power_use_poweroff(pdata, node)) {
>  		/* Default for SEQ_OFFSYNC is set, lets ensure this */
>  		err = twl_i2c_read_u8(TWL_MODULE_PM_MASTER, &val,
>  				      TWL4030_PM_MASTER_CFG_P123_TRANSITION);
> @@ -853,7 +862,13 @@ static int twl4030_power_probe(struct platform_device *pdev)
>  			}
>  		}
>  
> -		pm_power_off = twl4030_power_off;
> +		err = register_poweroff_handler(&twl4030_poweroff_nb);
> +		if (err) {
> +			dev_err(&pdev->dev,
> +				"Failed to register poweroff handler\n");

If this is not fatal, you should issue a dev_warn() instead.

> +			/* Not a fatal error */
> +			err = 0;

How about using your own variable for this?  Then you don't have to
worry about resetting it.

> +		}
>  	}
>  
>  relock:
> @@ -869,6 +884,8 @@ relock:
>  
>  static int twl4030_power_remove(struct platform_device *pdev)
>  {
> +	unregister_poweroff_handler(&twl4030_poweroff_nb);

Perhaps a naive question, but is there any way you can do this using
devres (devm_* managed resources)?

>  	return 0;
>  }
>  
> diff --git a/include/linux/i2c/twl.h b/include/linux/i2c/twl.h
> index 8cfb50f..f8544f1 100644
> --- a/include/linux/i2c/twl.h
> +++ b/include/linux/i2c/twl.h
> @@ -680,7 +680,6 @@ struct twl4030_power_data {
>  };
>  
>  extern int twl4030_remove_script(u8 flags);
> -extern void twl4030_power_off(void);
>  
>  struct twl4030_codec_data {
>  	unsigned int digimic_delay; /* in ms */

-- 
Lee Jones
Linaro STMicroelectronics Landing Team Lead
Linaro.org │ Open source software for ARM SoCs
Follow Linaro: Facebook | Twitter | Blog

^ permalink raw reply


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox