Discussion:
[PATCH 06/44] gpio-poweroff: Drop reference to pm_power_off from devicetree bindings
Guenter Roeck
2014-10-07 05:28:08 UTC
Permalink
pm_power_off is an implementation detail. Replace it with a more generic
description of the driver's functionality.

Cc: Rob Herring <robh+***@kernel.org>
Cc: Pawel Moll <***@arm.com>
Cc: Mark Rutland <***@arm.com>
Signed-off-by: Guenter Roeck <***@roeck-us.net>
---
Documentation/devicetree/bindings/gpio/gpio-poweroff.txt | 10 +++++-----
1 file changed, 5 insertions(+), 5 deletions(-)

diff --git a/Documentation/devicetree/bindings/gpio/gpio-poweroff.txt b/Documentation/devicetree/bindings/gpio/gpio-poweroff.txt
index d4eab92..c95a1a6 100644
--- a/Documentation/devicetree/bindings/gpio/gpio-poweroff.txt
+++ b/Documentation/devicetree/bindings/gpio/gpio-poweroff.txt
@@ -2,12 +2,12 @@ Driver a GPIO line that can be used to turn the power off.

The driver supports both level triggered and edge triggered power off.
At driver load time, the driver will request the given gpio line and
-install a pm_power_off handler. If the optional properties 'input' is
-not found, the GPIO line will be driven in the inactive
+install a handler to power off the system. If the optional properties
+'input' is not found, the GPIO line will be driven in the inactive
state. Otherwise its configured as an input.

-When the pm_power_off is called, the gpio is configured as an output,
-and drive active, so triggering a level triggered power off
+When the the poweroff handler is called, the gpio is configured as an
+output, and drive active, so triggering a level triggered power off
condition. This will also cause an inactive->active edge condition, so
triggering positive edge triggered power off. After a delay of 100ms,
the GPIO is set to inactive, thus causing an active->inactive edge,
@@ -24,7 +24,7 @@ Required properties:

Optional properties:
- input : Initially configure the GPIO line as an input. Only reconfigure
- it to an output when the pm_power_off function is called. If this optional
+ it to an output when the poweroff handler is called. If this optional
property is not specified, the GPIO is initialized as an output in its
inactive state.
--
1.9.1
Guenter Roeck
2014-10-07 05:28:28 UTC
Permalink
Register with kernel poweroff handler instead of setting pm_power_off
directly. Register with high priority value of 192 to reflect that
the original code overwrites existing poweroff handlers.

Cc: Thomas Gleixner <***@linutronix.de>
Cc: Ingo Molnar <***@redhat.com>
Cc: H. Peter Anvin <***@zytor.com>
Signed-off-by: Guenter Roeck <***@roeck-us.net>
---
arch/x86/platform/iris/iris.c | 25 +++++++++++++++++++------
1 file changed, 19 insertions(+), 6 deletions(-)

diff --git a/arch/x86/platform/iris/iris.c b/arch/x86/platform/iris/iris.c
index 4d171e8..662c4e8 100644
--- a/arch/x86/platform/iris/iris.c
+++ b/arch/x86/platform/iris/iris.c
@@ -23,6 +23,7 @@

#include <linux/moduleparam.h>
#include <linux/module.h>
+#include <linux/notifier.h>
#include <linux/platform_device.h>
#include <linux/kernel.h>
#include <linux/errno.h>
@@ -47,15 +48,21 @@ static bool force;
module_param(force, bool, 0);
MODULE_PARM_DESC(force, "Set to one to force poweroff handler installation.");

-static void (*old_pm_power_off)(void);
-
-static void iris_power_off(void)
+static int iris_power_off(struct notifier_block *this, unsigned long unused1,
+ void *unused2)
{
outb(IRIS_GIO_PULSE, IRIS_GIO_OUTPUT);
msleep(850);
outb(IRIS_GIO_REST, IRIS_GIO_OUTPUT);
+
+ return NOTIFY_DONE;
}

+static struct notifier_block iris_poweroff_nb = {
+ .notifier_call = iris_power_off,
+ .priority = 192,
+};
+
/*
* Before installing the power_off handler, try to make sure the OS is
* running on an Iris. Since Iris does not support DMI, this is done
@@ -65,20 +72,26 @@ static void iris_power_off(void)
static int iris_probe(struct platform_device *pdev)
{
unsigned char status = inb(IRIS_GIO_INPUT);
+ int ret;
+
if (status == IRIS_GIO_NODEV) {
printk(KERN_ERR "This machine does not seem to be an Iris. "
"Power off handler not installed.\n");
return -ENODEV;
}
- old_pm_power_off = pm_power_off;
- pm_power_off = &iris_power_off;
+
+ ret = register_poweroff_handler(&iris_poweroff_nb);
+ if (ret) {
+ dev_err(&pdev->dev, "Failed to register poweroff handler\n");
+ return ret;
+ }
printk(KERN_INFO "Iris power_off handler installed.\n");
return 0;
}

static int iris_remove(struct platform_device *pdev)
{
- pm_power_off = old_pm_power_off;
+ unregister_poweroff_handler(&iris_poweroff_nb);
printk(KERN_INFO "Iris power_off handler uninstalled.\n");
return 0;
}
--
1.9.1
Guenter Roeck
2014-10-07 05:28:25 UTC
Permalink
Register with kernel poweroff handler instead of setting pm_power_off
directly. Register with default priority value of 128 to reflect that
the original code generates an error if another poweroff handler has
already been registered when the driver is loaded.

Cc: Sebastian Reichel <***@kernel.org>
Cc: Dmitry Eremin-Solenikov <***@gmail.com>
Cc: David Woodhouse <***@infradead.org>
Signed-off-by: Guenter Roeck <***@roeck-us.net>
---
drivers/power/reset/qnap-poweroff.c | 28 ++++++++++++++--------------
1 file changed, 14 insertions(+), 14 deletions(-)

diff --git a/drivers/power/reset/qnap-poweroff.c b/drivers/power/reset/qnap-poweroff.c
index a75db7f..c474980 100644
--- a/drivers/power/reset/qnap-poweroff.c
+++ b/drivers/power/reset/qnap-poweroff.c
@@ -16,7 +16,9 @@

#include <linux/kernel.h>
#include <linux/module.h>
+#include <linux/notifier.h>
#include <linux/platform_device.h>
+#include <linux/pm.h>
#include <linux/serial_reg.h>
#include <linux/kallsyms.h>
#include <linux/of.h>
@@ -55,7 +57,8 @@ static void __iomem *base;
static unsigned long tclk;
static const struct power_off_cfg *cfg;

-static void qnap_power_off(void)
+static int qnap_power_off(struct notifier_block *this, unsigned long unused1,
+ void *unused2)
{
const unsigned divisor = ((tclk + (8 * cfg->baud)) / (16 * cfg->baud));

@@ -72,14 +75,20 @@ static void qnap_power_off(void)

/* send the power-off command to PIC */
writel(cfg->cmd, UART1_REG(TX));
+
+ return NOTIFY_DONE;
}

+static struct notifier_block qnap_poweroff_nb = {
+ .notifier_call = qnap_power_off,
+ .priority = 128,
+};
+
static int qnap_power_off_probe(struct platform_device *pdev)
{
struct device_node *np = pdev->dev.of_node;
struct resource *res;
struct clk *clk;
- char symname[KSYM_NAME_LEN];

const struct of_device_id *match =
of_match_node(qnap_power_off_of_match_table, np);
@@ -106,22 +115,13 @@ static int qnap_power_off_probe(struct platform_device *pdev)

tclk = clk_get_rate(clk);

- /* Check that nothing else has already setup a handler */
- if (pm_power_off) {
- lookup_symbol_name((ulong)pm_power_off, symname);
- dev_err(&pdev->dev,
- "pm_power_off already claimed %p %s",
- pm_power_off, symname);
- return -EBUSY;
- }
- pm_power_off = qnap_power_off;
-
- return 0;
+ return register_poweroff_handler(&qnap_poweroff_nb);
}

static int qnap_power_off_remove(struct platform_device *pdev)
{
- pm_power_off = NULL;
+ unregister_poweroff_handler(&qnap_poweroff_nb);
+
return 0;
}
--
1.9.1
Andrew Lunn
2014-10-07 16:02:08 UTC
Permalink
Post by Guenter Roeck
Register with kernel poweroff handler instead of setting pm_power_off
directly. Register with default priority value of 128 to reflect that
the original code generates an error if another poweroff handler has
already been registered when the driver is loaded.
Acked-by: Andrew Lunn <***@lunn.ch>

Thanks
Andrew
Post by Guenter Roeck
---
drivers/power/reset/qnap-poweroff.c | 28 ++++++++++++++--------------
1 file changed, 14 insertions(+), 14 deletions(-)
diff --git a/drivers/power/reset/qnap-poweroff.c b/drivers/power/reset/qnap-poweroff.c
index a75db7f..c474980 100644
--- a/drivers/power/reset/qnap-poweroff.c
+++ b/drivers/power/reset/qnap-poweroff.c
@@ -16,7 +16,9 @@
#include <linux/kernel.h>
#include <linux/module.h>
+#include <linux/notifier.h>
#include <linux/platform_device.h>
+#include <linux/pm.h>
#include <linux/serial_reg.h>
#include <linux/kallsyms.h>
#include <linux/of.h>
@@ -55,7 +57,8 @@ static void __iomem *base;
static unsigned long tclk;
static const struct power_off_cfg *cfg;
-static void qnap_power_off(void)
+static int qnap_power_off(struct notifier_block *this, unsigned long unused1,
+ void *unused2)
{
const unsigned divisor = ((tclk + (8 * cfg->baud)) / (16 * cfg->baud));
@@ -72,14 +75,20 @@ static void qnap_power_off(void)
/* send the power-off command to PIC */
writel(cfg->cmd, UART1_REG(TX));
+
+ return NOTIFY_DONE;
}
+static struct notifier_block qnap_poweroff_nb = {
+ .notifier_call = qnap_power_off,
+ .priority = 128,
+};
+
static int qnap_power_off_probe(struct platform_device *pdev)
{
struct device_node *np = pdev->dev.of_node;
struct resource *res;
struct clk *clk;
- char symname[KSYM_NAME_LEN];
const struct of_device_id *match =
of_match_node(qnap_power_off_of_match_table, np);
@@ -106,22 +115,13 @@ static int qnap_power_off_probe(struct platform_device *pdev)
tclk = clk_get_rate(clk);
- /* Check that nothing else has already setup a handler */
- if (pm_power_off) {
- lookup_symbol_name((ulong)pm_power_off, symname);
- dev_err(&pdev->dev,
- "pm_power_off already claimed %p %s",
- pm_power_off, symname);
- return -EBUSY;
- }
- pm_power_off = qnap_power_off;
-
- return 0;
+ return register_poweroff_handler(&qnap_poweroff_nb);
}
static int qnap_power_off_remove(struct platform_device *pdev)
{
- pm_power_off = NULL;
+ unregister_poweroff_handler(&qnap_poweroff_nb);
+
return 0;
}
--
1.9.1
_______________________________________________
linux-arm-kernel mailing list
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
Guenter Roeck
2014-10-07 05:28:04 UTC
Permalink
Use have_kernel_poweroff() to determine if the kernel is able
to power off the system.

Cc: Santosh Shilimkar <***@ti.com>
Signed-off-by: Guenter Roeck <***@roeck-us.net>
---
drivers/memory/emif.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/memory/emif.c b/drivers/memory/emif.c
index 04644e7..acd830a 100644
--- a/drivers/memory/emif.c
+++ b/drivers/memory/emif.c
@@ -1053,10 +1053,10 @@ static irqreturn_t emif_threaded_isr(int irq, void *dev_id)
dev_emerg(emif->dev, "SDRAM temperature exceeds operating limit.. Needs shut down!!!\n");

/* If we have Power OFF ability, use it, else try restarting */
- if (pm_power_off) {
+ if (have_kernel_poweroff()) {
kernel_power_off();
} else {
- WARN(1, "FIXME: NO pm_power_off!!! trying restart\n");
+ WARN(1, "FIXME: NO kernel poweroff capability!!! trying restart\n");
kernel_restart("SDRAM Over-temp Emergency restart");
}
return IRQ_HANDLED;
--
1.9.1
Guenter Roeck
2014-10-07 05:28:11 UTC
Permalink
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: Samuel Ortiz <***@linux.intel.com>
Cc: Lee Jones <***@linaro.org>
Signed-off-by: Guenter Roeck <***@roeck-us.net>
---
drivers/mfd/palmas.c | 30 +++++++++++++++++-------------
include/linux/mfd/palmas.h | 3 +++
2 files changed, 20 insertions(+), 13 deletions(-)

diff --git a/drivers/mfd/palmas.c b/drivers/mfd/palmas.c
index 28cb048..4d78847 100644
--- a/drivers/mfd/palmas.c
+++ b/drivers/mfd/palmas.c
@@ -19,6 +19,7 @@
#include <linux/i2c.h>
#include <linux/interrupt.h>
#include <linux/irq.h>
+#include <linux/pm.h>
#include <linux/regmap.h>
#include <linux/err.h>
#include <linux/mfd/core.h>
@@ -425,20 +426,18 @@ static void palmas_dt_to_pdata(struct i2c_client *i2c,
"ti,system-power-controller");
}

-static struct palmas *palmas_dev;
-static void palmas_power_off(void)
+static int palmas_power_off(struct notifier_block *this, unsigned long unused1,
+ void *unused2)
{
+ struct palmas *palmas = container_of(this, struct palmas, poweroff_nb);
unsigned int addr;
int ret, slave;

- if (!palmas_dev)
- return;
-
slave = PALMAS_BASE_TO_SLAVE(PALMAS_PMU_CONTROL_BASE);
addr = PALMAS_BASE_TO_REG(PALMAS_PMU_CONTROL_BASE, PALMAS_DEV_CTRL);

ret = regmap_update_bits(
- palmas_dev->regmap[slave],
+ palmas->regmap[slave],
addr,
PALMAS_DEV_CTRL_DEV_ON,
0);
@@ -446,6 +445,8 @@ static void palmas_power_off(void)
if (ret)
pr_err("%s: Unable to write to DEV_CTRL_DEV_ON: %d\n",
__func__, ret);
+
+ return NOTIFY_DONE;
}

static unsigned int palmas_features = PALMAS_PMIC_FEATURE_SMPS10_BOOST;
@@ -668,9 +669,15 @@ no_irq:
ret = of_platform_populate(node, NULL, NULL, &i2c->dev);
if (ret < 0) {
goto err_irq;
- } else if (pdata->pm_off && !pm_power_off) {
- palmas_dev = palmas;
- pm_power_off = palmas_power_off;
+ } else if (pdata->pm_off) {
+ palmas->poweroff_nb.notifier_call = palmas_power_off;
+ palmas->poweroff_nb.priority = 64;
+ ret = register_poweroff_handler(&palmas->poweroff_nb);
+ if (ret) {
+ dev_err(palmas->dev,
+ "Failed to register poweroff handler");
+ ret = 0;
+ }
}
}

@@ -698,10 +705,7 @@ static int palmas_i2c_remove(struct i2c_client *i2c)
i2c_unregister_device(palmas->i2c_clients[i]);
}

- if (palmas == palmas_dev) {
- pm_power_off = NULL;
- palmas_dev = NULL;
- }
+ unregister_poweroff_handler(&palmas->poweroff_nb);

return 0;
}
diff --git a/include/linux/mfd/palmas.h b/include/linux/mfd/palmas.h
index fb0390a..4715057 100644
--- a/include/linux/mfd/palmas.h
+++ b/include/linux/mfd/palmas.h
@@ -18,6 +18,7 @@

#include <linux/usb/otg.h>
#include <linux/leds.h>
+#include <linux/notifier.h>
#include <linux/regmap.h>
#include <linux/regulator/driver.h>
#include <linux/extcon.h>
@@ -68,6 +69,8 @@ struct palmas {
struct i2c_client *i2c_clients[PALMAS_NUM_CLIENTS];
struct regmap *regmap[PALMAS_NUM_CLIENTS];

+ struct notifier_block poweroff_nb;
+
/* Stored chip id */
int id;
--
1.9.1
Guenter Roeck
2014-10-07 05:28:30 UTC
Permalink
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 <***@linutronix.de>
Cc: Ingo Molnar <***@redhat.com>
Cc: H. Peter Anvin <***@zytor.com>
Signed-off-by: Guenter Roeck <***@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
Guenter Roeck
2014-10-07 05:28:32 UTC
Permalink
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 <***@rjwysocki.net>
Cc: Len Brown <***@kernel.org>
Signed-off-by: Guenter Roeck <***@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
Guenter Roeck
2014-10-07 05:28:31 UTC
Permalink
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-linux.org>
Cc: Marc Dietrich <***@gmx.de>
Cc: Greg Kroah-Hartman <***@linuxfoundation.org>
Signed-off-by: Guenter Roeck <***@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
Greg Kroah-Hartman
2014-10-07 16:23:06 UTC
Permalink
Post by Guenter Roeck
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.
---
drivers/staging/nvec/nvec.c | 24 +++++++++++++++---------
drivers/staging/nvec/nvec.h | 2 ++
2 files changed, 17 insertions(+), 9 deletions(-)
Acked-by: Greg Kroah-Hartman <***@linuxfoundation.org>
Guenter Roeck
2014-10-07 05:28:29 UTC
Permalink
Register with kernel poweroff handler instead of setting pm_power_off
directly. Register with high priority value of 192 to reflect that
the original code overwrites existing poweroff handlers.

Cc: Thomas Gleixner <***@linutronix.de>
Cc: Ingo Molnar <***@redhat.com>
Cc: H. Peter Anvin <***@zytor.com>
Cc: Jiri Kosina <***@suse.cz>
Signed-off-by: Guenter Roeck <***@roeck-us.net>
---
arch/x86/kernel/apm_32.c | 20 +++++++++++++++-----
1 file changed, 15 insertions(+), 5 deletions(-)

diff --git a/arch/x86/kernel/apm_32.c b/arch/x86/kernel/apm_32.c
index 5848744..84566a6 100644
--- a/arch/x86/kernel/apm_32.c
+++ b/arch/x86/kernel/apm_32.c
@@ -219,6 +219,7 @@
#include <linux/init.h>
#include <linux/time.h>
#include <linux/sched.h>
+#include <linux/notifier.h>
#include <linux/pm.h>
#include <linux/capability.h>
#include <linux/device.h>
@@ -981,7 +982,8 @@ recalc:
* on their first cpu.
*/

-static void apm_power_off(void)
+static int apm_power_off(struct notifier_block *this, unsigned long unused1,
+ void *unused2)
{
/* Some bioses don't like being called from CPU != 0 */
if (apm_info.realmode_power_off) {
@@ -990,8 +992,14 @@ static void apm_power_off(void)
} else {
(void)set_system_power_state(APM_STATE_OFF);
}
+ return NOTIFY_DONE;
}

+static struct notifier_block apm_poweroff_nb = {
+ .notifier_call = apm_power_off,
+ .priority = 192,
+};
+
#ifdef CONFIG_APM_DO_ENABLE

/**
@@ -1847,8 +1855,11 @@ static int apm(void *unused)
}

/* Install our power off handler.. */
- if (power_off)
- pm_power_off = apm_power_off;
+ if (power_off) {
+ error = register_poweroff_handler(&apm_poweroff_nb);
+ if (error)
+ pr_err("apm: Failed to register poweroff handler\n");
+ }

if (num_online_cpus() == 1 || smp) {
#if defined(CONFIG_APM_DISPLAY_BLANK) && defined(CONFIG_VT)
@@ -2408,9 +2419,8 @@ static void __exit apm_exit(void)
apm_error("disengage power management", error);
}
misc_deregister(&apm_device);
+ unregister_poweroff_handler(&apm_poweroff_nb);
remove_proc_entry("apm", NULL);
- if (power_off)
- pm_power_off = NULL;
if (kapmd_task) {
kthread_stop(kapmd_task);
kapmd_task = NULL;
--
1.9.1
Guenter Roeck
2014-10-07 05:28:16 UTC
Permalink
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: Samuel Ortiz <***@linux.intel.com>
Cc: Lee Jones <***@linaro.org>
Signed-off-by: Guenter Roeck <***@roeck-us.net>
---
drivers/mfd/tps80031.c | 30 ++++++++++++++++++------------
include/linux/mfd/tps80031.h | 2 ++
2 files changed, 20 insertions(+), 12 deletions(-)

diff --git a/drivers/mfd/tps80031.c b/drivers/mfd/tps80031.c
index ed6c5b0..24625a6 100644
--- a/drivers/mfd/tps80031.c
+++ b/drivers/mfd/tps80031.c
@@ -147,7 +147,6 @@ static const struct tps80031_pupd_data tps80031_pupds[] = {
[TPS80031_CTLI2C_SCL] = PUPD_DATA(4, 0, BIT(2)),
[TPS80031_CTLI2C_SDA] = PUPD_DATA(4, 0, BIT(3)),
};
-static struct tps80031 *tps80031_power_off_dev;

int tps80031_ext_power_req_config(struct device *dev,
unsigned long ext_ctrl_flag, int preq_bit,
@@ -209,11 +208,17 @@ int tps80031_ext_power_req_config(struct device *dev,
}
EXPORT_SYMBOL_GPL(tps80031_ext_power_req_config);

-static void tps80031_power_off(void)
+static int tps80031_power_off(struct notifier_block *this,
+ unsigned long unused1, void *unused2)
{
- dev_info(tps80031_power_off_dev->dev, "switching off PMU\n");
- tps80031_write(tps80031_power_off_dev->dev, TPS80031_SLAVE_ID1,
- TPS80031_PHOENIX_DEV_ON, TPS80031_DEVOFF);
+ struct tps80031 *tps80031 = container_of(this, struct tps80031,
+ poweroff_nb);
+
+ dev_info(tps80031->dev, "switching off PMU\n");
+ tps80031_write(tps80031->dev, TPS80031_SLAVE_ID1,
+ TPS80031_PHOENIX_DEV_ON, TPS80031_DEVOFF);
+
+ return NOTIFY_DONE;
}

static void tps80031_pupd_init(struct tps80031 *tps80031,
@@ -501,9 +506,13 @@ static int tps80031_probe(struct i2c_client *client,
goto fail_mfd_add;
}

- if (pdata->use_power_off && !pm_power_off) {
- tps80031_power_off_dev = tps80031;
- pm_power_off = tps80031_power_off;
+ if (pdata->use_power_off) {
+ tps80031->poweroff_nb.notifier_call = tps80031_power_off;
+ tps80031->poweroff_nb.priority = 64;
+ ret = register_poweroff_handler(&tps80031->poweroff_nb);
+ if (ret)
+ dev_err(&client->dev,
+ "Failed to register poweroff handler\n");
}
return 0;

@@ -523,10 +532,7 @@ static int tps80031_remove(struct i2c_client *client)
struct tps80031 *tps80031 = i2c_get_clientdata(client);
int i;

- if (tps80031_power_off_dev == tps80031) {
- tps80031_power_off_dev = NULL;
- pm_power_off = NULL;
- }
+ unregister_poweroff_handler(&tps80031->poweroff_nb);

mfd_remove_devices(tps80031->dev);

diff --git a/include/linux/mfd/tps80031.h b/include/linux/mfd/tps80031.h
index 2c75c9c..49bc006 100644
--- a/include/linux/mfd/tps80031.h
+++ b/include/linux/mfd/tps80031.h
@@ -24,6 +24,7 @@
#define __LINUX_MFD_TPS80031_H

#include <linux/device.h>
+#include <linux/notifier.h>
#include <linux/regmap.h>

/* Pull-ups/Pull-downs */
@@ -513,6 +514,7 @@ struct tps80031 {
struct i2c_client *clients[TPS80031_NUM_SLAVES];
struct regmap *regmap[TPS80031_NUM_SLAVES];
struct regmap_irq_chip_data *irq_data;
+ struct notifier_block poweroff_nb;
};

struct tps80031_pupd_init_data {
--
1.9.1
Guenter Roeck
2014-10-07 05:28:36 UTC
Permalink
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 <***@intel.com>
Cc: Fenghua Yu <***@intel.com>
Signed-off-by: Guenter Roeck <***@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
Guenter Roeck
2014-10-07 05:28:34 UTC
Permalink
Register with kernel poweroff handler instead of setting pm_power_off
directly.

Cc: Catalin Marinas <***@arm.com>
Cc: Will Deacon <***@arm.com>
Signed-off-by: Guenter Roeck <***@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
Guenter Roeck
2014-10-07 05:28:35 UTC
Permalink
Register with kernel poweroff handler instead of setting pm_power_off
directly.

Cc: Haavard Skinnemoen <***@gmail.com>
Cc: Hans-Christian Egtvedt <***@samfundet.no>
Signed-off-by: Guenter Roeck <***@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
Guenter Roeck
2014-10-07 05:28:15 UTC
Permalink
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.

Note that this patch fixes a problem on driver unload as side effect:
The old code did not restore or clean up pm_power_off on remove,
meaning the pointer was left in an undefined state.

Cc: Lee Jones <***@linaro.org>
Cc: Samuel Ortiz <***@linux.intel.com>
Signed-off-by: Guenter Roeck <***@roeck-us.net>
---
drivers/mfd/max8907.c | 24 ++++++++++++++++++------
include/linux/mfd/max8907.h | 2 ++
2 files changed, 20 insertions(+), 6 deletions(-)

diff --git a/drivers/mfd/max8907.c b/drivers/mfd/max8907.c
index 232749c..b8cddc1 100644
--- a/drivers/mfd/max8907.c
+++ b/drivers/mfd/max8907.c
@@ -19,6 +19,7 @@
#include <linux/module.h>
#include <linux/of.h>
#include <linux/of_device.h>
+#include <linux/pm.h>
#include <linux/regmap.h>
#include <linux/slab.h>

@@ -177,11 +178,16 @@ static const struct regmap_irq_chip max8907_rtc_irq_chip = {
.num_irqs = ARRAY_SIZE(max8907_rtc_irqs),
};

-static struct max8907 *max8907_pm_off;
-static void max8907_power_off(void)
+static int max8907_power_off(struct notifier_block *this, unsigned long unused1,
+ void *unused2)
{
- regmap_update_bits(max8907_pm_off->regmap_gen, MAX8907_REG_RESET_CNFG,
+ struct max8907 *max8907 = container_of(this, struct max8907,
+ poweroff_nb);
+
+ regmap_update_bits(max8907->regmap_gen, MAX8907_REG_RESET_CNFG,
MAX8907_MASK_POWER_OFF, MAX8907_MASK_POWER_OFF);
+
+ return NOTIFY_DONE;
}

static int max8907_i2c_probe(struct i2c_client *i2c,
@@ -267,9 +273,13 @@ static int max8907_i2c_probe(struct i2c_client *i2c,
goto err_add_devices;
}

- if (pm_off && !pm_power_off) {
- max8907_pm_off = max8907;
- pm_power_off = max8907_power_off;
+ if (pm_off) {
+ max8907->poweroff_nb.notifier_call = max8907_power_off;
+ max8907->poweroff_nb.priority = 64;
+ ret = register_poweroff_handler(&max8907->poweroff_nb);
+ if (ret)
+ dev_err(&i2c->dev,
+ "Failed to register poweroff handler");
}

return 0;
@@ -293,6 +303,8 @@ static int max8907_i2c_remove(struct i2c_client *i2c)
{
struct max8907 *max8907 = i2c_get_clientdata(i2c);

+ unregister_poweroff_handler(&max8907->poweroff_nb);
+
mfd_remove_devices(max8907->dev);

regmap_del_irq_chip(max8907->i2c_gen->irq, max8907->irqc_rtc);
diff --git a/include/linux/mfd/max8907.h b/include/linux/mfd/max8907.h
index b06f7a6..016428e 100644
--- a/include/linux/mfd/max8907.h
+++ b/include/linux/mfd/max8907.h
@@ -13,6 +13,7 @@
#define __LINUX_MFD_MAX8907_H

#include <linux/mutex.h>
+#include <linux/notifier.h>
#include <linux/pm.h>

#define MAX8907_GEN_I2C_ADDR (0x78 >> 1)
@@ -247,6 +248,7 @@ struct max8907 {
struct regmap_irq_chip_data *irqc_chg;
struct regmap_irq_chip_data *irqc_on_off;
struct regmap_irq_chip_data *irqc_rtc;
+ struct notifier_block poweroff_nb;
};

#endif
--
1.9.1
Guenter Roeck
2014-10-07 05:28:17 UTC
Permalink
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: Samuel Ortiz <***@linux.intel.com>
Cc: Lee Jones <***@linaro.org>
Signed-off-by: Guenter Roeck <***@roeck-us.net>
---
drivers/mfd/dm355evm_msp.c | 18 +++++++++++++++---
1 file changed, 15 insertions(+), 3 deletions(-)

diff --git a/drivers/mfd/dm355evm_msp.c b/drivers/mfd/dm355evm_msp.c
index 4c826f7..52a82f3 100644
--- a/drivers/mfd/dm355evm_msp.c
+++ b/drivers/mfd/dm355evm_msp.c
@@ -14,6 +14,8 @@
#include <linux/platform_device.h>
#include <linux/clk.h>
#include <linux/module.h>
+#include <linux/notifier.h>
+#include <linux/pm.h>
#include <linux/err.h>
#include <linux/gpio.h>
#include <linux/leds.h>
@@ -352,14 +354,22 @@ static void dm355evm_command(unsigned command)
command, status);
}

-static void dm355evm_power_off(void)
+static int dm355evm_power_off(struct notifier_block *this,
+ unsigned long unused1, void *unused2)
{
dm355evm_command(MSP_COMMAND_POWEROFF);
+
+ return NOTIFY_DONE;
}

+static struct notifier_block dm355evm_msp_poweroff_nb = {
+ .notifier_call = dm355evm_power_off,
+ .priority = 64,
+};
+
static int dm355evm_msp_remove(struct i2c_client *client)
{
- pm_power_off = NULL;
+ unregister_poweroff_handler(&dm355evm_msp_poweroff_nb);
msp430 = NULL;
return 0;
}
@@ -398,7 +408,9 @@ dm355evm_msp_probe(struct i2c_client *client, const struct i2c_device_id *id)
goto fail;

/* PM hookup */
- pm_power_off = dm355evm_power_off;
+ status = register_poweroff_handler(&dm355evm_msp_poweroff_nb);
+ if (status)
+ dev_err(&client->dev, "Failed to register poweroff handler\n");

return 0;
--
1.9.1
Guenter Roeck
2014-10-07 05:28:13 UTC
Permalink
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: Lee Jones <***@linaro.org>
Cc: Samuel Ortiz <***@linux.intel.com>
Signed-off-by: Guenter Roeck <***@roeck-us.net>
---
drivers/mfd/retu-mfd.c | 33 +++++++++++++++++++--------------
1 file changed, 19 insertions(+), 14 deletions(-)

diff --git a/drivers/mfd/retu-mfd.c b/drivers/mfd/retu-mfd.c
index 663f8a3..64b60fa 100644
--- a/drivers/mfd/retu-mfd.c
+++ b/drivers/mfd/retu-mfd.c
@@ -22,6 +22,8 @@
#include <linux/slab.h>
#include <linux/mutex.h>
#include <linux/module.h>
+#include <linux/notifier.h>
+#include <linux/pm.h>
#include <linux/regmap.h>
#include <linux/mfd/core.h>
#include <linux/mfd/retu.h>
@@ -43,6 +45,7 @@ struct retu_dev {
struct device *dev;
struct mutex mutex;
struct regmap_irq_chip_data *irq_data;
+ struct notifier_block poweroff_nb;
};

static struct resource retu_pwrbutton_res[] = {
@@ -81,9 +84,6 @@ static struct regmap_irq_chip retu_irq_chip = {
.ack_base = RETU_REG_IDR,
};

-/* Retu device registered for the power off. */
-static struct retu_dev *retu_pm_power_off;
-
static struct resource tahvo_usb_res[] = {
{
.name = "tahvo-usb",
@@ -165,12 +165,14 @@ int retu_write(struct retu_dev *rdev, u8 reg, u16 data)
}
EXPORT_SYMBOL_GPL(retu_write);

-static void retu_power_off(void)
+static int retu_power_off(struct notifier_block *this, unsigned long unused1,
+ void *unused2)
{
- struct retu_dev *rdev = retu_pm_power_off;
+ struct retu_dev *rdev = container_of(this, struct retu_dev,
+ poweroff_nb);
int reg;

- mutex_lock(&retu_pm_power_off->mutex);
+ mutex_lock(&rdev->mutex);

/* Ignore power button state */
regmap_read(rdev->regmap, RETU_REG_CC1, &reg);
@@ -183,7 +185,9 @@ static void retu_power_off(void)
for (;;)
cpu_relax();

- mutex_unlock(&retu_pm_power_off->mutex);
+ mutex_unlock(&rdev->mutex);
+
+ return NOTIFY_DONE;
}

static int retu_regmap_read(void *context, const void *reg, size_t reg_size,
@@ -279,9 +283,13 @@ static int retu_probe(struct i2c_client *i2c, const struct i2c_device_id *id)
return ret;
}

- if (i2c->addr == 1 && !pm_power_off) {
- retu_pm_power_off = rdev;
- pm_power_off = retu_power_off;
+ if (i2c->addr == 1) {
+ rdev->poweroff_nb.notifier_call = retu_power_off;
+ rdev->poweroff_nb.priority = 64;
+ ret = register_poweroff_handler(&rdev->poweroff_nb);
+ if (ret)
+ dev_err(rdev->dev,
+ "Failed to register poweroff handler\n");
}

return 0;
@@ -291,10 +299,7 @@ static int retu_remove(struct i2c_client *i2c)
{
struct retu_dev *rdev = i2c_get_clientdata(i2c);

- if (retu_pm_power_off == rdev) {
- pm_power_off = NULL;
- retu_pm_power_off = NULL;
- }
+ unregister_poweroff_handler(&rdev->poweroff_nb);
mfd_remove_devices(rdev->dev);
regmap_del_irq_chip(i2c->irq, rdev->irq_data);
--
1.9.1
Guenter Roeck
2014-10-07 05:28:21 UTC
Permalink
Register with kernel poweroff handler instead of setting pm_power_off
directly. Register with a high priority value of 192 to reflect that
the original code overwrites pm_power_off unconditionally.

Register poweroff handler after the ipmi system is ready, and unregister
it prior to cleanup. This avoids having to check for the ready variable
in the poweroff callback.

Cc: Corey Minyard <***@acm.org>
Signed-off-by: Guenter Roeck <***@roeck-us.net>
---
drivers/char/ipmi/ipmi_poweroff.c | 30 +++++++++++++++++++-----------
1 file changed, 19 insertions(+), 11 deletions(-)

diff --git a/drivers/char/ipmi/ipmi_poweroff.c b/drivers/char/ipmi/ipmi_poweroff.c
index 9f2e3be..a942a41 100644
--- a/drivers/char/ipmi/ipmi_poweroff.c
+++ b/drivers/char/ipmi/ipmi_poweroff.c
@@ -36,6 +36,7 @@
#include <linux/proc_fs.h>
#include <linux/string.h>
#include <linux/completion.h>
+#include <linux/notifier.h>
#include <linux/pm.h>
#include <linux/kdev_t.h>
#include <linux/ipmi.h>
@@ -63,9 +64,6 @@ static ipmi_user_t ipmi_user;
static int ipmi_ifnum;
static void (*specific_poweroff_func)(ipmi_user_t user);

-/* Holds the old poweroff function so we can restore it on removal. */
-static void (*old_poweroff_func)(void);
-
static int set_param_ifnum(const char *val, struct kernel_param *kp)
{
int rv = param_set_int(val, kp);
@@ -544,15 +542,20 @@ static struct poweroff_function poweroff_functions[] = {


/* Called on a powerdown request. */
-static void ipmi_poweroff_function(void)
+static int ipmi_poweroff_function(struct notifier_block *this,
+ unsigned long unused1, void *unused2)
{
- if (!ready)
- return;
-
/* Use run-to-completion mode, since interrupts may be off. */
specific_poweroff_func(ipmi_user);
+
+ return NOTIFY_DONE;
}

+static struct notifier_block ipmi_poweroff_nb = {
+ .notifier_call = ipmi_poweroff_function,
+ .priority = 192,
+};
+
/* Wait for an IPMI interface to be installed, the first one installed
will be grabbed by this code and used to perform the powerdown. */
static void ipmi_po_new_smi(int if_num, struct device *device)
@@ -631,9 +634,12 @@ static void ipmi_po_new_smi(int if_num, struct device *device)
printk(KERN_INFO PFX "Found a %s style poweroff function\n",
poweroff_functions[i].platform_type);
specific_poweroff_func = poweroff_functions[i].poweroff_func;
- old_poweroff_func = pm_power_off;
- pm_power_off = ipmi_poweroff_function;
+
ready = 1;
+
+ rv = register_poweroff_handler(&ipmi_poweroff_nb);
+ if (rv)
+ pr_err(PFX "failed to register poweroff handler\n");
}

static void ipmi_po_smi_gone(int if_num)
@@ -644,9 +650,10 @@ static void ipmi_po_smi_gone(int if_num)
if (ipmi_ifnum != if_num)
return;

+ unregister_poweroff_handler(&ipmi_poweroff_nb);
+
ready = 0;
ipmi_destroy_user(ipmi_user);
- pm_power_off = old_poweroff_func;
}

static struct ipmi_smi_watcher smi_watcher = {
@@ -732,12 +739,13 @@ static void __exit ipmi_poweroff_cleanup(void)

ipmi_smi_watcher_unregister(&smi_watcher);

+ unregister_poweroff_handler(&ipmi_poweroff_nb);
+
if (ready) {
rv = ipmi_destroy_user(ipmi_user);
if (rv)
printk(KERN_ERR PFX "could not cleanup the IPMI"
" user: 0x%x\n", rv);
- pm_power_off = old_poweroff_func;
}
}
module_exit(ipmi_poweroff_cleanup);
--
1.9.1
Guenter Roeck
2014-10-07 05:28:19 UTC
Permalink
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: Samuel Ortiz <***@linux.intel.com>
Cc: Lee Jones <***@linaro.org>
Signed-off-by: Guenter Roeck <***@roeck-us.net>
---
drivers/mfd/tps65910.c | 27 ++++++++++++++++++---------
include/linux/mfd/tps65910.h | 3 +++
2 files changed, 21 insertions(+), 9 deletions(-)

diff --git a/drivers/mfd/tps65910.c b/drivers/mfd/tps65910.c
index f243e75..0b114d3 100644
--- a/drivers/mfd/tps65910.c
+++ b/drivers/mfd/tps65910.c
@@ -23,6 +23,8 @@
#include <linux/irq.h>
#include <linux/irqdomain.h>
#include <linux/mfd/core.h>
+#include <linux/notifier.h>
+#include <linux/pm.h>
#include <linux/regmap.h>
#include <linux/mfd/tps65910.h>
#include <linux/of.h>
@@ -437,19 +439,20 @@ struct tps65910_board *tps65910_parse_dt(struct i2c_client *client,
}
#endif

-static struct i2c_client *tps65910_i2c_client;
-static void tps65910_power_off(void)
+static int tps65910_power_off(struct notifier_block *this,
+ unsigned long unused1, void *unused2)
{
- struct tps65910 *tps65910;
-
- tps65910 = dev_get_drvdata(&tps65910_i2c_client->dev);
+ struct tps65910 *tps65910 = container_of(this, struct tps65910,
+ poweroff_nb);

if (tps65910_reg_set_bits(tps65910, TPS65910_DEVCTRL,
DEVCTRL_PWR_OFF_MASK) < 0)
- return;
+ return NOTIFY_DONE;

tps65910_reg_clear_bits(tps65910, TPS65910_DEVCTRL,
DEVCTRL_DEV_ON_MASK);
+
+ return NOTIFY_DONE;
}

static int tps65910_i2c_probe(struct i2c_client *i2c,
@@ -500,9 +503,13 @@ static int tps65910_i2c_probe(struct i2c_client *i2c,
tps65910_ck32k_init(tps65910, pmic_plat_data);
tps65910_sleepinit(tps65910, pmic_plat_data);

- if (pmic_plat_data->pm_off && !pm_power_off) {
- tps65910_i2c_client = i2c;
- pm_power_off = tps65910_power_off;
+ if (pmic_plat_data->pm_off) {
+ tps65910->poweroff_nb.notifier_call = tps65910_power_off;
+ tps65910->poweroff_nb.priority = 64;
+ ret = register_poweroff_handler(&tps65910->poweroff_nb);
+ if (ret)
+ dev_err(&i2c->dev,
+ "failed to register poweroff handler\n");
}

ret = mfd_add_devices(tps65910->dev, -1,
@@ -522,6 +529,8 @@ static int tps65910_i2c_remove(struct i2c_client *i2c)
{
struct tps65910 *tps65910 = i2c_get_clientdata(i2c);

+ unregister_poweroff_handler(&tps65910->poweroff_nb);
+
tps65910_irq_exit(tps65910);
mfd_remove_devices(tps65910->dev);

diff --git a/include/linux/mfd/tps65910.h b/include/linux/mfd/tps65910.h
index 6483a6f..65cae2c 100644
--- a/include/linux/mfd/tps65910.h
+++ b/include/linux/mfd/tps65910.h
@@ -905,6 +905,9 @@ struct tps65910 {
/* IRQ Handling */
int chip_irq;
struct regmap_irq_chip_data *irq_data;
+
+ /* Poweroff handling */
+ struct notifier_block poweroff_nb;
};

struct tps65910_platform_data {
--
1.9.1
Guenter Roeck
2014-10-07 05:28:37 UTC
Permalink
Register with kernel poweroff handler instead of setting pm_power_off
directly.

Cc: Geert Uytterhoeven <***@linux-m68k.org>
Cc: Joshua Thompson <***@jurai.org>
Signed-off-by: Guenter Roeck <***@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
Guenter Roeck
2014-10-07 05:28:18 UTC
Permalink
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: Samuel Ortiz <***@linux.intel.com>
Cc: Lee Jones <***@linaro.org>
Signed-off-by: Guenter Roeck <***@roeck-us.net>
---
drivers/mfd/tps6586x.c | 31 +++++++++++++++++++++++--------
1 file changed, 23 insertions(+), 8 deletions(-)

diff --git a/drivers/mfd/tps6586x.c b/drivers/mfd/tps6586x.c
index 8e1dbc4..bc14509 100644
--- a/drivers/mfd/tps6586x.c
+++ b/drivers/mfd/tps6586x.c
@@ -21,10 +21,12 @@
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/mutex.h>
+#include <linux/notifier.h>
#include <linux/slab.h>
#include <linux/err.h>
#include <linux/i2c.h>
#include <linux/platform_device.h>
+#include <linux/pm.h>
#include <linux/regmap.h>
#include <linux/of.h>

@@ -133,6 +135,8 @@ struct tps6586x {
u32 irq_en;
u8 mask_reg[5];
struct irq_domain *irq_domain;
+
+ struct notifier_block poweroff_nb;
};

static inline struct tps6586x *dev_to_tps6586x(struct device *dev)
@@ -472,13 +476,18 @@ static const struct regmap_config tps6586x_regmap_config = {
.cache_type = REGCACHE_RBTREE,
};

-static struct device *tps6586x_dev;
-static void tps6586x_power_off(void)
+static int tps6586x_power_off(struct notifier_block *this,
+ unsigned long unused1, void *unused2)
{
- if (tps6586x_clr_bits(tps6586x_dev, TPS6586X_SUPPLYENE, EXITSLREQ_BIT))
- return;
+ struct tps6586x *tps6586x = container_of(this, struct tps6586x,
+ poweroff_nb);
+
+ if (tps6586x_clr_bits(tps6586x->dev, TPS6586X_SUPPLYENE, EXITSLREQ_BIT))
+ return NOTIFY_DONE;

- tps6586x_set_bits(tps6586x_dev, TPS6586X_SUPPLYENE, SLEEP_MODE_BIT);
+ tps6586x_set_bits(tps6586x->dev, TPS6586X_SUPPLYENE, SLEEP_MODE_BIT);
+
+ return NOTIFY_DONE;
}

static void tps6586x_print_version(struct i2c_client *client, int version)
@@ -575,9 +584,13 @@ static int tps6586x_i2c_probe(struct i2c_client *client,
goto err_add_devs;
}

- if (pdata->pm_off && !pm_power_off) {
- tps6586x_dev = &client->dev;
- pm_power_off = tps6586x_power_off;
+ if (pdata->pm_off) {
+ tps6586x->poweroff_nb.notifier_call = tps6586x_power_off;
+ tps6586x->poweroff_nb.priority = 64;
+ ret = register_poweroff_handler(&tps6586x->poweroff_nb);
+ if (ret)
+ dev_err(&client->dev,
+ "failed to register poweroff handler\n");
}

return 0;
@@ -594,6 +607,8 @@ static int tps6586x_i2c_remove(struct i2c_client *client)
{
struct tps6586x *tps6586x = i2c_get_clientdata(client);

+ unregister_poweroff_handler(&tps6586x->poweroff_nb);
+
tps6586x_remove_subdevs(tps6586x);
mfd_remove_devices(tps6586x->dev);
if (client->irq)
--
1.9.1
Guenter Roeck
2014-10-07 05:28:39 UTC
Permalink
Register with kernel poweroff handler instead of setting pm_power_off
directly.

Signed-off-by: Guenter Roeck <***@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
Guenter Roeck
2014-10-07 05:28:14 UTC
Permalink
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: Linus Walleij <***@linaro.org>
Cc: Lee Jones <***@linaro.org>
Cc: Samuel Ortiz <***@linux.intel.com>
Signed-off-by: Guenter Roeck <***@roeck-us.net>
---
drivers/mfd/ab8500-sysctrl.c | 26 +++++++++++++++-----------
1 file changed, 15 insertions(+), 11 deletions(-)

diff --git a/drivers/mfd/ab8500-sysctrl.c b/drivers/mfd/ab8500-sysctrl.c
index 8e0dae5..677438f 100644
--- a/drivers/mfd/ab8500-sysctrl.c
+++ b/drivers/mfd/ab8500-sysctrl.c
@@ -6,6 +6,7 @@

#include <linux/err.h>
#include <linux/module.h>
+#include <linux/notifier.h>
#include <linux/platform_device.h>
#include <linux/pm.h>
#include <linux/reboot.h>
@@ -23,7 +24,8 @@

static struct device *sysctrl_dev;

-static void ab8500_power_off(void)
+static int ab8500_power_off(struct notifier_block *this, unsigned long unused1,
+ void *unused2)
{
sigset_t old;
sigset_t all;
@@ -34,11 +36,6 @@ static void ab8500_power_off(void)
struct power_supply *psy;
int ret;

- if (sysctrl_dev == NULL) {
- pr_err("%s: sysctrl not initialized\n", __func__);
- return;
- }
-
/*
* If we have a charger connected and we're powering off,
* reboot into charge-only mode.
@@ -83,8 +80,15 @@ shutdown:
AB8500_STW4500CTRL1_SWRESET4500N);
(void)sigprocmask(SIG_SETMASK, &old, NULL);
}
+
+ return NOTIFY_DONE;
}

+static struct notifier_block ab8500_poweroff_nb = {
+ .notifier_call = ab8500_power_off,
+ .priority = 64,
+};
+
/*
* Use the AB WD to reset the platform. It will perform a hard
* reset instead of a soft reset. Write the reset reason to
@@ -185,6 +189,7 @@ static int ab8500_sysctrl_probe(struct platform_device *pdev)
struct ab8500 *ab8500 = dev_get_drvdata(pdev->dev.parent);
struct ab8500_platform_data *plat;
struct ab8500_sysctrl_platform_data *pdata;
+ int err;

plat = dev_get_platdata(pdev->dev.parent);

@@ -193,8 +198,9 @@ static int ab8500_sysctrl_probe(struct platform_device *pdev)

sysctrl_dev = &pdev->dev;

- if (!pm_power_off)
- pm_power_off = ab8500_power_off;
+ err = register_poweroff_handler(&ab8500_poweroff_nb);
+ if (err)
+ dev_err(&pdev->dev, "Failed to register poweroff handler\n");

pdata = plat->sysctrl;
if (pdata) {
@@ -226,11 +232,9 @@ static int ab8500_sysctrl_probe(struct platform_device *pdev)

static int ab8500_sysctrl_remove(struct platform_device *pdev)
{
+ unregister_poweroff_handler(&ab8500_poweroff_nb);
sysctrl_dev = NULL;

- if (pm_power_off == ab8500_power_off)
- pm_power_off = NULL;
-
return 0;
}
--
1.9.1
Guenter Roeck
2014-10-07 05:28:40 UTC
Permalink
Register with kernel poweroff handler instead of setting pm_power_off
directly.

Cc: Rusty Russell <***@rustcorp.com.au>
Cc: Thomas Gleixner <***@linutronix.de>
Cc: Ingo Molnar <***@redhat.com>
Cc: H. Peter Anvin <***@zytor.com>
Signed-off-by: Guenter Roeck <***@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
Guenter Roeck
2014-10-07 05:28:26 UTC
Permalink
Register with kernel poweroff handler instead of setting pm_power_off
directly. Select proprity 0 since the code does not really poweroff
the system.

Signed-off-by: Guenter Roeck <***@roeck-us.net>
---
drivers/power/reset/msm-poweroff.c | 13 +++++++++++--
1 file changed, 11 insertions(+), 2 deletions(-)

diff --git a/drivers/power/reset/msm-poweroff.c b/drivers/power/reset/msm-poweroff.c
index 774f9a3..189bcd3 100644
--- a/drivers/power/reset/msm-poweroff.c
+++ b/drivers/power/reset/msm-poweroff.c
@@ -19,6 +19,7 @@
#include <linux/of.h>
#include <linux/platform_device.h>
#include <linux/module.h>
+#include <linux/notifier.h>
#include <linux/reboot.h>

#include <asm/system_misc.h>
@@ -31,12 +32,19 @@ static void do_msm_restart(enum reboot_mode reboot_mode, const char *cmd)
mdelay(10000);
}

-static void do_msm_poweroff(void)
+static int do_msm_poweroff(struct notifier_block *this,
+ unsigned long unused1, void *unused2)
{
/* TODO: Add poweroff capability */
do_msm_restart(REBOOT_HARD, NULL);
+
+ return NOTIFY_DONE;
}

+static struct notifier_block msm_powroff_nb = {
+ .notifier_call = do_msm_poweroff,
+};
+
static int msm_restart_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
@@ -47,7 +55,8 @@ static int msm_restart_probe(struct platform_device *pdev)
if (IS_ERR(msm_ps_hold))
return PTR_ERR(msm_ps_hold);

- pm_power_off = do_msm_poweroff;
+ if (register_poweroff_handler(&msm_powroff_nb))
+ dev_err(&pdev->dev, "Failed to register poweroff handler\n");
arm_pm_restart = do_msm_restart;
return 0;
}
--
1.9.1
Guenter Roeck
2014-10-07 05:28:20 UTC
Permalink
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 <***@linux.intel.com>
Cc: Lee Jones <***@linaro.org>
Signed-off-by: Guenter Roeck <***@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,
+};
+
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");
+ /* Not a fatal error */
+ err = 0;
+ }
}

relock:
@@ -869,6 +884,8 @@ relock:

static int twl4030_power_remove(struct platform_device *pdev)
{
+ unregister_poweroff_handler(&twl4030_poweroff_nb);
+
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 */
--
1.9.1
Guenter Roeck
2014-10-07 05:28:42 UTC
Permalink
A dummy poweroff handler does not serve any purpose. Drop it.

Cc: Thomas Gleixner <***@linutronix.de>
Cc: Ingo Molnar <***@redhat.com>
Cc: H. Peter Anvin <***@zytor.com>
Signed-off-by: Guenter Roeck <***@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
Guenter Roeck
2014-10-07 05:28:33 UTC
Permalink
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 <***@arm.linux.org.uk>
Cc: Andrew Victor <***@maxim.org.za>
Cc: Nicolas Ferre <***@atmel.com>
Cc: Jean-Christophe Plagniol-Villard <***@jcrosoft.com>
Cc: Stephen Warren <***@wwwdotorg.org>
Cc: Christian Daudt <***@fixthebug.org>
Cc: Matt Porter <***@linaro.org>
Cc: Anton Vorontsov <***@enomsg.org>
Cc: Rob Herring <***@kernel.org>
Cc: Shawn Guo <***@freescale.com>
Cc: Sascha Hauer <***@pengutronix.de>
Cc: Imre Kaloz <***@openwrt.org>
Cc: Krzysztof Halasa <***@pm.waw.pl>
Cc: Tony Lindgren <***@atomide.com>
Cc: Jason Cooper <***@lakedaemon.net>
Cc: Andrew Lunn <***@lunn.ch>
Cc: Sebastian Hesselbarth <***@gmail.com>
Cc: Eric Miao <***@gmail.com>
Cc: Haojian Zhuang <***@gmail.com>
Cc: Robert Jarzmik <***@free.fr>
Cc: Marek Vasut <***@gmail.com>
Cc: Ben Dooks <ben-***@fluff.org>
Cc: Kukjin Kim <***@samsung.com>
Cc: Linus Walleij <***@linaro.org>
Cc: Tony Prisk <***@prisktech.co.nz>
Cc: Stefano Stabellini <***@eu.citrix.com>
Signed-off-by: Guenter Roeck <***@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
Guenter Roeck
2014-10-07 05:28:41 UTC
Permalink
Register with kernel poweroff handler instead of setting pm_power_off
directly.

Cc: Thomas Gleixner <***@linutronix.de>
Cc: Ingo Molnar <***@redhat.com>
Cc: H. Peter Anvin <***@zytor.com>
Signed-off-by: Guenter Roeck <***@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
Guenter Roeck
2014-10-07 05:28:43 UTC
Permalink
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 <***@linutronix.de>
Cc: Ingo Molnar <***@redhat.com>
Cc: H. Peter Anvin <***@zytor.com>
Signed-off-by: Guenter Roeck <***@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
Guenter Roeck
2014-10-07 05:28:12 UTC
Permalink
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: Lee Jones <***@linaro.org>
Cc: Samuel Ortiz <***@linux.intel.com>
Signed-off-by: Guenter Roeck <***@roeck-us.net>
---
drivers/mfd/axp20x.c | 30 +++++++++++++++++-------------
include/linux/mfd/axp20x.h | 1 +
2 files changed, 18 insertions(+), 13 deletions(-)

diff --git a/drivers/mfd/axp20x.c b/drivers/mfd/axp20x.c
index dee6539..238db4c 100644
--- a/drivers/mfd/axp20x.c
+++ b/drivers/mfd/axp20x.c
@@ -17,7 +17,8 @@
#include <linux/interrupt.h>
#include <linux/kernel.h>
#include <linux/module.h>
-#include <linux/pm_runtime.h>
+#include <linux/notifier.h>
+#include <linux/pm.h>
#include <linux/regmap.h>
#include <linux/slab.h>
#include <linux/regulator/consumer.h>
@@ -161,11 +162,16 @@ static struct mfd_cell axp20x_cells[] = {
},
};

-static struct axp20x_dev *axp20x_pm_power_off;
-static void axp20x_power_off(void)
+static int axp20x_power_off(struct notifier_block *this, unsigned long unused1,
+ void *unused2)
+
{
- regmap_write(axp20x_pm_power_off->regmap, AXP20X_OFF_CTRL,
- AXP20X_OFF);
+ struct axp20x_dev *axp20x = container_of(this, struct axp20x_dev,
+ poweroff_nb);
+
+ regmap_write(axp20x->regmap, AXP20X_OFF_CTRL, AXP20X_OFF);
+
+ return NOTIFY_DONE;
}

static int axp20x_i2c_probe(struct i2c_client *i2c,
@@ -215,10 +221,11 @@ static int axp20x_i2c_probe(struct i2c_client *i2c,
return ret;
}

- if (!pm_power_off) {
- axp20x_pm_power_off = axp20x;
- pm_power_off = axp20x_power_off;
- }
+ axp20x->poweroff_nb.notifier_call = axp20x_power_off;
+ axp20x->poweroff_nb.priority = 64;
+ ret = register_poweroff_handler(&axp20x->poweroff_nb);
+ if (ret)
+ dev_err(&i2c->dev, "failed to register poweroff handler\n");

dev_info(&i2c->dev, "AXP20X driver loaded\n");

@@ -229,10 +236,7 @@ static int axp20x_i2c_remove(struct i2c_client *i2c)
{
struct axp20x_dev *axp20x = i2c_get_clientdata(i2c);

- if (axp20x == axp20x_pm_power_off) {
- axp20x_pm_power_off = NULL;
- pm_power_off = NULL;
- }
+ unregister_poweroff_handler(&axp20x->poweroff_nb);

mfd_remove_devices(axp20x->dev);
regmap_del_irq_chip(axp20x->i2c_client->irq, axp20x->regmap_irqc);
diff --git a/include/linux/mfd/axp20x.h b/include/linux/mfd/axp20x.h
index d0e31a2..8f23b39 100644
--- a/include/linux/mfd/axp20x.h
+++ b/include/linux/mfd/axp20x.h
@@ -175,6 +175,7 @@ struct axp20x_dev {
struct regmap *regmap;
struct regmap_irq_chip_data *regmap_irqc;
long variant;
+ struct notifier_block poweroff_nb;
};

#endif /* __LINUX_MFD_AXP20X_H */
--
1.9.1
Guenter Roeck
2014-10-07 05:28:45 UTC
Permalink
Drivers should not call pm_power_off directly; it is not guaranteed
to be non-NULL. Call kernel_power_off instead.

Cc: Jean Delvare <***@suse.de>
Reviewed-by: Jean Delvare <***@suse.de>
Signed-off-by: Guenter Roeck <***@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
Guenter Roeck
2014-10-07 05:28:27 UTC
Permalink
Register with kernel poweroff handler instead of setting pm_power_off
directly.

Signed-off-by: Guenter Roeck <***@roeck-us.net>
---
drivers/power/reset/vexpress-poweroff.c | 19 +++++++++++++++++--
1 file changed, 17 insertions(+), 2 deletions(-)

diff --git a/drivers/power/reset/vexpress-poweroff.c b/drivers/power/reset/vexpress-poweroff.c
index 4dc102e2..060c55d 100644
--- a/drivers/power/reset/vexpress-poweroff.c
+++ b/drivers/power/reset/vexpress-poweroff.c
@@ -12,6 +12,7 @@
*/

#include <linux/delay.h>
+#include <linux/notifier.h>
#include <linux/of.h>
#include <linux/of_device.h>
#include <linux/platform_device.h>
@@ -36,11 +37,19 @@ static void vexpress_reset_do(struct device *dev, const char *what)

static struct device *vexpress_power_off_device;

-static void vexpress_power_off(void)
+static int vexpress_power_off(struct notifier_block *this,
+ unsigned long unused1, void *unused2)
{
vexpress_reset_do(vexpress_power_off_device, "power off");
+
+ return NOTIFY_DONE;
}

+static struct notifier_block vexpress_poweroff_nb = {
+ .notifier_call = vexpress_power_off,
+ .priority = 128,
+};
+
static struct device *vexpress_restart_device;

static void vexpress_restart(enum reboot_mode reboot_mode, const char *cmd)
@@ -92,6 +101,7 @@ static int vexpress_reset_probe(struct platform_device *pdev)
const struct of_device_id *match =
of_match_device(vexpress_reset_of_match, &pdev->dev);
struct regmap *regmap;
+ int ret;

if (match)
func = (enum vexpress_reset_func)match->data;
@@ -106,7 +116,12 @@ static int vexpress_reset_probe(struct platform_device *pdev)
switch (func) {
case FUNC_SHUTDOWN:
vexpress_power_off_device = &pdev->dev;
- pm_power_off = vexpress_power_off;
+ ret = register_poweroff_handler(&vexpress_poweroff_nb);
+ if (ret) {
+ dev_err(&pdev->dev,
+ "Failed to register poweroff handler\n");
+ return ret;
+ }
break;
case FUNC_RESET:
if (!vexpress_restart_device)
--
1.9.1
Guenter Roeck
2014-10-07 05:28:38 UTC
Permalink
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 <***@linux-mips.org>
Cc: Maciej W. Rozycki <***@linux-mips.org>
Signed-off-by: Guenter Roeck <***@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
Guenter Roeck
2014-10-07 05:28:44 UTC
Permalink
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 <***@intel.com>
Signed-off-by: Guenter Roeck <***@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 <***@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
Guenter Roeck
2014-10-07 05:28:46 UTC
Permalink
No users of pm_power_off are left, so it is safe to remove the function.

Cc: Rafael J. Wysocki <***@rjwysocki.net>
Cc: Pavel Machek <***@ucw.cz>
Cc: Len Brown <***@intel.com>
Signed-off-by: Guenter Roeck <***@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
Guenter Roeck
2014-10-07 05:28:23 UTC
Permalink
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.

Other changes:

Drop note that there can not be an additional instance of this driver.
The original reason no longer applies, it should be obvious that there
can only be one instance of the driver if static variables are used to
reflect its state, and support for multiple instances can now be added
easily if needed by avoiding static variables.

Do not create an error message if another poweroff handler has already been
registered. This is perfectly normal and acceptable.

Do not display a warning traceback if the poweroff handler fails to
power off the system. There may be other poweroff handlers.

Cc: Sebastian Reichel <***@kernel.org>
Cc: Dmitry Eremin-Solenikov <***@gmail.com>
Cc: David Woodhouse <***@infradead.org>
Signed-off-by: Guenter Roeck <***@roeck-us.net>
---
drivers/power/reset/gpio-poweroff.c | 36 ++++++++++++++++++------------------
1 file changed, 18 insertions(+), 18 deletions(-)

diff --git a/drivers/power/reset/gpio-poweroff.c b/drivers/power/reset/gpio-poweroff.c
index ce849bc..e95a7a1 100644
--- a/drivers/power/reset/gpio-poweroff.c
+++ b/drivers/power/reset/gpio-poweroff.c
@@ -14,18 +14,18 @@
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/delay.h>
+#include <linux/notifier.h>
+#include <linux/pm.h>
#include <linux/platform_device.h>
#include <linux/gpio/consumer.h>
#include <linux/of_platform.h>
#include <linux/module.h>

-/*
- * Hold configuration here, cannot be more than one instance of the driver
- * since pm_power_off itself is global.
- */
static struct gpio_desc *reset_gpio;

-static void gpio_poweroff_do_poweroff(void)
+static int gpio_poweroff_do_poweroff(struct notifier_block *this,
+ unsigned long unused1, void *unused2)
+
{
BUG_ON(!reset_gpio);

@@ -42,20 +42,18 @@ static void gpio_poweroff_do_poweroff(void)
/* give it some time */
mdelay(3000);

- WARN_ON(1);
+ return NOTIFY_DONE;
}

+static struct notifier_block gpio_poweroff_nb = {
+ .notifier_call = gpio_poweroff_do_poweroff,
+ .priority = 64,
+};
+
static int gpio_poweroff_probe(struct platform_device *pdev)
{
bool input = false;
-
- /* If a pm_power_off function has already been added, leave it alone */
- if (pm_power_off != NULL) {
- dev_err(&pdev->dev,
- "%s: pm_power_off function already registered",
- __func__);
- return -EBUSY;
- }
+ int err;

reset_gpio = devm_gpiod_get(&pdev->dev, NULL);
if (IS_ERR(reset_gpio))
@@ -77,14 +75,16 @@ static int gpio_poweroff_probe(struct platform_device *pdev)
}
}

- pm_power_off = &gpio_poweroff_do_poweroff;
- return 0;
+ err = register_poweroff_handler(&gpio_poweroff_nb);
+ if (err)
+ dev_err(&pdev->dev, "Failed to register poweroff handler\n");
+
+ return err;
}

static int gpio_poweroff_remove(struct platform_device *pdev)
{
- if (pm_power_off == &gpio_poweroff_do_poweroff)
- pm_power_off = NULL;
+ unregister_poweroff_handler(&gpio_poweroff_nb);

return 0;
}
--
1.9.1
Guenter Roeck
2014-10-07 05:28:24 UTC
Permalink
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: Sebastian Reichel <***@kernel.org>
Cc: Dmitry Eremin-Solenikov <***@gmail.com>
Cc: David Woodhouse <***@infradead.org>
Signed-off-by: Guenter Roeck <***@roeck-us.net>
---
drivers/power/reset/as3722-poweroff.c | 36 ++++++++++++++++++-----------------
1 file changed, 19 insertions(+), 17 deletions(-)

diff --git a/drivers/power/reset/as3722-poweroff.c b/drivers/power/reset/as3722-poweroff.c
index 6849711..7ebaed9 100644
--- a/drivers/power/reset/as3722-poweroff.c
+++ b/drivers/power/reset/as3722-poweroff.c
@@ -17,32 +17,33 @@

#include <linux/mfd/as3722.h>
#include <linux/module.h>
+#include <linux/notifier.h>
#include <linux/of.h>
#include <linux/of_device.h>
#include <linux/platform_device.h>
+#include <linux/pm.h>
#include <linux/slab.h>

struct as3722_poweroff {
struct device *dev;
struct as3722 *as3722;
+ struct notifier_block poweroff_nb;
};

-static struct as3722_poweroff *as3722_pm_poweroff;
-
-static void as3722_pm_power_off(void)
+static int as3722_power_off(struct notifier_block *this, unsigned long unused1,
+ void *unused2)
{
+ struct as3722_poweroff *as3722_poweroff =
+ container_of(this, struct as3722_poweroff, poweroff_nb);
int ret;

- if (!as3722_pm_poweroff) {
- pr_err("AS3722 poweroff is not initialised\n");
- return;
- }
-
- ret = as3722_update_bits(as3722_pm_poweroff->as3722,
+ ret = as3722_update_bits(as3722_poweroff->as3722,
AS3722_RESET_CONTROL_REG, AS3722_POWER_OFF, AS3722_POWER_OFF);
if (ret < 0)
- dev_err(as3722_pm_poweroff->dev,
+ dev_err(as3722_poweroff->dev,
"RESET_CONTROL_REG update failed, %d\n", ret);
+
+ return NOTIFY_DONE;
}

static int as3722_poweroff_probe(struct platform_device *pdev)
@@ -63,18 +64,19 @@ static int as3722_poweroff_probe(struct platform_device *pdev)

as3722_poweroff->as3722 = dev_get_drvdata(pdev->dev.parent);
as3722_poweroff->dev = &pdev->dev;
- as3722_pm_poweroff = as3722_poweroff;
- if (!pm_power_off)
- pm_power_off = as3722_pm_power_off;
+ as3722_poweroff->poweroff_nb.notifier_call = as3722_power_off;
+ as3722_poweroff->poweroff_nb.priority = 64;

- return 0;
+ platform_set_drvdata(pdev, as3722_poweroff);
+
+ return register_poweroff_handler(&as3722_poweroff->poweroff_nb);
}

static int as3722_poweroff_remove(struct platform_device *pdev)
{
- if (pm_power_off == as3722_pm_power_off)
- pm_power_off = NULL;
- as3722_pm_poweroff = NULL;
+ struct as3722_poweroff *as3722_poweroff = platform_get_drvdata(pdev);
+
+ unregister_poweroff_handler(&as3722_poweroff->poweroff_nb);

return 0;
}
--
1.9.1
Guenter Roeck
2014-10-07 05:28:22 UTC
Permalink
Register with kernel poweroff handler instead of seting pm_power_off
directly. Register as poweroff handler of last resort since the driver
does not really power off the system but executes a restart.

Cc: Sebastian Reichel <***@kernel.org>
Cc: Dmitry Eremin-Solenikov <***@gmail.com>
Cc: David Woodhouse <***@infradead.org>
Signed-off-by: Guenter Roeck <***@roeck-us.net>
---
drivers/power/reset/restart-poweroff.c | 25 ++++++++++++-------------
1 file changed, 12 insertions(+), 13 deletions(-)

diff --git a/drivers/power/reset/restart-poweroff.c b/drivers/power/reset/restart-poweroff.c
index edd707e..5437697 100644
--- a/drivers/power/reset/restart-poweroff.c
+++ b/drivers/power/reset/restart-poweroff.c
@@ -12,35 +12,34 @@
*/
#include <linux/kernel.h>
#include <linux/init.h>
+#include <linux/notifier.h>
#include <linux/platform_device.h>
#include <linux/of_platform.h>
#include <linux/module.h>
+#include <linux/pm.h>
#include <linux/reboot.h>
-#include <asm/system_misc.h>

-static void restart_poweroff_do_poweroff(void)
+static int restart_poweroff_do_poweroff(struct notifier_block *this,
+ unsigned long unused1, void *unused2)
{
reboot_mode = REBOOT_HARD;
machine_restart(NULL);
+
+ return NOTIFY_DONE;
}

+static struct notifier_block restart_poweroff_handler = {
+ .notifier_call = restart_poweroff_do_poweroff,
+};
+
static int restart_poweroff_probe(struct platform_device *pdev)
{
- /* If a pm_power_off function has already been added, leave it alone */
- if (pm_power_off != NULL) {
- dev_err(&pdev->dev,
- "pm_power_off function already registered");
- return -EBUSY;
- }
-
- pm_power_off = &restart_poweroff_do_poweroff;
- return 0;
+ return register_poweroff_handler(&restart_poweroff_handler);
}

static int restart_poweroff_remove(struct platform_device *pdev)
{
- if (pm_power_off == &restart_poweroff_do_poweroff)
- pm_power_off = NULL;
+ unregister_poweroff_handler(&restart_poweroff_handler);

return 0;
}
--
1.9.1
Guenter Roeck
2014-10-07 05:28:03 UTC
Permalink
Various drivers implement architecture and/or device specific means to
remove power from the system. For the most part, those drivers set the
global variable pm_power_off to point to a function within the driver.

This mechanism has a number of drawbacks. Typically only one scheme
to remove power is supported (at least if pm_power_off is used).
At least in theory there can be multiple means remove power, some of
which may be less desirable. For example, some mechanisms may only
power off the CPU or the CPU card, while another may power off the
entire system. Others may really just execute a restart sequence
or drop into the ROM monitor. Using pm_power_off can also be racy
if the function pointer is set from a driver built as module, as the
driver may be in the process of being unloaded when pm_power_off is
called. If there are multiple poweroff handlers in the system, removing
a module with such a handler may inadvertently reset the pointer to
pm_power_off to NULL, leaving the system with no means to remove power.

Introduce a system poweroff handler call chain to solve the described
problems. This call chain is expected to be executed from the
architecture specific machine_power_off() function. Drivers providing
system poweroff functionality are expected to register with this call chain.
By using the priority field in the notifier block, callers can control
poweroff handler execution sequence and thus ensure that the poweroff
handler with the optimal capabilities to remove power for a given system
is called first.

Cc: Andrew Morton <***@linux-foundation.org>
cc: Heiko Stuebner <***@sntech.de>
Cc: Romain Perier <***@gmail.com>
Cc: Rafael J. Wysocki <***@rjwysocki.net>
Cc: Len Brown <***@intel.com>
Cc: Pavel Machek <***@ucw.cz>
Cc: Alexander Graf <***@suse.de>
Cc: Geert Uytterhoeven <***@linux-m68k.org>
Signed-off-by: Guenter Roeck <***@roeck-us.net>
---
include/linux/pm.h | 13 +++
kernel/power/Makefile | 1 +
kernel/power/poweroff_handler.c | 172 ++++++++++++++++++++++++++++++++++++++++
3 files changed, 186 insertions(+)
create mode 100644 kernel/power/poweroff_handler.c

diff --git a/include/linux/pm.h b/include/linux/pm.h
index 72c0fe0..45271b5 100644
--- a/include/linux/pm.h
+++ b/include/linux/pm.h
@@ -34,6 +34,19 @@
extern void (*pm_power_off)(void);
extern void (*pm_power_off_prepare)(void);

+/*
+ * Callbacks to manage poweroff handlers
+ */
+
+struct notifier_block;
+
+extern int register_poweroff_handler(struct notifier_block *);
+extern int register_poweroff_handler_simple(void (*function)(void),
+ int priority);
+extern int unregister_poweroff_handler(struct notifier_block *);
+extern void do_kernel_poweroff(void);
+extern bool have_kernel_poweroff(void);
+
struct device; /* we have a circular dep with device.h */
#ifdef CONFIG_VT_CONSOLE_SLEEP
extern void pm_vt_switch_required(struct device *dev, bool required);
diff --git a/kernel/power/Makefile b/kernel/power/Makefile
index 29472bf..4d9f0c7 100644
--- a/kernel/power/Makefile
+++ b/kernel/power/Makefile
@@ -2,6 +2,7 @@
ccflags-$(CONFIG_PM_DEBUG) := -DDEBUG

obj-y += qos.o
+obj-y += poweroff_handler.o
obj-$(CONFIG_PM) += main.o
obj-$(CONFIG_VT_CONSOLE_SLEEP) += console.o
obj-$(CONFIG_FREEZER) += process.o
diff --git a/kernel/power/poweroff_handler.c b/kernel/power/poweroff_handler.c
new file mode 100644
index 0000000..ed99e5e
--- /dev/null
+++ b/kernel/power/poweroff_handler.c
@@ -0,0 +1,172 @@
+/*
+ * linux/kernel/power/poweroff_handler.c - Poweroff handling functions
+ *
+ * Copyright (c) 2014 Guenter Roeck
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public Licence
+ * as published by the Free Software Foundation; either version
+ * 2 of the Licence, or (at your option) any later version.
+ */
+
+#define pr_fmt(fmt) "poweroff: " fmt
+
+#include <linux/ctype.h>
+#include <linux/export.h>
+#include <linux/kallsyms.h>
+#include <linux/notifier.h>
+#include <linux/pm.h>
+#include <linux/slab.h>
+#include <linux/types.h>
+
+/*
+ * Notifier list for kernel code which wants to be called
+ * to power off the system.
+ */
+static ATOMIC_NOTIFIER_HEAD(poweroff_handler_list);
+
+/**
+ * register_poweroff_handler - Register function to be called to power off
+ * the system
+ * @nb: Info about handler function to be called
+ * @nb->priority: Handler priority. Handlers should follow the
+ * following guidelines for setting priorities.
+ * 0: Poweroff handler of last resort,
+ * with limited poweroff capabilities,
+ * such as poweroff handlers which
+ * do not really power off the system
+ * but loop forever or stop the CPU.
+ * 128: Default poweroff handler; use if no other
+ * poweroff handler is expected to be available,
+ * and/or if poweroff functionality is
+ * sufficient to power off the entire system
+ * 255: Highest priority poweroff handler, will
+ * preempt all other poweroff handlers
+ *
+ * Registers a function with code to be called to power off the
+ * system.
+ *
+ * Registered functions will be called from machine_power_off as last
+ * step of the poweroff sequence. Registered functions are expected
+ * to power off the system immediately. If more than one function is
+ * registered, the poweroff handler priority selects which function
+ * will be called first.
+ *
+ * Poweroff handlers may be registered from architecture code or from
+ * drivers. A typical use case would be a system where power off
+ * functionality is provided through a multi-function chip or through
+ * a programmable power controller. Multiple poweroff handlers may exist;
+ * for example, one poweroff handler might power off the entire system,
+ * while another only powers off the CPU card. In such cases, the
+ * poweroff handler which only powers off part of the hardware is
+ * expected to register with low priority to ensure that it only
+ * runs if no other means to power off the system are available.
+ *
+ * Currently always returns zero, as atomic_notifier_chain_register()
+ * always returns zero.
+ */
+int register_poweroff_handler(struct notifier_block *nb)
+{
+ return atomic_notifier_chain_register(&poweroff_handler_list, nb);
+}
+EXPORT_SYMBOL(register_poweroff_handler);
+
+/**
+ * unregister_poweroff_handler - Unregister previously registered
+ * poweroff handler
+ * @nb: Hook to be unregistered
+ *
+ * Unregisters a previously registered poweroff handler function.
+ *
+ * Returns zero on success, or %-ENOENT on failure.
+ */
+int unregister_poweroff_handler(struct notifier_block *nb)
+{
+ return atomic_notifier_chain_unregister(&poweroff_handler_list, nb);
+}
+EXPORT_SYMBOL(unregister_poweroff_handler);
+
+struct _poweroff_handler_data {
+ void (*handler)(void);
+ struct notifier_block poweroff_nb;
+};
+
+static int _poweroff_handler(struct notifier_block *this,
+ unsigned long _unused1, void *_unused2)
+{
+ struct _poweroff_handler_data *poh =
+ container_of(this, struct _poweroff_handler_data, poweroff_nb);
+
+ poh->handler();
+
+ return NOTIFY_DONE;
+}
+
+static struct _poweroff_handler_data poweroff_handler_data;
+
+/**
+ * register_poweroff_handler_simple - Register function to be called to power off
+ * the system
+ * @handler: Function to be called to power off the system
+ * @priority: Handler priority. For priority guidelines see
+ * register_poweroff_handler.
+ *
+ * This is a simplified version of register_poweroff_handler. It does not
+ * take a notifier as argument, but a function pointer. The function
+ * registers a poweroff handler with specified priority. Poweroff
+ * handlers registered with this function can not be unregistered,
+ * and only a single poweroff handler can be installed using it.
+ *
+ * This function must not be called from modules and is therefore
+ * not exported.
+ *
+ * Returns -EBUSY if a poweroff handler has already been registered
+ * using register_poweroff_handler_simple. Otherwise returns zero,
+ * since atomic_notifier_chain_register() currently always returns zero.
+ */
+int register_poweroff_handler_simple(void (*handler)(void), int priority)
+{
+ char symname[KSYM_NAME_LEN];
+
+ if (poweroff_handler_data.handler) {
+ lookup_symbol_name((unsigned long)poweroff_handler_data.handler,
+ symname);
+ pr_warn("Poweroff function already registered (%s)", symname);
+ lookup_symbol_name((unsigned long)handler, symname);
+ pr_cont(", cannot register %s\n", symname);
+ return -EBUSY;
+ }
+
+ poweroff_handler_data.handler = handler;
+ poweroff_handler_data.poweroff_nb.notifier_call = _poweroff_handler;
+ poweroff_handler_data.poweroff_nb.priority = priority;
+
+ return register_poweroff_handler(&poweroff_handler_data.poweroff_nb);
+}
+
+/**
+ * do_kernel_poweroff - Execute kernel poweroff handler call chain
+ *
+ * Calls functions registered with register_poweroff_handler.
+ *
+ * Expected to be called from machine_power_off as last step of
+ * the poweroff sequence.
+ *
+ * Powers off the system immediately if a poweroff handler function
+ * has been registered. Otherwise does nothing.
+ */
+void do_kernel_poweroff(void)
+{
+ atomic_notifier_call_chain(&poweroff_handler_list, 0, NULL);
+}
+
+/**
+ * have_kernel_poweroff() - Check if kernel poweroff handler is available
+ *
+ * Returns true is a kernel poweroff handler is available, false otherwise.
+ */
+bool have_kernel_poweroff(void)
+{
+ return pm_power_off != NULL || poweroff_handler_list.head != NULL;
+}
+EXPORT_SYMBOL(have_kernel_poweroff);
--
1.9.1
Guenter Roeck
2014-10-07 05:28:05 UTC
Permalink
Poweroff handlers may now be installed with register_poweroff_handler.
Use the new API function have_kernel_poweroff to determine if a poweroff
handler has been installed.

Cc: Rafael J. Wysocki <***@rjwysocki.net>
Cc: Pavel Machek <***@ucw.cz>
Cc: Len Brown <***@intel.com>
Signed-off-by: Guenter Roeck <***@roeck-us.net>
---
kernel/power/hibernate.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/kernel/power/hibernate.c b/kernel/power/hibernate.c
index a9dfa79..20353c5 100644
--- a/kernel/power/hibernate.c
+++ b/kernel/power/hibernate.c
@@ -602,7 +602,7 @@ static void power_down(void)
case HIBERNATION_PLATFORM:
hibernation_platform_enter();
case HIBERNATION_SHUTDOWN:
- if (pm_power_off)
+ if (have_kernel_poweroff())
kernel_power_off();
break;
#ifdef CONFIG_SUSPEND
--
1.9.1
Guenter Roeck
2014-10-07 05:28:09 UTC
Permalink
Replace reference to pm_power_off (which is an implementation detail)
and replace it with a more generic description of the driver's functionality.

Cc: Rob Herring <robh+***@kernel.org>
Cc: Pawel Moll <***@arm.com>
Cc: Mark Rutland <***@arm.com>
Signed-off-by: Guenter Roeck <***@roeck-us.net>
---
Documentation/devicetree/bindings/power_supply/qnap-poweroff.txt | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/Documentation/devicetree/bindings/power_supply/qnap-poweroff.txt b/Documentation/devicetree/bindings/power_supply/qnap-poweroff.txt
index af25e77..1e2260a 100644
--- a/Documentation/devicetree/bindings/power_supply/qnap-poweroff.txt
+++ b/Documentation/devicetree/bindings/power_supply/qnap-poweroff.txt
@@ -3,8 +3,8 @@
QNAP NAS devices have a microcontroller controlling the main power
supply. This microcontroller is connected to UART1 of the Kirkwood and
Orion5x SoCs. Sending the character 'A', at 19200 baud, tells the
-microcontroller to turn the power off. This driver adds a handler to
-pm_power_off which is called to turn the power off.
+microcontroller to turn the power off. This driver installs a handler
+to power off the system.

Synology NAS devices use a similar scheme, but a different baud rate,
9600, and a different character, '1'.
--
1.9.1
Guenter Roeck
2014-10-07 05:28:06 UTC
Permalink
Replace mach_power_off with pm_power_off to simplify the subsequent
move of pm_power_off to generic code.

Cc: Geert Uytterhoeven <***@linux-m68k.org>
Cc: Greg Ungerer <***@uclinux.org>
Cc: Joshua Thompson <***@jurai.org>
Signed-off-by: Guenter Roeck <***@roeck-us.net>
---
arch/m68k/emu/natfeat.c | 3 ++-
arch/m68k/include/asm/machdep.h | 1 -
arch/m68k/kernel/process.c | 5 +++--
arch/m68k/kernel/setup_mm.c | 1 -
arch/m68k/kernel/setup_no.c | 1 -
arch/m68k/mac/config.c | 3 ++-
6 files changed, 7 insertions(+), 7 deletions(-)

diff --git a/arch/m68k/emu/natfeat.c b/arch/m68k/emu/natfeat.c
index 71b78ec..91e2ae7 100644
--- a/arch/m68k/emu/natfeat.c
+++ b/arch/m68k/emu/natfeat.c
@@ -15,6 +15,7 @@
#include <linux/string.h>
#include <linux/kernel.h>
#include <linux/module.h>
+#include <linux/pm.h>
#include <linux/io.h>
#include <asm/machdep.h>
#include <asm/natfeat.h>
@@ -90,5 +91,5 @@ void __init nf_init(void)
pr_info("NatFeats found (%s, %lu.%lu)\n", buf, version >> 16,
version & 0xffff);

- mach_power_off = nf_poweroff;
+ pm_power_off = nf_poweroff;
}
diff --git a/arch/m68k/include/asm/machdep.h b/arch/m68k/include/asm/machdep.h
index 953ca21..f9fac51 100644
--- a/arch/m68k/include/asm/machdep.h
+++ b/arch/m68k/include/asm/machdep.h
@@ -24,7 +24,6 @@ extern int (*mach_set_rtc_pll)(struct rtc_pll_info *);
extern int (*mach_set_clock_mmss)(unsigned long);
extern void (*mach_reset)( void );
extern void (*mach_halt)( void );
-extern void (*mach_power_off)( void );
extern unsigned long (*mach_hd_init) (unsigned long, unsigned long);
extern void (*mach_hd_setup)(char *, int *);
extern long mach_max_dma_address;
diff --git a/arch/m68k/kernel/process.c b/arch/m68k/kernel/process.c
index c55ff71..afe3d6e 100644
--- a/arch/m68k/kernel/process.c
+++ b/arch/m68k/kernel/process.c
@@ -22,6 +22,7 @@
#include <linux/unistd.h>
#include <linux/ptrace.h>
#include <linux/user.h>
+#include <linux/pm.h>
#include <linux/reboot.h>
#include <linux/init_task.h>
#include <linux/mqueue.h>
@@ -77,8 +78,8 @@ void machine_halt(void)

void machine_power_off(void)
{
- if (mach_power_off)
- mach_power_off();
+ if (pm_power_off)
+ pm_power_off();
for (;;);
}

diff --git a/arch/m68k/kernel/setup_mm.c b/arch/m68k/kernel/setup_mm.c
index 5b8ec4d..002fea6 100644
--- a/arch/m68k/kernel/setup_mm.c
+++ b/arch/m68k/kernel/setup_mm.c
@@ -96,7 +96,6 @@ EXPORT_SYMBOL(mach_get_rtc_pll);
EXPORT_SYMBOL(mach_set_rtc_pll);
void (*mach_reset)( void );
void (*mach_halt)( void );
-void (*mach_power_off)( void );
long mach_max_dma_address = 0x00ffffff; /* default set to the lower 16MB */
#ifdef CONFIG_HEARTBEAT
void (*mach_heartbeat) (int);
diff --git a/arch/m68k/kernel/setup_no.c b/arch/m68k/kernel/setup_no.c
index 88c27d9..1520156 100644
--- a/arch/m68k/kernel/setup_no.c
+++ b/arch/m68k/kernel/setup_no.c
@@ -55,7 +55,6 @@ int (*mach_hwclk) (int, struct rtc_time*);
/* machine dependent reboot functions */
void (*mach_reset)(void);
void (*mach_halt)(void);
-void (*mach_power_off)(void);

#ifdef CONFIG_M68000
#if defined(CONFIG_M68328)
diff --git a/arch/m68k/mac/config.c b/arch/m68k/mac/config.c
index a471eab..677913ff 100644
--- a/arch/m68k/mac/config.c
+++ b/arch/m68k/mac/config.c
@@ -16,6 +16,7 @@
#include <linux/tty.h>
#include <linux/console.h>
#include <linux/interrupt.h>
+#include <linux/pm.h>
/* keyb */
#include <linux/random.h>
#include <linux/delay.h>
@@ -159,7 +160,7 @@ void __init config_mac(void)
mach_set_clock_mmss = mac_set_clock_mmss;
mach_reset = mac_reset;
mach_halt = mac_poweroff;
- mach_power_off = mac_poweroff;
+ pm_power_off = mac_poweroff;
mach_max_dma_address = 0xffffffff;
#if defined(CONFIG_INPUT_M68K_BEEP) || defined(CONFIG_INPUT_M68K_BEEP_MODULE)
mach_beep = mac_mksound;
--
1.9.1
Guenter Roeck
2014-10-07 05:28:07 UTC
Permalink
Devicetree bindings are supposed to be operating system independent
and should thus not describe how a specific functionality is implemented
in Linux.

Cc: Rob Herring <robh+***@kernel.org>
Cc: Pawel Moll <***@arm.com>
Cc: Mark Rutland <***@arm.com>
Signed-off-by: Guenter Roeck <***@roeck-us.net>
---
Documentation/devicetree/bindings/mfd/as3722.txt | 3 +--
1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/Documentation/devicetree/bindings/mfd/as3722.txt b/Documentation/devicetree/bindings/mfd/as3722.txt
index 4f64b2a..0b2a609 100644
--- a/Documentation/devicetree/bindings/mfd/as3722.txt
+++ b/Documentation/devicetree/bindings/mfd/as3722.txt
@@ -122,8 +122,7 @@ Following are properties of regulator subnode.

Power-off:
=========
-AS3722 supports the system power off by turning off all its rail. This
-is provided through pm_power_off.
+AS3722 supports the system power off by turning off all its rails.
The device node should have the following properties to enable this
functionality
ams,system-power-controller: Boolean, to enable the power off functionality
--
1.9.1
Philippe Rétornaz
2014-10-07 07:46:59 UTC
Permalink
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:

[...]
Post by Guenter Roeck
+/*
+ * Notifier list for kernel code which wants to be called
+ * to power off the system.
+ */
+static ATOMIC_NOTIFIER_HEAD(poweroff_handler_list);
[...]
Post by Guenter Roeck
+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
Lee Jones
2014-10-07 07:52:38 UTC
Permalink
Post by Guenter Roeck
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.
=20
Make twl4030_power_off static as it is only called from the twl4030-p=
ower
Post by Guenter Roeck
driver.
=20
---
drivers/mfd/twl4030-power.c | 25 +++++++++++++++++++++----
include/linux/i2c/twl.h | 1 -
2 files changed, 21 insertions(+), 5 deletions(-)
=20
diff --git a/drivers/mfd/twl4030-power.c b/drivers/mfd/twl4030-power.=
c
Post by Guenter Roeck
index 4d3ff37..bd6b830 100644
--- a/drivers/mfd/twl4030-power.c
+++ b/drivers/mfd/twl4030-power.c
@@ -25,9 +25,10 @@
*/
=20
#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>
=20
@@ -611,7 +612,8 @@ twl4030_power_configure_resources(const struct tw=
l4030_power_data *pdata)
Post by Guenter Roeck
* 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 l=
ong unused1,
Post by Guenter Roeck
+ void *unused2)
{
int err;
=20
@@ -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;
}
=20
+static struct notifier_block twl4030_poweroff_nb =3D {
+ .notifier_call =3D twl4030_power_off,
+ .priority =3D 64,
64 out of what? How is this calculated? Wouldn't it be better to
define these?
Post by Guenter Roeck
+};
+
static bool twl4030_power_use_poweroff(const struct twl4030_power_da=
ta *pdata,
Post by Guenter Roeck
struct device_node *node)
{
@@ -836,7 +845,7 @@ static int twl4030_power_probe(struct platform_de=
vice *pdev)
Post by Guenter Roeck
}
=20
/* 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 =3D 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_d=
evice *pdev)
Post by Guenter Roeck
}
}
=20
- pm_power_off =3D twl4030_power_off;
+ err =3D 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.
Post by Guenter Roeck
+ /* Not a fatal error */
+ err =3D 0;
How about using your own variable for this? Then you don't have to
worry about resetting it.
Post by Guenter Roeck
+ }
}
=20
=20
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)?
Post by Guenter Roeck
return 0;
}
=20
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 {
};
=20
extern int twl4030_remove_script(u8 flags);
-extern void twl4030_power_off(void);
=20
struct twl4030_codec_data {
unsigned int digimic_delay; /* in ms */
--=20
Lee Jones
Linaro STMicroelectronics Landing Team Lead
Linaro.org =E2=94=82 Open source software for ARM SoCs
=46ollow Linaro: Facebook | Twitter | Blog
Lee Jones
2014-10-07 08:00:48 UTC
Permalink
Post by Guenter Roeck
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.
=20
---
drivers/mfd/ab8500-sysctrl.c | 26 +++++++++++++++-----------
1 file changed, 15 insertions(+), 11 deletions(-)
=20
diff --git a/drivers/mfd/ab8500-sysctrl.c b/drivers/mfd/ab8500-sysctr=
l.c
Post by Guenter Roeck
index 8e0dae5..677438f 100644
--- a/drivers/mfd/ab8500-sysctrl.c
+++ b/drivers/mfd/ab8500-sysctrl.c
@@ -6,6 +6,7 @@
[...]
Post by Guenter Roeck
+static int ab8500_power_off(struct notifier_block *this, unsigned lo=
ng unused1,
Post by Guenter Roeck
+ void *unused2)
{
sigset_t old;
sigset_t all;
@@ -34,11 +36,6 @@ static void ab8500_power_off(void)
struct power_supply *psy;
int ret;
=20
- if (sysctrl_dev =3D=3D NULL) {
- pr_err("%s: sysctrl not initialized\n", __func__);
- return;
- }
Can you explain the purpose of this change please?
Post by Guenter Roeck
/*
* If we have a charger connected and we're powering off,
* reboot into charge-only mode.
AB8500_STW4500CTRL1_SWRESET4500N);
(void)sigprocmask(SIG_SETMASK, &old, NULL);
}
+
+ return NOTIFY_DONE;
}
--=20
Lee Jones
Linaro STMicroelectronics Landing Team Lead
Linaro.org =E2=94=82 Open source software for ARM SoCs
=46ollow Linaro: Facebook | Twitter | Blog
Nicolas Ferre
2014-10-07 08:04:20 UTC
Permalink
Post by Guenter Roeck
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.
---
arch/arm/kernel/psci.c | 2 +-
arch/arm/mach-at91/board-gsia18s.c | 2 +-
arch/arm/mach-at91/setup.c | 4 ++--
For the 2 files above: NAK just because:
for the first one -> this file will be removed during 3.19 dev cycle.
for the second one -> the poweroff handlers are removed during the 3.18
cycle and converted in the appropriate poweroff drivers (in
drivers/power/reset/at91-poweroff.c).

So, can you remove these changes from your patch?

Thanks for your work, bye.
Post by Guenter Roeck
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);
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);
- 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) {
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;
/* 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;
/* 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;
--
Nicolas Ferre
Geert Uytterhoeven
2014-10-07 08:29:52 UTC
Permalink
Post by Guenter Roeck
Replace mach_power_off with pm_power_off to simplify the subsequent
move of pm_power_off to generic code.
Thanks!
Looks OK, so since you said it builds ;-)

Acked-by: Geert Uytterhoeven <***@linux-m68k.org>

Gr{oetje,eeting}s,

Geert

--
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- ***@linux-m68k.org

In personal conversations with technical people, I call myself a hacker. But
when I'm talking to journalists I just say "programmer" or something like that.
-- Linus Torvalds
Geert Uytterhoeven
2014-10-07 09:19:36 UTC
Permalink
Post by Guenter Roeck
Register with kernel poweroff handler instead of setting pm_power_off
directly.
As someone already mentioned, having #defines instead of hardcoded
numbers for the priorities would be nice.
Post by Guenter Roeck
+ register_poweroff_handler_simple(nf_poweroff, 128);
+ register_poweroff_handler_simple(mac_poweroff, 128);
Gr{oetje,eeting}s,

Geert

--
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- ***@linux-m68k.org

In personal conversations with technical people, I call myself a hacker. But
when I'm talking to journalists I just say "programmer" or something like that.
-- Linus Torvalds
Mark Rutland
2014-10-07 10:59:41 UTC
Permalink
Post by Guenter Roeck
Devicetree bindings are supposed to be operating system independent
and should thus not describe how a specific functionality is implemented
in Linux.
---
Documentation/devicetree/bindings/mfd/as3722.txt | 3 +--
1 file changed, 1 insertion(+), 2 deletions(-)
Thanks for the fix-up!

Acked-by: Mark Rutland <***@arm.com>

Mark.
Post by Guenter Roeck
diff --git a/Documentation/devicetree/bindings/mfd/as3722.txt b/Documentation/devicetree/bindings/mfd/as3722.txt
index 4f64b2a..0b2a609 100644
--- a/Documentation/devicetree/bindings/mfd/as3722.txt
+++ b/Documentation/devicetree/bindings/mfd/as3722.txt
@@ -122,8 +122,7 @@ Following are properties of regulator subnode.
=========
-AS3722 supports the system power off by turning off all its rail. This
-is provided through pm_power_off.
+AS3722 supports the system power off by turning off all its rails.
The device node should have the following properties to enable this
functionality
ams,system-power-controller: Boolean, to enable the power off functionality
--
1.9.1
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
More majordomo info at http://vger.kernel.org/majordomo-info.html
Mark Rutland
2014-10-07 11:02:19 UTC
Permalink
Post by Guenter Roeck
Replace reference to pm_power_off (which is an implementation detail)
and replace it with a more generic description of the driver's functionality.
---
Documentation/devicetree/bindings/power_supply/qnap-poweroff.txt | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/Documentation/devicetree/bindings/power_supply/qnap-poweroff.txt b/Documentation/devicetree/bindings/power_supply/qnap-poweroff.txt
index af25e77..1e2260a 100644
--- a/Documentation/devicetree/bindings/power_supply/qnap-poweroff.txt
+++ b/Documentation/devicetree/bindings/power_supply/qnap-poweroff.txt
@@ -3,8 +3,8 @@
QNAP NAS devices have a microcontroller controlling the main power
supply. This microcontroller is connected to UART1 of the Kirkwood and
Orion5x SoCs. Sending the character 'A', at 19200 baud, tells the
-microcontroller to turn the power off. This driver adds a handler to
-pm_power_off which is called to turn the power off.
+microcontroller to turn the power off. This driver installs a handler
+to power off the system.
I'd remove the last sentence -- the driver is also independent of the
HW, and the description of how the power off works at the HW level is
sufficient.

With that:

Acked-by: Mark Rutland <***@arm.com>

Thanks,
Mark.
--
To unsubscribe from this list: send the line "unsubscribe linux-acpi" in
the body of a message to ***@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Guenter Roeck
2014-10-07 15:57:13 UTC
Permalink
Post by Mark Rutland
Post by Guenter Roeck
Replace reference to pm_power_off (which is an implementation detail)
and replace it with a more generic description of the driver's functionality.
---
Documentation/devicetree/bindings/power_supply/qnap-poweroff.txt | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/Documentation/devicetree/bindings/power_supply/qnap-poweroff.txt b/Documentation/devicetree/bindings/power_supply/qnap-poweroff.txt
index af25e77..1e2260a 100644
--- a/Documentation/devicetree/bindings/power_supply/qnap-poweroff.txt
+++ b/Documentation/devicetree/bindings/power_supply/qnap-poweroff.txt
@@ -3,8 +3,8 @@
QNAP NAS devices have a microcontroller controlling the main power
supply. This microcontroller is connected to UART1 of the Kirkwood and
Orion5x SoCs. Sending the character 'A', at 19200 baud, tells the
-microcontroller to turn the power off. This driver adds a handler to
-pm_power_off which is called to turn the power off.
+microcontroller to turn the power off. This driver installs a handler
+to power off the system.
I'd remove the last sentence -- the driver is also independent of the
HW, and the description of how the power off works at the HW level is
sufficient.
Done.
Thanks!

Guenter
Mark Rutland
2014-10-07 11:03:32 UTC
Permalink
Post by Guenter Roeck
pm_power_off is an implementation detail. Replace it with a more generic
description of the driver's functionality.
---
Documentation/devicetree/bindings/gpio/gpio-poweroff.txt | 10 +++++-----
1 file changed, 5 insertions(+), 5 deletions(-)
diff --git a/Documentation/devicetree/bindings/gpio/gpio-poweroff.txt b/Documentation/devicetree/bindings/gpio/gpio-poweroff.txt
index d4eab92..c95a1a6 100644
--- a/Documentation/devicetree/bindings/gpio/gpio-poweroff.txt
+++ b/Documentation/devicetree/bindings/gpio/gpio-poweroff.txt
@@ -2,12 +2,12 @@ Driver a GPIO line that can be used to turn the power off.
The driver supports both level triggered and edge triggered power off.
At driver load time, the driver will request the given gpio line and
-install a pm_power_off handler. If the optional properties 'input' is
-not found, the GPIO line will be driven in the inactive
+install a handler to power off the system. If the optional properties
+'input' is not found, the GPIO line will be driven in the inactive
state. Otherwise its configured as an input.
-When the pm_power_off is called, the gpio is configured as an output,
-and drive active, so triggering a level triggered power off
+When the the poweroff handler is called, the gpio is configured as an
+output, and drive active, so triggering a level triggered power off
condition. This will also cause an inactive->active edge condition, so
triggering positive edge triggered power off. After a delay of 100ms,
the GPIO is set to inactive, thus causing an active->inactive edge,
- input : Initially configure the GPIO line as an input. Only reconfigure
- it to an output when the pm_power_off function is called. If this optional
+ it to an output when the poweroff handler is called. If this optional
property is not specified, the GPIO is initialized as an output in its
inactive state.
--
1.9.1
--
To unsubscribe from this list: send the line "unsubscribe linux-acpi" in
the body of a message to ***@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Andrew Lunn
2014-10-07 15:50:44 UTC
Permalink
Post by Guenter Roeck
pm_power_off is an implementation detail. Replace it with a more generic
description of the driver's functionality.
Acked-by: Andrew Lunn <***@lunn.ch>

Thanks
Andrew
Post by Guenter Roeck
---
Documentation/devicetree/bindings/gpio/gpio-poweroff.txt | 10 +++++-----
1 file changed, 5 insertions(+), 5 deletions(-)
diff --git a/Documentation/devicetree/bindings/gpio/gpio-poweroff.txt b/Documentation/devicetree/bindings/gpio/gpio-poweroff.txt
index d4eab92..c95a1a6 100644
--- a/Documentation/devicetree/bindings/gpio/gpio-poweroff.txt
+++ b/Documentation/devicetree/bindings/gpio/gpio-poweroff.txt
@@ -2,12 +2,12 @@ Driver a GPIO line that can be used to turn the power off.
The driver supports both level triggered and edge triggered power off.
At driver load time, the driver will request the given gpio line and
-install a pm_power_off handler. If the optional properties 'input' is
-not found, the GPIO line will be driven in the inactive
+install a handler to power off the system. If the optional properties
+'input' is not found, the GPIO line will be driven in the inactive
state. Otherwise its configured as an input.
-When the pm_power_off is called, the gpio is configured as an output,
-and drive active, so triggering a level triggered power off
+When the the poweroff handler is called, the gpio is configured as an
+output, and drive active, so triggering a level triggered power off
condition. This will also cause an inactive->active edge condition, so
triggering positive edge triggered power off. After a delay of 100ms,
the GPIO is set to inactive, thus causing an active->inactive edge,
- input : Initially configure the GPIO line as an input. Only reconfigure
- it to an output when the pm_power_off function is called. If this optional
+ it to an output when the poweroff handler is called. If this optional
property is not specified, the GPIO is initialized as an output in its
inactive state.
--
1.9.1
_______________________________________________
linux-arm-kernel mailing list
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
Andrew Lunn
2014-10-07 15:51:24 UTC
Permalink
Post by Guenter Roeck
Replace reference to pm_power_off (which is an implementation detail)
and replace it with a more generic description of the driver's functionality.
Acked-by: Andrew Lunn <***@lunn.ch>

Thanks
Andrew
Post by Guenter Roeck
---
Documentation/devicetree/bindings/power_supply/qnap-poweroff.txt | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/Documentation/devicetree/bindings/power_supply/qnap-poweroff.txt b/Documentation/devicetree/bindings/power_supply/qnap-poweroff.txt
index af25e77..1e2260a 100644
--- a/Documentation/devicetree/bindings/power_supply/qnap-poweroff.txt
+++ b/Documentation/devicetree/bindings/power_supply/qnap-poweroff.txt
@@ -3,8 +3,8 @@
QNAP NAS devices have a microcontroller controlling the main power
supply. This microcontroller is connected to UART1 of the Kirkwood and
Orion5x SoCs. Sending the character 'A', at 19200 baud, tells the
-microcontroller to turn the power off. This driver adds a handler to
-pm_power_off which is called to turn the power off.
+microcontroller to turn the power off. This driver installs a handler
+to power off the system.
Synology NAS devices use a similar scheme, but a different baud rate,
9600, and a different character, '1'.
--
1.9.1
_______________________________________________
linux-arm-kernel mailing list
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
Andrew Lunn
2014-10-07 16:00:56 UTC
Permalink
Post by Guenter Roeck
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.
Drop note that there can not be an additional instance of this driver.
The original reason no longer applies, it should be obvious that there
can only be one instance of the driver if static variables are used to
reflect its state, and support for multiple instances can now be added
easily if needed by avoiding static variables.
Do not create an error message if another poweroff handler has already been
registered. This is perfectly normal and acceptable.
Do not display a warning traceback if the poweroff handler fails to
power off the system. There may be other poweroff handlers.
I would prefer to keep the warning traceback. We found on some
hardware the GPIO transitions were too fast and it failed to power
off. Seeing the traceback gives an idea where to go look for the
problem.

Other than that,
Post by Guenter Roeck
---
drivers/power/reset/gpio-poweroff.c | 36 ++++++++++++++++++------------------
1 file changed, 18 insertions(+), 18 deletions(-)
diff --git a/drivers/power/reset/gpio-poweroff.c b/drivers/power/reset/gpio-poweroff.c
index ce849bc..e95a7a1 100644
--- a/drivers/power/reset/gpio-poweroff.c
+++ b/drivers/power/reset/gpio-poweroff.c
@@ -14,18 +14,18 @@
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/delay.h>
+#include <linux/notifier.h>
+#include <linux/pm.h>
#include <linux/platform_device.h>
#include <linux/gpio/consumer.h>
#include <linux/of_platform.h>
#include <linux/module.h>
-/*
- * Hold configuration here, cannot be more than one instance of the driver
- * since pm_power_off itself is global.
- */
static struct gpio_desc *reset_gpio;
-static void gpio_poweroff_do_poweroff(void)
+static int gpio_poweroff_do_poweroff(struct notifier_block *this,
+ unsigned long unused1, void *unused2)
+
{
BUG_ON(!reset_gpio);
@@ -42,20 +42,18 @@ static void gpio_poweroff_do_poweroff(void)
/* give it some time */
mdelay(3000);
- WARN_ON(1);
+ return NOTIFY_DONE;
}
+static struct notifier_block gpio_poweroff_nb = {
+ .notifier_call = gpio_poweroff_do_poweroff,
+ .priority = 64,
+};
+
static int gpio_poweroff_probe(struct platform_device *pdev)
{
bool input = false;
-
- /* If a pm_power_off function has already been added, leave it alone */
- if (pm_power_off != NULL) {
- dev_err(&pdev->dev,
- "%s: pm_power_off function already registered",
- __func__);
- return -EBUSY;
- }
+ int err;
reset_gpio = devm_gpiod_get(&pdev->dev, NULL);
if (IS_ERR(reset_gpio))
@@ -77,14 +75,16 @@ static int gpio_poweroff_probe(struct platform_device *pdev)
}
}
- pm_power_off = &gpio_poweroff_do_poweroff;
- return 0;
+ err = register_poweroff_handler(&gpio_poweroff_nb);
+ if (err)
+ dev_err(&pdev->dev, "Failed to register poweroff handler\n");
+
+ return err;
}
static int gpio_poweroff_remove(struct platform_device *pdev)
{
- if (pm_power_off == &gpio_poweroff_do_poweroff)
- pm_power_off = NULL;
+ unregister_poweroff_handler(&gpio_poweroff_nb);
return 0;
}
--
1.9.1
_______________________________________________
linux-arm-kernel mailing list
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
Andrew Lunn
2014-10-07 16:06:38 UTC
Permalink
Post by Guenter Roeck
Register with kernel poweroff handler instead of seting pm_power_off
directly. Register as poweroff handler of last resort since the driver
does not really power off the system but executes a restart.
I would not say last resort, this is how it is designed to work. There
is no way to turn the power off from with linux, it is designed that
u-boot will put the hardware into minimal power consumption until the
"power" button is pressed.

Other than that,

Acked-by: Andrew Lunn <***@lunn.ch>

Thanks
Andrew
Post by Guenter Roeck
---
drivers/power/reset/restart-poweroff.c | 25 ++++++++++++-------------
1 file changed, 12 insertions(+), 13 deletions(-)
diff --git a/drivers/power/reset/restart-poweroff.c b/drivers/power/reset/restart-poweroff.c
index edd707e..5437697 100644
--- a/drivers/power/reset/restart-poweroff.c
+++ b/drivers/power/reset/restart-poweroff.c
@@ -12,35 +12,34 @@
*/
#include <linux/kernel.h>
#include <linux/init.h>
+#include <linux/notifier.h>
#include <linux/platform_device.h>
#include <linux/of_platform.h>
#include <linux/module.h>
+#include <linux/pm.h>
#include <linux/reboot.h>
-#include <asm/system_misc.h>
-static void restart_poweroff_do_poweroff(void)
+static int restart_poweroff_do_poweroff(struct notifier_block *this,
+ unsigned long unused1, void *unused2)
{
reboot_mode = REBOOT_HARD;
machine_restart(NULL);
+
+ return NOTIFY_DONE;
}
+static struct notifier_block restart_poweroff_handler = {
+ .notifier_call = restart_poweroff_do_poweroff,
+};
+
static int restart_poweroff_probe(struct platform_device *pdev)
{
- /* If a pm_power_off function has already been added, leave it alone */
- if (pm_power_off != NULL) {
- dev_err(&pdev->dev,
- "pm_power_off function already registered");
- return -EBUSY;
- }
-
- pm_power_off = &restart_poweroff_do_poweroff;
- return 0;
+ return register_poweroff_handler(&restart_poweroff_handler);
}
static int restart_poweroff_remove(struct platform_device *pdev)
{
- if (pm_power_off == &restart_poweroff_do_poweroff)
- pm_power_off = NULL;
+ unregister_poweroff_handler(&restart_poweroff_handler);
return 0;
}
--
1.9.1
_______________________________________________
linux-arm-kernel mailing list
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
Rob Landley
2014-10-07 16:21:11 UTC
Permalink
Post by Guenter Roeck
Devicetree bindings are supposed to be operating system independent
and should thus not describe how a specific functionality is implemented
in Linux.
So your argument is that linux/Documentation/devicetree/bindings should
not be specific to Linux. Merely hosted in the Linux kernel source
repository.

Well that's certainly a point of view.

Rob
Guenter Roeck
2014-10-07 16:31:31 UTC
Permalink
Post by Rob Landley
Post by Guenter Roeck
Devicetree bindings are supposed to be operating system independent
and should thus not describe how a specific functionality is implemented
in Linux.
So your argument is that linux/Documentation/devicetree/bindings should
not be specific to Linux. Merely hosted in the Linux kernel source
repository.
Well that's certainly a point of view.
Not specifically my argument, really, and nothing new either. But, yes, I do
think that devicetree bindings descriptions should not include implementation
details, especially since those may change over time (as is the case here).

Thanks,
Guenter
Mark Rutland
2014-10-07 16:58:35 UTC
Permalink
Post by Rob Landley
Post by Guenter Roeck
Devicetree bindings are supposed to be operating system independent
and should thus not describe how a specific functionality is implemented
in Linux.
So your argument is that linux/Documentation/devicetree/bindings should
not be specific to Linux. Merely hosted in the Linux kernel source
repository.
Precisely. If nothing else as a general guideline this keeps us honest,
and prevents us from embedding arbitrary implementation details into
bidnings that cause pain later when we want to change things at either
end.

There are already otehr users of these bindings, so we can't really
claim they're strictly Linux-specific anyhow.
Post by Rob Landley
Well that's certainly a point of view.
As far as I am aware, it's the point of view shared by the device tree
maintainers, and it's been that way for a while.

I don't really follow your concern. For one thing were this followed
more strictly this file wouldn't need patching at all to correct for
this Linux-internal rework...

Thanks,
Mark.
David Daney
2014-10-07 16:59:29 UTC
Permalink
Post by Guenter Roeck
Post by Rob Landley
Post by Guenter Roeck
Devicetree bindings are supposed to be operating system independent
and should thus not describe how a specific functionality is implemented
in Linux.
So your argument is that linux/Documentation/devicetree/bindings should
not be specific to Linux. Merely hosted in the Linux kernel source
repository.
Well that's certainly a point of view.
Not specifically my argument, really, and nothing new either. But, yes, I do
think that devicetree bindings descriptions should not include implementation
details, especially since those may change over time (as is the case here).
I fully agree.

Many device trees come from outside the kernel (i.e. they are supplied
by the system boot environment). Obviously these device trees cannot be
changed at the whim of kernel developers, *and* it is perfectly
reasonable to think that software other than the Linux kernel will run
on this type of system too.

So yes, it is really true, device trees are not a Linux kernel private
implementation detail, they are really an external ABI that, although
documented in the kernel source tree, cannot be changed in incompatible
ways as time progresses.

David Daney
Rob Landley
2014-10-07 17:10:58 UTC
Permalink
Post by David Daney
Post by Guenter Roeck
Post by Rob Landley
Post by Guenter Roeck
Devicetree bindings are supposed to be operating system independent
and should thus not describe how a specific functionality is
implemented
in Linux.
So your argument is that linux/Documentation/devicetree/bindings should
not be specific to Linux. Merely hosted in the Linux kernel source
repository.
Well that's certainly a point of view.
Not specifically my argument, really, and nothing new either. But,
yes, I do
think that devicetree bindings descriptions should not include
implementation
details, especially since those may change over time (as is the case
here).
I fully agree.
Many device trees come from outside the kernel (i.e. they are supplied
by the system boot environment). Obviously these device trees cannot be
changed at the whim of kernel developers, *and* it is perfectly
reasonable to think that software other than the Linux kernel will run
on this type of system too.
So yes, it is really true, device trees are not a Linux kernel private
implementation detail, they are really an external ABI that, although
documented in the kernel source tree, cannot be changed in incompatible
ways as time progresses.
Ah. Existing thing with backstory among the in-crowd, so I'll assume
"git subtree" was previously suggested and you had that discussion
already and decided against it.

Carry on,

Rob
Rafael J. Wysocki
2014-10-07 23:41:56 UTC
Permalink
Post by Guenter Roeck
Poweroff handlers may now be installed with register_poweroff_handler.
Use the new API function have_kernel_poweroff to determine if a poweroff
handler has been installed.
ACK
Post by Guenter Roeck
---
kernel/power/hibernate.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/kernel/power/hibernate.c b/kernel/power/hibernate.c
index a9dfa79..20353c5 100644
--- a/kernel/power/hibernate.c
+++ b/kernel/power/hibernate.c
@@ -602,7 +602,7 @@ static void power_down(void)
hibernation_platform_enter();
- if (pm_power_off)
+ if (have_kernel_poweroff())
kernel_power_off();
break;
#ifdef CONFIG_SUSPEND
--
I speak only for myself.
Rafael J. Wysocki, Intel Open Source Technology Center.
Rafael J. Wysocki
2014-10-07 23:43:07 UTC
Permalink
Post by Guenter Roeck
No users of pm_power_off are left, so it is safe to remove the function.
ACK
Post by Guenter Roeck
---
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);
--
I speak only for myself.
Rafael J. Wysocki, Intel Open Source Technology Center.
Catalin Marinas
2014-10-09 10:28:55 UTC
Permalink
diff --git a/arch/arm64/kernel/process.c b/arch/arm64/kernel/process.c
index e0ef8ba..db396bb 100644
--- a/arch/arm64/kernel/process.c
+++ b/arch/arm64/kernel/process.c
@@ -94,8 +94,6 @@ void soft_restart(unsigned long addr)
/*
* Function pointers to optional machine specific functions
*/
-void (*pm_power_off)(void);
-EXPORT_SYMBOL_GPL(pm_power_off);
void (*arm_pm_restart)(enum reboot_mode reboot_mode, const char *cmd);
@@ -155,8 +153,7 @@ void machine_power_off(void)
{
local_irq_disable();
smp_send_stop();
- if (pm_power_off)
- pm_power_off();
+ do_kernel_poweroff();
}
Acked-by: Catalin Marinas <***@arm.com>
Pavel Machek
2014-10-09 10:31:43 UTC
Permalink
Hi!
Post by Guenter Roeck
+/**
+ * register_poweroff_handler_simple - Register function to be called to power off
+ * the system
+ * register_poweroff_handler.
+ *
+ * This is a simplified version of register_poweroff_handler. It does not
+ * take a notifier as argument, but a function pointer. The function
+ * registers a poweroff handler with specified priority. Poweroff
+ * handlers registered with this function can not be unregistered,
+ * and only a single poweroff handler can be installed using it.
+ *
+ * This function must not be called from modules and is therefore
+ * not exported.
+ *
+ * Returns -EBUSY if a poweroff handler has already been registered
+ * using register_poweroff_handler_simple. Otherwise returns zero,
+ * since atomic_notifier_chain_register() currently always returns zero.
+ */
+int register_poweroff_handler_simple(void (*handler)(void), int priority)
+{
+ char symname[KSYM_NAME_LEN];
+
+ if (poweroff_handler_data.handler) {
+ lookup_symbol_name((unsigned long)poweroff_handler_data.handler,
+ symname);
+ pr_warn("Poweroff function already registered (%s)", symname);
+ lookup_symbol_name((unsigned long)handler, symname);
+ pr_cont(", cannot register %s\n", symname);
+ return -EBUSY;
+ }
Dunno, are you maybe overdoing the debugging infrastructure a bit?
This is not going to happen in production, and if it does happen,
developer can look the symbol name himself.
Pavel
--
(english) http://www.livejournal.com/~pavelmachek
(cesky, pictures) http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html
Guenter Roeck
2014-10-09 15:38:36 UTC
Permalink
Post by Pavel Machek
Hi!
Post by Guenter Roeck
+/**
+ * register_poweroff_handler_simple - Register function to be called to power off
+ * the system
+ * register_poweroff_handler.
+ *
+ * This is a simplified version of register_poweroff_handler. It does not
+ * take a notifier as argument, but a function pointer. The function
+ * registers a poweroff handler with specified priority. Poweroff
+ * handlers registered with this function can not be unregistered,
+ * and only a single poweroff handler can be installed using it.
+ *
+ * This function must not be called from modules and is therefore
+ * not exported.
+ *
+ * Returns -EBUSY if a poweroff handler has already been registered
+ * using register_poweroff_handler_simple. Otherwise returns zero,
+ * since atomic_notifier_chain_register() currently always returns zero.
+ */
+int register_poweroff_handler_simple(void (*handler)(void), int priority)
+{
+ char symname[KSYM_NAME_LEN];
+
+ if (poweroff_handler_data.handler) {
+ lookup_symbol_name((unsigned long)poweroff_handler_data.handler,
+ symname);
+ pr_warn("Poweroff function already registered (%s)", symname);
+ lookup_symbol_name((unsigned long)handler, symname);
+ pr_cont(", cannot register %s\n", symname);
+ return -EBUSY;
+ }
Dunno, are you maybe overdoing the debugging infrastructure a bit?
This is not going to happen in production, and if it does happen,
developer can look the symbol name himself.
On the other side, I don't think it hurts to have that message.
Anyway, I'll use %ps as suggested by Geert.

Guenter
Pavel Machek
2014-10-09 10:32:54 UTC
Permalink
Post by Guenter Roeck
Poweroff handlers may now be installed with register_poweroff_handler.
Use the new API function have_kernel_poweroff to determine if a poweroff
handler has been installed.
---
kernel/power/hibernate.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/kernel/power/hibernate.c b/kernel/power/hibernate.c
index a9dfa79..20353c5 100644
--- a/kernel/power/hibernate.c
+++ b/kernel/power/hibernate.c
@@ -602,7 +602,7 @@ static void power_down(void)
hibernation_platform_enter();
- if (pm_power_off)
+ if (have_kernel_poweroff())
kernel_power_off();
break;
poweroff -> power_off.

But if you are playing with this, anyway... does it make sense to
introduce kernel_power_off() that just works, no need to check
have_..?
Pavel
--
(english) http://www.livejournal.com/~pavelmachek
(cesky, pictures) http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html
Catalin Marinas
2014-10-09 10:36:56 UTC
Permalink
Post by Lee Jones
Post by Guenter Roeck
--- a/drivers/mfd/ab8500-sysctrl.c
+++ b/drivers/mfd/ab8500-sysctrl.c
@@ -6,6 +6,7 @@
[...]
Post by Guenter Roeck
+static int ab8500_power_off(struct notifier_block *this, unsigned long unused1,
+ void *unused2)
{
sigset_t old;
sigset_t all;
@@ -34,11 +36,6 @@ static void ab8500_power_off(void)
struct power_supply *psy;
int ret;
- if (sysctrl_dev == NULL) {
- pr_err("%s: sysctrl not initialized\n", __func__);
- return;
- }
Can you explain the purpose of this change please?
I guess it's because the sysctrl_dev is already initialised when
registering the power_off handler, so there isn't a way to call the
above function with a NULL sysctrl_dev. Probably even with the original
code you didn't need this check (after some race fix in
ab8500_sysctrl_remove but races is one of the things Guenter's patches
try to address).
--
Catalin
Lee Jones
2014-10-09 10:49:27 UTC
Permalink
Post by Catalin Marinas
Post by Lee Jones
Post by Guenter Roeck
--- a/drivers/mfd/ab8500-sysctrl.c
+++ b/drivers/mfd/ab8500-sysctrl.c
@@ -6,6 +6,7 @@
=20
[...]
=20
Post by Guenter Roeck
+static int ab8500_power_off(struct notifier_block *this, unsigne=
d long unused1,
Post by Catalin Marinas
Post by Lee Jones
Post by Guenter Roeck
+ void *unused2)
{
sigset_t old;
sigset_t all;
@@ -34,11 +36,6 @@ static void ab8500_power_off(void)
struct power_supply *psy;
int ret;
=20
- if (sysctrl_dev =3D=3D NULL) {
- pr_err("%s: sysctrl not initialized\n", __func__);
- return;
- }
=20
Can you explain the purpose of this change please?
=20
I guess it's because the sysctrl_dev is already initialised when
registering the power_off handler, so there isn't a way to call the
above function with a NULL sysctrl_dev. Probably even with the origin=
al
Post by Catalin Marinas
code you didn't need this check (after some race fix in
ab8500_sysctrl_remove but races is one of the things Guenter's patche=
s
Post by Catalin Marinas
try to address).
Sounds reasonable, although I think this change should be part of
another patch.

--=20
Lee Jones
Linaro STMicroelectronics Landing Team Lead
Linaro.org =E2=94=82 Open source software for ARM SoCs
=46ollow Linaro: Facebook | Twitter | Blog
--
To unsubscribe from this list: send the line "unsubscribe linux-acpi" i=
n
the body of a message to ***@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Guenter Roeck
2014-10-09 13:26:46 UTC
Permalink
Post by Lee Jones
Post by Catalin Marinas
Post by Lee Jones
Post by Guenter Roeck
--- a/drivers/mfd/ab8500-sysctrl.c
+++ b/drivers/mfd/ab8500-sysctrl.c
@@ -6,6 +6,7 @@
[...]
Post by Guenter Roeck
+static int ab8500_power_off(struct notifier_block *this, unsigned long unused1,
+ void *unused2)
{
sigset_t old;
sigset_t all;
@@ -34,11 +36,6 @@ static void ab8500_power_off(void)
struct power_supply *psy;
int ret;
- if (sysctrl_dev == NULL) {
- pr_err("%s: sysctrl not initialized\n", __func__);
- return;
- }
Can you explain the purpose of this change please?
I guess it's because the sysctrl_dev is already initialised when
registering the power_off handler, so there isn't a way to call the
above function with a NULL sysctrl_dev. Probably even with the original
code you didn't need this check (after some race fix in
ab8500_sysctrl_remove but races is one of the things Guenter's patches
try to address).
Sounds reasonable, although I think this change should be part of
another patch.
Sure, no problem. I'll split this into two patches.

Since we are at it, any idea what to do with the restart function
in the same file ? It is not used anywhere.

Guenter

--
To unsubscribe from this list: send the line "unsubscribe linux-alpha" in
the body of a message to ***@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Lee Jones
2014-10-09 13:33:55 UTC
Permalink
Post by Guenter Roeck
Post by Lee Jones
Post by Catalin Marinas
Post by Lee Jones
Post by Guenter Roeck
--- a/drivers/mfd/ab8500-sysctrl.c
+++ b/drivers/mfd/ab8500-sysctrl.c
@@ -6,6 +6,7 @@
[...]
Post by Guenter Roeck
+static int ab8500_power_off(struct notifier_block *this, unsigne=
d long unused1,
Post by Guenter Roeck
Post by Lee Jones
Post by Catalin Marinas
Post by Lee Jones
Post by Guenter Roeck
+ void *unused2)
{
sigset_t old;
sigset_t all;
@@ -34,11 +36,6 @@ static void ab8500_power_off(void)
struct power_supply *psy;
int ret;
- if (sysctrl_dev =3D=3D NULL) {
- pr_err("%s: sysctrl not initialized\n", __func__);
- return;
- }
Can you explain the purpose of this change please?
I guess it's because the sysctrl_dev is already initialised when
registering the power_off handler, so there isn't a way to call the
above function with a NULL sysctrl_dev. Probably even with the orig=
inal
Post by Guenter Roeck
Post by Lee Jones
Post by Catalin Marinas
code you didn't need this check (after some race fix in
ab8500_sysctrl_remove but races is one of the things Guenter's patc=
hes
Post by Guenter Roeck
Post by Lee Jones
Post by Catalin Marinas
try to address).
Sounds reasonable, although I think this change should be part of
another patch.
Sure, no problem. I'll split this into two patches.
=20
Since we are at it, any idea what to do with the restart function
in the same file ? It is not used anywhere.
You can strip it out with Linus Walleij's Ack. Or I'll be happy to do
it?

--=20
Lee Jones
Linaro STMicroelectronics Landing Team Lead
Linaro.org =E2=94=82 Open source software for ARM SoCs
=46ollow Linaro: Facebook | Twitter | Blog
Guenter Roeck
2014-10-09 15:45:15 UTC
Permalink
Post by Lee Jones
Post by Guenter Roeck
Post by Lee Jones
Post by Catalin Marinas
Post by Lee Jones
Post by Guenter Roeck
--- a/drivers/mfd/ab8500-sysctrl.c
+++ b/drivers/mfd/ab8500-sysctrl.c
@@ -6,6 +6,7 @@
[...]
Post by Guenter Roeck
+static int ab8500_power_off(struct notifier_block *this, unsigned long unused1,
+ void *unused2)
{
sigset_t old;
sigset_t all;
@@ -34,11 +36,6 @@ static void ab8500_power_off(void)
struct power_supply *psy;
int ret;
- if (sysctrl_dev == NULL) {
- pr_err("%s: sysctrl not initialized\n", __func__);
- return;
- }
Can you explain the purpose of this change please?
I guess it's because the sysctrl_dev is already initialised when
registering the power_off handler, so there isn't a way to call the
above function with a NULL sysctrl_dev. Probably even with the original
code you didn't need this check (after some race fix in
ab8500_sysctrl_remove but races is one of the things Guenter's patches
try to address).
Sounds reasonable, although I think this change should be part of
another patch.
Sure, no problem. I'll split this into two patches.
Since we are at it, any idea what to do with the restart function
in the same file ? It is not used anywhere.
You can strip it out with Linus Walleij's Ack. Or I'll be happy to do
it?
I'll strip it out in a 3rd patch.

Guenter
Guenter Roeck
2014-10-09 15:54:04 UTC
Permalink
Post by Lee Jones
Post by Catalin Marinas
Post by Lee Jones
Post by Guenter Roeck
--- a/drivers/mfd/ab8500-sysctrl.c
+++ b/drivers/mfd/ab8500-sysctrl.c
@@ -6,6 +6,7 @@
[...]
Post by Guenter Roeck
+static int ab8500_power_off(struct notifier_block *this, unsigned long unused1,
+ void *unused2)
{
sigset_t old;
sigset_t all;
@@ -34,11 +36,6 @@ static void ab8500_power_off(void)
struct power_supply *psy;
int ret;
- if (sysctrl_dev == NULL) {
- pr_err("%s: sysctrl not initialized\n", __func__);
- return;
- }
Can you explain the purpose of this change please?
I guess it's because the sysctrl_dev is already initialised when
registering the power_off handler, so there isn't a way to call the
above function with a NULL sysctrl_dev. Probably even with the original
code you didn't need this check (after some race fix in
ab8500_sysctrl_remove but races is one of the things Guenter's patches
try to address).
Sounds reasonable, although I think this change should be part of
another patch.
Turns out the options are to either drop the check or to use the device
managed function to register the poweroff handler. I decided to keep
the check and use the device managed function.

Guenter

Catalin Marinas
2014-10-09 10:41:04 UTC
Permalink
Post by Guenter Roeck
Register with kernel poweroff handler instead of setting pm_power_off
directly.
---
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);
of_node_put(np);
Acked-by: Catalin Marinas <catalin.marinas-***@public.gmane.org>
Geert Uytterhoeven
2014-10-09 11:31:40 UTC
Permalink
Post by Guenter Roeck
+int register_poweroff_handler_simple(void (*handler)(void), int priority)
+{
+ char symname[KSYM_NAME_LEN];
+
+ if (poweroff_handler_data.handler) {
+ lookup_symbol_name((unsigned long)poweroff_handler_data.handler,
+ symname);
+ pr_warn("Poweroff function already registered (%s)", symname);
+ lookup_symbol_name((unsigned long)handler, symname);
+ pr_cont(", cannot register %s\n", symname);
Doesn't %ps work to look up symbols?

pr_warn("Poweroff function already registered (%ps), cannot register
%ps\n", poweroff_handler_data.handler, handler);
Post by Guenter Roeck
+ return -EBUSY;
+ }
Gr{oetje,eeting}s,

Geert

--
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- ***@linux-m68k.org

In personal conversations with technical people, I call myself a hacker. But
when I'm talking to journalists I just say "programmer" or something like that.
-- Linus Torvalds
Guenter Roeck
2014-10-09 13:24:13 UTC
Permalink
Post by Pavel Machek
Post by Guenter Roeck
Poweroff handlers may now be installed with register_poweroff_handler.
Use the new API function have_kernel_poweroff to determine if a poweroff
handler has been installed.
---
kernel/power/hibernate.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/kernel/power/hibernate.c b/kernel/power/hibernate.c
index a9dfa79..20353c5 100644
--- a/kernel/power/hibernate.c
+++ b/kernel/power/hibernate.c
@@ -602,7 +602,7 @@ static void power_down(void)
hibernation_platform_enter();
- if (pm_power_off)
+ if (have_kernel_poweroff())
kernel_power_off();
break;
poweroff -> power_off.
As mentioned in my other reply, that was on purpose to distinguish
existing functions from poweroff handler functions.
Post by Pavel Machek
But if you are playing with this, anyway... does it make sense to
introduce kernel_power_off() that just works, no need to check
have_..?
Pavel
I am trying not to change existing behavior.

kernel_power_off is an existing function which does some cleanup
before calling machine_power_off which in turn calls do_kernel_poweroff
(or currently pm_power_off and may do some other machine specific stuff.

Sure, poweroff handling could be unified further. We could decide to
enter an endless loop if machine_power_off() returns, or we could decide
to dump a warning or panic in this case. But that is all separate from
the issue I am trying to solve here, which is to provide a capability to
register more than one poweroff handler. It would also not be that simple,
since some architectures call machine_power_off() directly from various
places.

Guenter
Loading...