Discussion:
[RFC PATCH 00/16] kernel: Add support for poweroff handler call chain
Guenter Roeck
2014-09-30 18:00:40 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.

The poweroff handler is introduced in multiple steps

1) Implement poweroff handler API.
Patch 01/16.
2) Ensure that pm_power_off is only called from machine_restart.
Patches 02/16 and 03/16.
3) Implement call to poweroff handler in architecture specific
machine_restart code.
Patches 03/16 to 13/16.
4) Convert all drivers to register with poweroff handler
instead of setting pm_power_off directly.
Patches 15/16 and 16/16 (examples).
This can be done in two steps: First convert all drivers which can
be built as modules, then convert the remaining drivers (possibly after
unexporting pm_powr_off).
5) Unexport pm_power_off for all architectures,
and drop it entirely for architectures where it is not really used.
6) [optional] Convert machine specific architecture code to register
with poweroff handler instead of setting pm_power_off directly,
and remove pm_power_off entirely from the system.

Cc: Andrew Morton <***@linux-foundation.org>
Cc: Heiko Stuebner <***@sntech.de>
Cc: Romain Perier <***@gmail.com>
Cc: James E.J. Bottomley <***@parisc-linux.org>
Cc: Helge Deller <***@gmx.de>
Cc: Russell King <***@arm.linux.org.uk>
Cc: Catalin Marinas <***@arm.com>
Cc: Will Deacon <***@arm.com>
Cc: Haavard Skinnemoen <***@gmail.com>
Cc: Hans-Christian Egtvedt <***@samfundet.no>
Cc: Mark Salter <***@redhat.com>
Cc: Aurelien Jacquiot <a-***@ti.com>
Cc: Tony Luck <***@intel.com>
Cc: Fenghua Yu <***@intel.com>
Cc: James Hogan <***@imgtec.com>
Cc: Ralf Baechle <***@linux-mips.org>
Cc: Guan Xuetao <***@mprc.pku.edu.cn>
Cc: Thomas Gleixner <***@linutronix.de>
Cc: Ingo Molnar <***@redhat.com>
Cc: H. Peter Anvin <***@zytor.com>
Cc: Konrad Rzeszutek Wilk <***@oracle.com>
Cc: Boris Ostrovsky <***@oracle.com>
Cc: Sebastian Reichel <***@kernel.org>
Cc: Dmitry Eremin-Solenikov <***@gmail.com>
Cc: David Woodhouse <***@infradead.org>
Cc: Samuel Ortiz <***@linux.intel.com>
Cc: Lee Jones <***@linaro.org>

----------------------------------------------------------------
Guenter Roeck (16):
kernel: Add support for poweroff handler call chain
hwmon: (ab8500) Call kernel_power_off instead of pm_power_off
parisc: support poweroff through poweroff handler call chain
arm: support poweroff through poweroff handler call chain
arm64: support poweroff through poweroff handler call chain
avr32: support poweroff through poweroff handler call chain
c6x: support poweroff through poweroff handler call chain
ia64: support poweroff through poweroff handler call chain
metag: support poweroff through poweroff handler call chain
mips: support poweroff through poweroff handler call chain
sh: support poweroff through poweroff handler call chain
unicore32: support poweroff through poweroff handler call chain
x86: support poweroff through poweroff handler call chain
x86/xen: support poweroff through poweroff handler call chain
power/reset: restart-poweroff: Register with kernel poweroff handler
mfd: palmas: Register with kernel poweroff handler

arch/arm/kernel/process.c | 2 +
arch/arm64/kernel/process.c | 2 +
arch/avr32/kernel/process.c | 2 +
arch/c6x/kernel/process.c | 2 +
arch/ia64/kernel/process.c | 2 +
arch/metag/kernel/process.c | 2 +
arch/mips/kernel/reset.c | 2 +
arch/parisc/kernel/process.c | 7 ++-
arch/sh/kernel/reboot.c | 2 +
arch/unicore32/kernel/process.c | 2 +
arch/x86/kernel/reboot.c | 4 ++
arch/x86/xen/enlighten.c | 2 +
drivers/hwmon/ab8500.c | 5 ++-
drivers/mfd/palmas.c | 30 +++++++------
drivers/parisc/power.c | 3 +-
drivers/power/reset/restart-poweroff.c | 24 +++++-----
include/linux/mfd/palmas.h | 3 ++
include/linux/reboot.h | 4 ++
kernel/reboot.c | 81 ++++++++++++++++++++++++++++++++++
19 files changed, 149 insertions(+), 32 deletions(-)
--
To unsubscribe from this list: send the line "unsubscribe linux-parisc" in
the body of a message to ***@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Guenter Roeck
2014-09-30 18:00:41 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: James E.J. Bottomley <***@parisc-linux.org>
Cc: Helge Deller <***@gmx.de>
Cc: Russell King <***@arm.linux.org.uk>
Cc: Catalin Marinas <***@arm.com>
Cc: Will Deacon <***@arm.com>
Cc: Haavard Skinnemoen <***@gmail.com>
Cc: Hans-Christian Egtvedt <***@samfundet.no>
Cc: Mark Salter <***@redhat.com>
Cc: Aurelien Jacquiot <a-***@ti.com>
Cc: Tony Luck <***@intel.com>
Cc: Fenghua Yu <***@intel.com>
Cc: James Hogan <***@imgtec.com>
Cc: Ralf Baechle <***@linux-mips.org>
Cc: Guan Xuetao <***@mprc.pku.edu.cn>
Cc: Thomas Gleixner <***@linutronix.de>
Cc: Ingo Molnar <***@redhat.com>
Cc: H. Peter Anvin <***@zytor.com>
Cc: Konrad Rzeszutek Wilk <***@oracle.com>
Cc: Boris Ostrovsky <***@oracle.com>
Cc: Sebastian Reichel <***@kernel.org>
Cc: Dmitry Eremin-Solenikov <***@gmail.com>
Cc: David Woodhouse <***@infradead.org>
Cc: Samuel Ortiz <***@linux.intel.com>
Cc: Lee Jones <***@linaro.org>
Signed-off-by: Guenter Roeck <***@roeck-us.net>
---
include/linux/reboot.h | 4 +++
kernel/reboot.c | 81 ++++++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 85 insertions(+)

diff --git a/include/linux/reboot.h b/include/linux/reboot.h
index 67fc8fc..b172951 100644
--- a/include/linux/reboot.h
+++ b/include/linux/reboot.h
@@ -38,6 +38,10 @@ extern int reboot_force;
extern int register_reboot_notifier(struct notifier_block *);
extern int unregister_reboot_notifier(struct notifier_block *);

+extern int register_poweroff_handler(struct notifier_block *);
+extern int unregister_poweroff_handler(struct notifier_block *);
+extern void do_kernel_poweroff(void);
+
extern int register_restart_handler(struct notifier_block *);
extern int unregister_restart_handler(struct notifier_block *);
extern void do_kernel_restart(char *cmd);
diff --git a/kernel/reboot.c b/kernel/reboot.c
index 5925f5a..bdfab65 100644
--- a/kernel/reboot.c
+++ b/kernel/reboot.c
@@ -106,6 +106,87 @@ EXPORT_SYMBOL(unregister_reboot_notifier);

/*
* 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
+ * 128: Default poweroff handler; use if no other
+ * poweroff handler is expected to be available,
+ * and/or if poweroff functionality is
+ * sufficient to poweroff the entire system
+ * 255: Highest priority poweroff handler, will
+ * preempt all other poweroff handlers
+ *
+ * Registers a function with code to be called to poweroff the
+ * system.
+ *
+ * Registered functions will be called from machine_power_off as last
+ * step of the poweroff sequence (if the architecture specific
+ * machine_power_off function calls do_kernel_poweroff - see below
+ * for details).
+ * Registered functions are expected to poweroff the system immediately.
+ * If more than one function is registered, the poweroff handler priority
+ * selects which function will be called first.
+ *
+ * Poweroff handlers are expected to be registered from non-architecture
+ * code, typically from drivers. A typical use case would be a system
+ * where poweroff functionality is provided through a mfd driver. Multiple
+ * poweroff handlers may exist; for example, one poweroff handler might
+ * poweroff the entire system, while another only powers off the CPU.
+ * 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 poweroff the system is 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);
+
+/**
+ * do_kernel_poweroff - Execute kernel poweroff handler call chain
+ *
+ * Calls functions registered with register_poweroff_handler.
+ *
+ * Expected to be called from machine_poweroff 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);
+}
+
+/*
+ * Notifier list for kernel code which wants to be called
* to restart the system.
*/
static ATOMIC_NOTIFIER_HEAD(restart_handler_list);
--
1.9.1

--
To unsubscribe from this list: send the line "unsubscribe linux-pm" in
the body of a message to ***@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Guenter Roeck
2014-09-30 18:00:48 UTC
Permalink
The kernel core now supports a poweroff handler call chain
to remove power from the system. Call it if pm_power_off
is set to NULL.

Cc: Tony Luck <***@intel.com>
Cc: Fenghua Yu <***@intel.com>
Signed-off-by: Guenter Roeck <***@roeck-us.net>
---
arch/ia64/kernel/process.c | 2 ++
1 file changed, 2 insertions(+)

diff --git a/arch/ia64/kernel/process.c b/arch/ia64/kernel/process.c
index deed6fa..489b0d8 100644
--- a/arch/ia64/kernel/process.c
+++ b/arch/ia64/kernel/process.c
@@ -677,6 +677,8 @@ machine_power_off (void)
{
if (pm_power_off)
pm_power_off();
+ else
+ do_kernel_poweroff();
machine_halt();
}
--
1.9.1
Guenter Roeck
2014-09-30 18:00:52 UTC
Permalink
The kernel core now supports a poweroff handler call chain
to remove power from the system. Call it if pm_power_off
is set to NULL.

Cc: Guan Xuetao <***@mprc.pku.edu.cn>
Signed-off-by: Guenter Roeck <***@roeck-us.net>
---
arch/unicore32/kernel/process.c | 2 ++
1 file changed, 2 insertions(+)

diff --git a/arch/unicore32/kernel/process.c b/arch/unicore32/kernel/process.c
index b008e99..421fde6 100644
--- a/arch/unicore32/kernel/process.c
+++ b/arch/unicore32/kernel/process.c
@@ -66,6 +66,8 @@ void machine_power_off(void)
{
if (pm_power_off)
pm_power_off();
+ else
+ do_kernel_poweroff();
machine_halt();
}
--
1.9.1

--
To unsubscribe from this list: send the line "unsubscribe linux-pm" in
the body of a message to ***@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Guenter Roeck
2014-09-30 18:00:50 UTC
Permalink
The kernel core now supports a poweroff handler call chain
to remove power from the system. Call it if pm_power_off
is set to NULL.

Cc: Ralf Baechle <***@linux-mips.org>
Signed-off-by: Guenter Roeck <***@roeck-us.net>
---
arch/mips/kernel/reset.c | 2 ++
1 file changed, 2 insertions(+)

diff --git a/arch/mips/kernel/reset.c b/arch/mips/kernel/reset.c
index 07fc524..c3391d7 100644
--- a/arch/mips/kernel/reset.c
+++ b/arch/mips/kernel/reset.c
@@ -41,4 +41,6 @@ void machine_power_off(void)
{
if (pm_power_off)
pm_power_off();
+ else
+ do_kernel_poweroff();
}
--
1.9.1
Ralf Baechle
2014-10-01 13:32:39 UTC
Permalink
Post by Guenter Roeck
The kernel core now supports a poweroff handler call chain
to remove power from the system. Call it if pm_power_off
is set to NULL.
---
arch/mips/kernel/reset.c | 2 ++
1 file changed, 2 insertions(+)
diff --git a/arch/mips/kernel/reset.c b/arch/mips/kernel/reset.c
index 07fc524..c3391d7 100644
--- a/arch/mips/kernel/reset.c
+++ b/arch/mips/kernel/reset.c
@@ -41,4 +41,6 @@ void machine_power_off(void)
{
if (pm_power_off)
pm_power_off();
+ else
+ do_kernel_poweroff();
I'm happy with this as long as in a later version pm_power_off indeed
goes away.

Ralf
Guenter Roeck
2014-10-01 16:26:17 UTC
Permalink
Post by Ralf Baechle
Post by Guenter Roeck
The kernel core now supports a poweroff handler call chain
to remove power from the system. Call it if pm_power_off
is set to NULL.
---
arch/mips/kernel/reset.c | 2 ++
1 file changed, 2 insertions(+)
diff --git a/arch/mips/kernel/reset.c b/arch/mips/kernel/reset.c
index 07fc524..c3391d7 100644
--- a/arch/mips/kernel/reset.c
+++ b/arch/mips/kernel/reset.c
@@ -41,4 +41,6 @@ void machine_power_off(void)
{
if (pm_power_off)
pm_power_off();
+ else
+ do_kernel_poweroff();
I'm happy with this as long as in a later version pm_power_off indeed
goes away.
Yes, that would be the ultimate goal. Hope we can get there.

Guenter
--
To unsubscribe from this list: send the line "unsubscribe linux-ia64" in
the body of a message to ***@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Guenter Roeck
2014-09-30 18:00:46 UTC
Permalink
The kernel core now supports a poweroff handler call chain
to remove power from the system. Call it if pm_power_off
is set to NULL.

Cc: Haavard Skinnemoen <***@gmail.com>
Cc: Hans-Christian Egtvedt <***@samfundet.no>
Signed-off-by: Guenter Roeck <***@roeck-us.net>
---
arch/avr32/kernel/process.c | 2 ++
1 file changed, 2 insertions(+)

diff --git a/arch/avr32/kernel/process.c b/arch/avr32/kernel/process.c
index 42a53e74..6bd6289 100644
--- a/arch/avr32/kernel/process.c
+++ b/arch/avr32/kernel/process.c
@@ -50,6 +50,8 @@ void machine_power_off(void)
{
if (pm_power_off)
pm_power_off();
+ else
+ do_kernel_poweroff();
}

void machine_restart(char *cmd)
--
1.9.1
Guenter Roeck
2014-09-30 18:00:43 UTC
Permalink
The kernel core now supports a poweroff handler call chain
to remove power from the system. Call it from machine_power_off.

Also, do not use pm_power_off as alternate pointer to machine_power_off.
Have the parisc/power driver call kernel_power_off() which in turn will
call machine_power_off().

Cc: James E.J. Bottomley <***@parisc-linux.org>
Cc: Helge Deller <***@gmx.de>
Signed-off-by: Guenter Roeck <***@roeck-us.net>
---
arch/parisc/kernel/process.c | 7 +++++--
drivers/parisc/power.c | 3 +--
2 files changed, 6 insertions(+), 4 deletions(-)

diff --git a/arch/parisc/kernel/process.c b/arch/parisc/kernel/process.c
index 0bbbf0d..21d1ab3 100644
--- a/arch/parisc/kernel/process.c
+++ b/arch/parisc/kernel/process.c
@@ -42,6 +42,7 @@
#include <linux/module.h>
#include <linux/personality.h>
#include <linux/ptrace.h>
+#include <linux/reboot.h>
#include <linux/sched.h>
#include <linux/slab.h>
#include <linux/stddef.h>
@@ -133,7 +134,9 @@ void machine_power_off(void)
pdc_soft_power_button(0);

pdc_chassis_send_status(PDC_CHASSIS_DIRECT_SHUTDOWN);
-
+
+ do_kernel_poweroff();
+
/* It seems we have no way to power the system off via
* software. The user has to press the button himself. */

@@ -141,7 +144,7 @@ void machine_power_off(void)
"Please power this system off now.");
}

-void (*pm_power_off)(void) = machine_power_off;
+void (*pm_power_off)(void);
EXPORT_SYMBOL(pm_power_off);

/*
diff --git a/drivers/parisc/power.c b/drivers/parisc/power.c
index 90cca5e..de5b2ff 100644
--- a/drivers/parisc/power.c
+++ b/drivers/parisc/power.c
@@ -95,8 +95,7 @@ static void process_shutdown(void)
/* send kill signal */
if (kill_cad_pid(SIGINT, 1)) {
/* just in case killing init process failed */
- if (pm_power_off)
- pm_power_off();
+ kernel_power_off();
}
}
}
--
1.9.1

--
To unsubscribe from this list: send the line "unsubscribe linux-ia64" in
the body of a message to ***@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Guenter Roeck
2014-09-30 18:00:42 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>
Signed-off-by: Guenter Roeck <***@roeck-us.net>
---
I already submitted this patch separately as non-RFC. It is included
in this series for completeness.

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-09-30 18:00:54 UTC
Permalink
The kernel core now supports a poweroff handler call chain
to remove power from the system. Call it if pm_power_off
is set to NULL.

Cc: Konrad Rzeszutek Wilk <konrad.wilk-QHcLZuEGTsvQT0dZR+***@public.gmane.org>
Cc: Boris Ostrovsky <boris.ostrovsky-QHcLZuEGTsvQT0dZR+***@public.gmane.org>
Cc: Thomas Gleixner <tglx-***@public.gmane.org>
Cc: Ingo Molnar <mingo-H+wXaHxf7aLQT0dZR+***@public.gmane.org>
Cc: H. Peter Anvin <hpa-***@public.gmane.org>
Signed-off-by: Guenter Roeck <linux-***@public.gmane.org>
---
arch/x86/xen/enlighten.c | 2 ++
1 file changed, 2 insertions(+)

diff --git a/arch/x86/xen/enlighten.c b/arch/x86/xen/enlighten.c
index c0cb11f..645d00f 100644
--- a/arch/x86/xen/enlighten.c
+++ b/arch/x86/xen/enlighten.c
@@ -1322,6 +1322,8 @@ static void xen_machine_power_off(void)
{
if (pm_power_off)
pm_power_off();
+ else
+ do_kernel_poweroff();
xen_reboot(SHUTDOWN_poweroff);
}
--
1.9.1

--
To unsubscribe from this list: send the line "unsubscribe linux-metag" in
the body of a message to majordomo-***@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
David Vrabel
2014-10-02 09:45:40 UTC
Permalink
Post by Guenter Roeck
The kernel core now supports a poweroff handler call chain
to remove power from the system. Call it if pm_power_off
is set to NULL.
---
arch/x86/xen/enlighten.c | 2 ++
1 file changed, 2 insertions(+)
diff --git a/arch/x86/xen/enlighten.c b/arch/x86/xen/enlighten.c
index c0cb11f..645d00f 100644
--- a/arch/x86/xen/enlighten.c
+++ b/arch/x86/xen/enlighten.c
@@ -1322,6 +1322,8 @@ static void xen_machine_power_off(void)
{
if (pm_power_off)
pm_power_off();
+ else
+ do_kernel_poweroff();
Why isn't this if (pm_power_off) check in do_kernel_poweroff()?

That way when you finally remove pm_power_off you need only update one
place. A quick skim of the other archs suggest this would work for them
too.

David
--
To unsubscribe from this list: send the line "unsubscribe linux-metag" in
the body of a message to majordomo-***@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Guenter Roeck
2014-10-02 13:27:08 UTC
Permalink
Post by David Vrabel
Post by Guenter Roeck
The kernel core now supports a poweroff handler call chain
to remove power from the system. Call it if pm_power_off
is set to NULL.
---
arch/x86/xen/enlighten.c | 2 ++
1 file changed, 2 insertions(+)
diff --git a/arch/x86/xen/enlighten.c b/arch/x86/xen/enlighten.c
index c0cb11f..645d00f 100644
--- a/arch/x86/xen/enlighten.c
+++ b/arch/x86/xen/enlighten.c
@@ -1322,6 +1322,8 @@ static void xen_machine_power_off(void)
{
if (pm_power_off)
pm_power_off();
+ else
+ do_kernel_poweroff();
Why isn't this if (pm_power_off) check in do_kernel_poweroff()?
That way when you finally remove pm_power_off you need only update one
place. A quick skim of the other archs suggest this would work for them
too.
Good idea. I'll do that for the next version of the patch set.

Guenter


--
To unsubscribe from this list: send the line "unsubscribe linux-metag" in
the body of a message to majordomo-***@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Guenter Roeck
2014-09-30 18:00:56 UTC
Permalink
Register with kernel poweroff handler instead of setting pm_power_off
directly.

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..e8ef345a 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/reboot.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 = 128;
+ ret = register_poweroff_handler(&palmas->poweroff_nb);
+ if (ret) {
+ dev_err(palmas->dev,
+ "cannot 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

--
To unsubscribe from this list: send the line "unsubscribe linux-sh" in
the body of a message to ***@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Guenter Roeck
2014-09-30 18:00:44 UTC
Permalink
The kernel core now supports a poweroff handler call chain
to remove power from the system. Call it if pm_power_off
is set to NULL.

Cc: Russell King <***@arm.linux.org.uk>
Signed-off-by: Guenter Roeck <***@roeck-us.net>
---
arch/arm/kernel/process.c | 2 ++
1 file changed, 2 insertions(+)

diff --git a/arch/arm/kernel/process.c b/arch/arm/kernel/process.c
index 250b6f6..848c578 100644
--- a/arch/arm/kernel/process.c
+++ b/arch/arm/kernel/process.c
@@ -207,6 +207,8 @@ void machine_power_off(void)

if (pm_power_off)
pm_power_off();
+ else
+ do_kernel_poweroff();
}

/*
--
1.9.1
Guenter Roeck
2014-09-30 18:00:45 UTC
Permalink
The kernel core now supports a poweroff handler call chain
to remove power from the system. Call it if pm_power_off
is set to NULL.

Cc: Catalin Marinas <***@arm.com>
Cc: Will Deacon <***@arm.com>
Signed-off-by: Guenter Roeck <***@roeck-us.net>
---
arch/arm64/kernel/process.c | 2 ++
1 file changed, 2 insertions(+)

diff --git a/arch/arm64/kernel/process.c b/arch/arm64/kernel/process.c
index 398ab05..cc0c63e 100644
--- a/arch/arm64/kernel/process.c
+++ b/arch/arm64/kernel/process.c
@@ -157,6 +157,8 @@ void machine_power_off(void)
smp_send_stop();
if (pm_power_off)
pm_power_off();
+ else
+ do_kernel_poweroff();
}

/*
--
1.9.1
Catalin Marinas
2014-10-03 10:30:56 UTC
Permalink
Post by Guenter Roeck
The kernel core now supports a poweroff handler call chain
to remove power from the system. Call it if pm_power_off
is set to NULL.
---
arch/arm64/kernel/process.c | 2 ++
1 file changed, 2 insertions(+)
diff --git a/arch/arm64/kernel/process.c b/arch/arm64/kernel/process.c
index 398ab05..cc0c63e 100644
--- a/arch/arm64/kernel/process.c
+++ b/arch/arm64/kernel/process.c
@@ -157,6 +157,8 @@ void machine_power_off(void)
smp_send_stop();
if (pm_power_off)
pm_power_off();
+ else
+ do_kernel_poweroff();
Acked-by: Catalin Marinas <***@arm.com>

As others already stated, I think we should eventually remove
pm_power_off entirely.

Catalin
--
To unsubscribe from this list: send the line "unsubscribe linux-parisc" 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-03 13:12:23 UTC
Permalink
Post by Catalin Marinas
Post by Guenter Roeck
The kernel core now supports a poweroff handler call chain
to remove power from the system. Call it if pm_power_off
is set to NULL.
---
arch/arm64/kernel/process.c | 2 ++
1 file changed, 2 insertions(+)
diff --git a/arch/arm64/kernel/process.c b/arch/arm64/kernel/process.c
index 398ab05..cc0c63e 100644
--- a/arch/arm64/kernel/process.c
+++ b/arch/arm64/kernel/process.c
@@ -157,6 +157,8 @@ void machine_power_off(void)
smp_send_stop();
if (pm_power_off)
pm_power_off();
+ else
+ do_kernel_poweroff();
As others already stated, I think we should eventually remove
pm_power_off entirely.
Hi Catalin,
yes, already working on it. As suggested by others, I'll move pm_power_off
to a central location (no need to declare the same variable for each
architecture) and hide the call to it in do_kernel_poweroff() as a
first step. You'll see this in the next version of the series.
This will make it much easier to remove it later on.

Thanks,
Guenter

--
To unsubscribe from this list: send the line "unsubscribe linux-sh" in
the body of a message to ***@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Guenter Roeck
2014-09-30 18:00:55 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 <sre-DgEjT+Ai2ygdnm+***@public.gmane.org>
Cc: Dmitry Eremin-Solenikov <dbaryshkov-***@public.gmane.org>
Cc: David Woodhouse <dwmw2-***@public.gmane.org>
Signed-off-by: Guenter Roeck <linux-***@public.gmane.org>
---
drivers/power/reset/restart-poweroff.c | 24 +++++++++++-------------
1 file changed, 11 insertions(+), 13 deletions(-)

diff --git a/drivers/power/reset/restart-poweroff.c b/drivers/power/reset/restart-poweroff.c
index edd707e..82d058f 100644
--- a/drivers/power/reset/restart-poweroff.c
+++ b/drivers/power/reset/restart-poweroff.c
@@ -12,35 +12,33 @@
*/
#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/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_restart_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_restart_handler(&restart_poweroff_handler);

return 0;
}
--
1.9.1

--
To unsubscribe from this list: send the line "unsubscribe linux-metag" in
the body of a message to majordomo-***@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Sebastian Reichel
2014-10-03 14:27:18 UTC
Permalink
Hi,
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.
Acked-By: Sebastian Reichel <***@kernel.org>

-- Sebastian
Guenter Roeck
2014-09-30 18:00:53 UTC
Permalink
The kernel core now supports a poweroff handler call chain
to remove power from the system. Call it if pm_power_off
is set to NULL.

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/reboot.c | 4 ++++
1 file changed, 4 insertions(+)

diff --git a/arch/x86/kernel/reboot.c b/arch/x86/kernel/reboot.c
index 17962e6..c5514aa 100644
--- a/arch/x86/kernel/reboot.c
+++ b/arch/x86/kernel/reboot.c
@@ -651,6 +651,10 @@ static void native_machine_power_off(void)
if (!reboot_force)
machine_shutdown();
pm_power_off();
+ } else {
+ if (!reboot_force)
+ machine_shutdown();
+ do_kernel_poweroff();
}
/* A fallback in case there is no PM info available */
tboot_shutdown(TB_SHUTDOWN_HALT);
--
1.9.1
Guenter Roeck
2014-09-30 18:00:51 UTC
Permalink
The kernel core now supports a poweroff handler call chain
to remove power from the system. Call it if pm_power_off
is set to NULL.

Signed-off-by: Guenter Roeck <***@roeck-us.net>
---
arch/sh/kernel/reboot.c | 2 ++
1 file changed, 2 insertions(+)

diff --git a/arch/sh/kernel/reboot.c b/arch/sh/kernel/reboot.c
index 04afe5b..8e68926 100644
--- a/arch/sh/kernel/reboot.c
+++ b/arch/sh/kernel/reboot.c
@@ -53,6 +53,8 @@ static void native_machine_power_off(void)
{
if (pm_power_off)
pm_power_off();
+ else
+ do_kernel_poweroff();
}

static void native_machine_halt(void)
--
1.9.1

--
To unsubscribe from this list: send the line "unsubscribe linux-sh" in
the body of a message to ***@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Guenter Roeck
2014-09-30 18:00:47 UTC
Permalink
The kernel core now supports a poweroff handler call chain
to remove power from the system. Call it if pm_power_off
is set to NULL.

Cc: Mark Salter <***@redhat.com>
Cc: Aurelien Jacquiot <a-***@ti.com>
Signed-off-by: Guenter Roeck <***@roeck-us.net>
---
arch/c6x/kernel/process.c | 2 ++
1 file changed, 2 insertions(+)

diff --git a/arch/c6x/kernel/process.c b/arch/c6x/kernel/process.c
index 57d2ea8..ddf088e 100644
--- a/arch/c6x/kernel/process.c
+++ b/arch/c6x/kernel/process.c
@@ -75,6 +75,8 @@ void machine_power_off(void)
{
if (pm_power_off)
pm_power_off();
+ else
+ do_kernel_poweroff();
halt_loop();
}
--
1.9.1
Mark Salter
2014-10-03 15:17:22 UTC
Permalink
Post by Guenter Roeck
The kernel core now supports a poweroff handler call chain
to remove power from the system. Call it if pm_power_off
is set to NULL.
---
arch/c6x/kernel/process.c | 2 ++
1 file changed, 2 insertions(+)
diff --git a/arch/c6x/kernel/process.c b/arch/c6x/kernel/process.c
index 57d2ea8..ddf088e 100644
--- a/arch/c6x/kernel/process.c
+++ b/arch/c6x/kernel/process.c
@@ -75,6 +75,8 @@ void machine_power_off(void)
{
if (pm_power_off)
pm_power_off();
+ else
+ do_kernel_poweroff();
halt_loop();
}
Guenter Roeck
2014-09-30 18:00:49 UTC
Permalink
The kernel core now supports a poweroff handler call chain
to remove power from the system. Call it if pm_power_off
is set to NULL.

Cc: James Hogan <***@imgtec.com>
Signed-off-by: Guenter Roeck <***@roeck-us.net>
---
arch/metag/kernel/process.c | 2 ++
1 file changed, 2 insertions(+)

diff --git a/arch/metag/kernel/process.c b/arch/metag/kernel/process.c
index 483dff9..ff7f3eb 100644
--- a/arch/metag/kernel/process.c
+++ b/arch/metag/kernel/process.c
@@ -92,6 +92,8 @@ void machine_power_off(void)
{
if (pm_power_off)
pm_power_off();
+ else
+ do_kernel_poweroff();
smp_send_stop();
hard_processor_halt(HALT_OK);
}
--
1.9.1

--
To unsubscribe from this list: send the line "unsubscribe linux-pm" in
the body of a message to ***@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Loading...