2017-01-11 2 views
2

Я успешно использовал указатель функции pm_power_off, чтобы сделать мою пользовательскую Linux-плату своим чипом управления питанием через i2c (чтобы отключить питание).Как отключить питание Linux при остановке?

Я бы хотел, чтобы команда Linux halt выключила питание.

Как я могу это достичь?

Код (ARM) для machine_halt не имеет указателя, аналогичного machine_power_off's pm_power_off.

арка/рука/ядро ​​/ 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(); 
} 

Я мог бы, очевидно, просто взломать machine_halt, но я хотел бы сделать это "правильно", если это возможно.

Я пропустил что-то (возможно, в пользовательском пространстве), которое может вызвать команду halt для выполнения «отключения питания»?


Обновление: Спасибо за ответ и все ваши комментарии, они помогли мне понять, какова актуальная проблема.

Моя проблема:

У меня есть входной край, доступный блок пользовательского управления питанием. Подумайте об этом как о стартовой кнопке, без функции остановки или сброса. Я полностью контролирую код PMU (это ATMEGA работает как подчиненный i2c).

  1. Если ядро ​​Linux запущено, я хочу, чтобы край был проигнорирован.
  2. Если CPU выключен, я хочу, чтобы кран подключался к CPU.
  3. Если ядро ​​Linux остановлено, я хочу, чтобы край сбросил CPU.

Дело 1 легко, нечего делать.

Случай 2 был прост, определите pm_power_off в моем драйвере, чтобы отправить сообщение i2c в PMU. К счастью, подсистема i2c все еще находится в рабочем состоянии, когда вызывается pm_power_off.

Дело 3 - проблема - я искал pm_halt, чтобы определить, отправить сообщение i2c в PMU.

Возможно, существует другой способ, так как комментарии 0andriy?

Есть ли место в ядре, чтобы подталкивать в ЦУП с I2C сообщений в нескольких Гц, если машина не halt ред?

Ответ на: https://unix.stackexchange.com/a/42576/17288 гласит:

«. * В эти дни привал достаточно умен, чтобы автоматически вызывать отключение питания, если ACPI включена На самом деле, они функционально эквивалентны в настоящее время»

Возможно, есть какой-то способ обеспечения или подключения к ACPI - мне нужно будет прочитать об этом.

+0

Правильный путь не потрогай это. Конечно, вы можете настроить сторожевой таймер и получить тот же эффект после истечения таймаута. – 0andriy

+0

Я уверен, что вы не хотите взломать machine_halt(); идея заключается в том, чтобы дать возможность работать с pm_power_off(), чтобы не реагировать на работу, и в этот момент она могла записать это и вызвать machine_halt() через syscall. – Joshua

+0

@ 0andriy вы могли бы указать мне на какой-то код драйвера ядра, который периодически выполняет какую-то деятельность? Есть ли способ, которым я мог бы использовать отметку 100 Гц в качестве подсказки для отправки keepalive? – fadedbee

ответ

1

Вы должны использовать команду poweroff или halt -p. По команде man 8 halt команда halt (без аргументов) не гарантирует выключение питания вашего устройства. Причины описаны here:

halt использовали до того ACPI (который сегодня будет отключить питание для вас) *. Он остановит систему, а затем напечатает сообщение о том, что «теперь нормально выключать питание». В то время были физические переключатели включения/выключения, а не комбинированная кнопка управления мощностью ACPI современных компьютеров.

* В настоящее время halt достаточно умен, чтобы автоматически вызывать переключение, если включен ACPI. Фактически, они функционально эквивалентны сейчас.

Как вы можете видеть из halt инструмента исходного кода, он выдает reboot() системный вызов с cmd = RB_POWER_OFF = LINUX_REBOOT_CMD_POWER_OFF.

В ядре, что системный вызов реализован here, и на cmd = LINUX_REBOOT_CMD_POWER_OFF, он называет:
    ->kernel_power_off()
    ->machine_power_off()
    ->pm_power_off()

+0

Вы смотрите на неправильную сторону границы пользовательского пространства/ядра. OP уже работает в ядре - они пытаются реализовать сторону ядра 'LINUX_REBOOT_CMD_POWER_OFF'. – duskwuff

+0

Подождите, я неправильно понял вопрос. Я делаю нулевое изменение в вашем ответе, чтобы я мог удалить свой ошибочный downvote. – duskwuff

+0

@duskwuff Теперь, когда вы упомянули об этом, я перечитываю вопрос, и я не совсем уверен, что хочет узнать OP (либо он просто неправильно использует инструмент «halt», либо он на самом деле не может управлять - на его борту даже с использованием правильной команды, потому что код ядра неполный). Я буду ждать ответа, и если я неправильно понял вопрос - удалю мой ответ. –

Смежные вопросы