Message ID | 1395348795-8554-2-git-send-email-sebastian.capella@linaro.org (mailing list archive) |
---|---|
State | RFC, archived |
Headers | show |
Hi! > Reboot logic in kernel/reboot will avoid calling kernel_power_off > when pm_power_off is null, and instead uses kernel_halt. Change > hibernate's power_down to follow the behavior in the reboot call. > > Calling the notifier twice (once for SYS_POWER_OFF and again for > SYS_HALT) causes a panic during hibernation on Kirkwood > Openblocks A6 board. I can't say I like this patch. kernel_power_off should work with pm_power_off == NULL, see for example x86. static void native_machine_power_off(void) { if (pm_power_off) { if (!reboot_force) machine_shutdown(); pm_power_off(); } /* A fallback in case there is no PM info available */ tboot_shutdown(TB_SHUTDOWN_HALT); } . arch/arm/process.c implementation is strange: void machine_halt(void) { local_irq_disable(); smp_send_stop(); local_irq_disable(); while (1); } ## Why second disable? /* * Power-off simply requires that the secondary CPUs stop performing any * activity (executing tasks, handling interrupts). smp_send_stop() * achieves this. When the system power is turned off, it will take all CPUs * with it. */ void machine_power_off(void) { local_irq_disable(); smp_send_stop(); if (pm_power_off) pm_power_off(); } ## It really should do while (1) here. Pavel
> if (pm_power_off) > pm_power_off(); > } > > ## It really should do while (1) here. while(1) cpu_relax(); or similar at minimum. Alan -- To unsubscribe from this list: send the line "unsubscribe linux-pm" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Thanks Pavel and Alan for your comments! I'll rework and try again. Sebastian On 20 March 2014 14:35, One Thousand Gnomes <gnomes@lxorguk.ukuu.org.uk> wrote: >> if (pm_power_off) >> pm_power_off(); >> } >> >> ## It really should do while (1) here. > > while(1) > cpu_relax(); > > or similar at minimum. > > Alan -- To unsubscribe from this list: send the line "unsubscribe linux-pm" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
> On 20 March 2014 14:35, One Thousand Gnomes <gnomes@lxorguk.ukuu.org.uk> wrote: >>> if (pm_power_off) >>> pm_power_off(); >>> ## It really should do while (1) here. >> while(1) >> cpu_relax(); >> or similar at minimum. Hi Alan, Pavel, I prepared the changes suggested for ARM, but Russell disagrees that this code must block, and points to the kernel/reboot.c function from which I'd taken the original change. > On Mar 26, Russell King - ARM Linux wrote: >> I don't see why we should make this change. kernel/reboot.c handles >> this function returning, so other places should do too. >> Even on x86, this function can return: >> >> Therefore, I'd say... it's a bug in the hibernation code - or we probably >> have many buggy architectures. I'd suggest fixing the hibernation code >> rather than stuffing some workaround like an endless loop into every >> architecture. In this case, the hibernation code would need to changed prevent calling both sets of notifiers. The discussions are very short, but the details are here: https://lkml.org/lkml/2014/3/25/554 -- linux-arm discussion https://lkml.org/lkml/2014/3/20/649 -- linux-pm discussion It doesn't appear definitive that the machine_power_off should block, since the reboot call is working around the possibility. If we go the route Russell proposes, the change would basically be this patch. Are you ok with me trying to adjust the hibernation handling here? Do you have any further thoughts on this? Thanks! Sebastian -- To unsubscribe from this list: send the line "unsubscribe linux-pm" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Ping.. There appears to be disagreement on the correct path to take on this. Pavel and Alan recommend that arm's machine_power_off shall never return Russell suggests hibernation be modified to handle machine_power_off returning; that x86 architecture (and others as well) can have machine_power_off returning. Discussions available at the links below: https://lkml.org/lkml/2014/3/25/554 -- linux-arm discussion https://lkml.org/lkml/2014/3/20/649 -- linux-pm discussion Should I continue with the original hibernation patch from the linux-pm discussion? Does anyone have any response to Russel's commentsl? Thanks! Sebastian -- To unsubscribe from this list: send the line "unsubscribe linux-pm" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
On Tue, Apr 15, 2014 at 11:34:52AM -0700, Sebastian Capella wrote: > Ping.. > > There appears to be disagreement on the correct path to take on this. > > Pavel and Alan recommend that arm's machine_power_off shall never return > > Russell suggests hibernation be modified to handle machine_power_off > returning; that x86 architecture (and others as well) can have > machine_power_off returning. > > Discussions available at the links below: > https://lkml.org/lkml/2014/3/25/554 -- linux-arm discussion > https://lkml.org/lkml/2014/3/20/649 -- linux-pm discussion > > Should I continue with the original hibernation patch from the > linux-pm discussion? > > Does anyone have any response to Russel's commentsl? What I'm basically saying is that I see no reason for ARM to do something different to what x86 does. What is pretty clear to me is that ARM is compatible with x86, which is compatible with kernel/reboot.c, and it's the hibernate code which is the odd one out.
On Tue 2014-04-15 21:54:53, Russell King - ARM Linux wrote: > On Tue, Apr 15, 2014 at 11:34:52AM -0700, Sebastian Capella wrote: > > Ping.. > > > > There appears to be disagreement on the correct path to take on this. > > > > Pavel and Alan recommend that arm's machine_power_off shall never return > > > > Russell suggests hibernation be modified to handle machine_power_off > > returning; that x86 architecture (and others as well) can have > > machine_power_off returning. > > > > Discussions available at the links below: > > https://lkml.org/lkml/2014/3/25/554 -- linux-arm discussion > > https://lkml.org/lkml/2014/3/20/649 -- linux-pm discussion > > > > Should I continue with the original hibernation patch from the > > linux-pm discussion? > > > > Does anyone have any response to Russel's commentsl? > > What I'm basically saying is that I see no reason for ARM to do something > different to what x86 does. > > What is pretty clear to me is that ARM is compatible with x86, which is > compatible with kernel/reboot.c, and it's the hibernate code which is > the odd one out. I'm pretty sure the original code did not return. Anyway, the best solution, given how many platforms are out there, would be to a) document that it should not return b) fix hibernation to handle the returning case, anyway. Pavel
On 15 April 2014 14:18, Pavel Machek <pavel@ucw.cz> wrote: > On Tue 2014-04-15 21:54:53, Russell King - ARM Linux wrote: >> What I'm basically saying is that I see no reason for ARM to do something >> different to what x86 does. >> >> What is pretty clear to me is that ARM is compatible with x86, which is >> compatible with kernel/reboot.c, and it's the hibernate code which is >> the odd one out. > > I'm pretty sure the original code did not return. Anyway, the best > solution, given how many platforms are out there, would be to > > a) document that it should not return > > b) fix hibernation to handle the returning case, anyway. Thanks Russell and Pavel! This sounds fine to me. Any objections? Thanks! Sebastian -- To unsubscribe from this list: send the line "unsubscribe linux-pm" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
On Wed, Apr 16, 2014 at 09:28:28AM -0700, Sebastian Capella wrote: > On 15 April 2014 14:18, Pavel Machek <pavel@ucw.cz> wrote: > > On Tue 2014-04-15 21:54:53, Russell King - ARM Linux wrote: > >> What I'm basically saying is that I see no reason for ARM to do something > >> different to what x86 does. > >> > >> What is pretty clear to me is that ARM is compatible with x86, which is > >> compatible with kernel/reboot.c, and it's the hibernate code which is > >> the odd one out. > > > > I'm pretty sure the original code did not return. Anyway, the best > > solution, given how many platforms are out there, would be to > > > > a) document that it should not return > > > > b) fix hibernation to handle the returning case, anyway. > > Thanks Russell and Pavel! > > This sounds fine to me. Any objections? Here is the i386 code from 2.2.20: void machine_halt(void) { } void machine_power_off(void) { if (acpi_power_off) acpi_power_off(); } Both can return. On the other hand, machine_restart() can never return as the final attempt to perform that action in machine_real_restart is a jump to 16-bit code. 2.4 kernels then modified it to this: void machine_halt(void) { } void machine_power_off(void) { if (pm_power_off) pm_power_off(); } with machine_restart() doing similar to v2.2. 2.6.0 also did the same as 2.4 kernels. 2.6.16 then changed to this: void machine_restart(char * __unused) { machine_shutdown(); machine_emergency_restart(); } void machine_halt(void) { } void machine_power_off(void) { if (pm_power_off) { machine_shutdown(); pm_power_off(); } } which starts adding some extra stuff into the power off hook - but again, it's a no-op unless the pm_power_off function pointer is initialised. Today, it's: void machine_power_off(void) { machine_ops.power_off(); } which calls native_power_off(): static void native_machine_power_off(void) { if (pm_power_off) { if (!reboot_force) machine_shutdown(); pm_power_off(); } /* A fallback in case there is no PM info available */ tboot_shutdown(TB_SHUTDOWN_HALT); } and tboot_shutdown(): void tboot_shutdown(u32 shutdown_type) { void (*shutdown)(void); if (!tboot_enabled()) return; so it's entirely possible today for machine_power_off() on x86 to return. So... the i386 code has had this "machine_power_off() can return" behaviour for a significant number of years and persists to this day. I'd say scrap (a) _unless_ we're going to add while (1) loops to all the architectures. Alternatively, we could just accept that machine_power_off() may return and deal with that case (iow, not crash) in generic code.
> I'd say scrap (a) _unless_ we're going to add while (1) loops to all > the architectures. Alternatively, we could just accept that > machine_power_off() may return and deal with that case (iow, not > crash) in generic code. What would the right behaviour be while(1); isn't really nice behaviour on a modern device -- To unsubscribe from this list: send the line "unsubscribe linux-pm" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
On Wed, Apr 16, 2014 at 09:57:18PM +0100, One Thousand Gnomes wrote: > > I'd say scrap (a) _unless_ we're going to add while (1) loops to all > > the architectures. Alternatively, we could just accept that > > machine_power_off() may return and deal with that case (iow, not > > crash) in generic code. > > What would the right behaviour be > > while(1); > > isn't really nice behaviour on a modern device That's an entirely different question... one which also needs fixing in the hibernate code. We already know that cpu_relax() in there is a good thing to do, so that would be a good start.
Thanks Russell, Alan! So we're OK with the current patch + replacing while(1) after kernel_halt at the end of power_down in hibernate.c with a while (1) cpu_relax()? Any other changes needed? If not, I'll send a follow up patch with just these. Thanks! Sebastian -- To unsubscribe from this list: send the line "unsubscribe linux-pm" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
On Fri 2014-04-18 14:38:34, Sebastian Capella wrote: > Thanks Russell, Alan! > > So we're OK with the current patch + replacing while(1) after > kernel_halt at the end of power_down in hibernate.c with a while (1) > cpu_relax()? > > Any other changes needed? > > If not, I'll send a follow up patch with just these. That sounds like a plan. Thanks. Pavel
diff --git a/kernel/power/hibernate.c b/kernel/power/hibernate.c index 37170d4..6a278dc 100644 --- a/kernel/power/hibernate.c +++ b/kernel/power/hibernate.c @@ -595,7 +595,8 @@ static void power_down(void) case HIBERNATION_PLATFORM: hibernation_platform_enter(); case HIBERNATION_SHUTDOWN: - kernel_power_off(); + if (pm_power_off) + kernel_power_off(); break; #ifdef CONFIG_SUSPEND case HIBERNATION_SUSPEND:
Reboot logic in kernel/reboot will avoid calling kernel_power_off when pm_power_off is null, and instead uses kernel_halt. Change hibernate's power_down to follow the behavior in the reboot call. Calling the notifier twice (once for SYS_POWER_OFF and again for SYS_HALT) causes a panic during hibernation on Kirkwood Openblocks A6 board. Signed-off-by: Sebastian Capella <sebastian.capella@linaro.org> Reported-by: Ezequiel Garcia <ezequiel.garcia@free-electrons.com> Cc: Len Brown <len.brown@intel.com> Cc: Pavel Machek <pavel@ucw.cz> Cc: "Rafael J. Wysocki" <rjw@rjwysocki.net> --- kernel/power/hibernate.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)