I have successfully used the pm_power_off
function pointer to make my custom Linux board call its power management chip over i2c (to turn the power off).
I would like the Linux halt
command to switch the power off too.
How can I achieve this?
The (ARM) code for machine_halt
does not have an pointer analogous to machine_power_off
's pm_power_off
.
arch/arm/kernel/reboot.c:
/*
* Halting simply requires that the secondary CPUs stop performing any
* activity (executing tasks, handling interrupts). smp_send_stop()
* achieves this.
*/
void machine_halt(void)
{
local_irq_disable();
smp_send_stop();
local_irq_disable();
while (1);
}
/*
* 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();
}
I could obviously just hack machine_halt
, but I would like to do this "properly", if possible.
Have I missed something (perhaps in userspace) which could cause a halt
command to execute a "power off"?
Update: Thanks for the answer and all of your comments, they have helped me realise what the actual issue is.
My problem is:
I have an input edge, available to the custom power management unit. Think of it as a start button, with no stop or reset functionality. I have full control of the PMU code (it's an ATMEGA running as an i2c slave).
Case 1 is easy, nothing to do.
Case 2 was easy, define pm_power_off
in my driver to send an i2c message to the PMU. Luckily the i2c subsystem is still in a working state when pm_power_off
is called.
Case 3 is the problem - I was looking for a pm_halt
to define, to send an i2c message to the PMU.
Perhaps there is another way, as 0andriy comments?
Is there a place in the kernel to keep prodding the PMU with i2c messages at a few Hz, unless the machine is halt
ed?
The answer at: https://unix.stackexchange.com/a/42576/17288 reads:
"* These days halt is smart enough to automatically call poweroff if ACPI is enabled. In fact, they are functionally equivalent now."
Perhaps there is some way of providing or hooking into ACPI - I will have to read up on it.
You should use poweroff
command or halt -p
. As per man 8 halt, halt
command (with no arguments) doesn't guarantee to power off your machine. Reasons are described here:
halt
was used before ACPI (which today will turn off the power for you)*. It would halt the system and then print a message to the effect of "it's ok to power off now". Back then there were physical on/off switches, rather than the combo ACPI controlled power button of modern computers.*These days
halt
is smart enough to automatically call poweroff if ACPI is enabled. In fact, they are functionally equivalent now.
As you can see from halt
tool source code, it issues reboot() system call with cmd = RB_POWER_OFF = LINUX_REBOOT_CMD_POWER_OFF
.
In kernel, that system call is implemented here, and on cmd = LINUX_REBOOT_CMD_POWER_OFF
, it calls:
-> kernel_power_off()
-> machine_power_off()
-> pm_power_off()