Ноутбук засыпает, ноутбук просыпается, батарея «зависает» — более не отдает ни уровень заряда ни другие показатели, вне зависимости от подключения к сети.
Патч ядра Linux и три года изысканий, рассказываю как это было.

Вводная
Автор очень давно использует самые разнообразные версии и вариации Linux и UNIX‑систем для работы и диких развлечений, в том числе на ноутбуках, поэтому старается решать все найденные проблемы, по мере сил.
Временами проблема возвращается заново в новых версиях ядра, будучи решенной в прошлом, временами происходит наоборот и проблема проявляется только в самых свежих версиях Linux.
Бывает приходится приостановить поиски решения и вернуться к изысканиям спустя много лет, когда случайно обнаруживается новый вариант решения.
Описываемая история — как раз из последних.
Проблема
Вкратце проблема заключалась в абзаце, вынесенном в заголовок:
ноутбук засыпает, ноутбук просыпается, после чего батарея «зависает» — более не отдает свой актуальный уровень заряда и все показатели, вне зависимости от подключения к электросети.
Естественно в Windows все работало правильно и стабильно, в любых режимах засыпания.
Ноутбук редкий, ноутбук старый, от вендора, который в гробу видал никогда не любил альтернативные ОС и тем более в страшном сне не мог представить, что одна из топовых моделей (на свое время) вместо подсчета прибылей успешному менеджеру, стала бы использоваться для компиляции ядра из исходников и прочих гиковских непотребств.
Никакая отладка ядра и никакие отладочные сообщения не помогли, что неудивительно:
Работа с ACPI — традиционно самая замороченная область ядра Linux, а процессы засыпания и возвращения к работе — сложны и нестабильны по своей сути.
Так что оно глючило, глючит и будет глючить, в любой ОС и на любом оборудовании при любой погоде.
Процесс отлова ошибок связанных с ACPI усложнен тем, что такие ошибки чаще всего «плавающие» — могут появиться не через один цикл «засыпания‑пробуждения» а например через десять, т. е. вам надо десять раз подряд погрузить ноутбук в сон и затем пробудить чтобы отловить ошибку.
Правда ведь отладка это весело?

Решение
Далеко не сразу (ушло примерно три года), путем хитрых запросов к поисковикам и изучения исходников ядра, автор все же смог отыскать концы этой проблемы.
И помог в этом случайный комментарий неизвестного китайского разработчика:
I have few reputation so I can't tell others about solution in their questions, so I will post it here.
Solution : build kernel with this PATCH
Description : I tracked the issue ,I discovered that all was working good until the 4.19.86 kernel.
So I checked DIFF and After many tries maybe 50 or more.
I found the cause : It was (if statement was added in 4.19.86 COMMIT) ,particularly checking if spaceid == 0 [ACPI_ADR_SPACE_SYSTEM_MEMORY]. Commit Link
Разумеется патч китайского автора оказался нерабочий, сообщение было написано про другую модель ноутбука, с другим поведением при сбое и с неверной фиксацией на типе батареи в качестве источника проблемы.
Еще речь шла про совсем уж древнюю версию ядра (4.19, релиз в 2018м году) а само сообщение датировалось 2022 годом.
Но вы ведь и не думали, что все будет настолько просто, верно?
Решение
Посмотрим на код «виновника торжества», файл drivers/acpi/acpica/evregion.c, метод acpi_ev_execute_reg_methods, а еще точнее — вот этот замечательный комментарий:
/*
* These address spaces do not need a call to _REG, since the ACPI
* specification defines them as: "must always be accessible". Since
* they never change state (never become unavailable), no need to ever
* call _REG on them. Also, a data_table is not a "real" address space,
* so do not call _REG. September 2018.
*/Обратите внимание на дату — 2018й год, год выпуска версии ядра 4.19, в которой и проявилась данная проблема.
По сути самого комментария и исходя из логики, один из коммитеров ядра Linux в далеком 2018 году хотел «сделать как лучше»:
if ((space_id == ACPI_ADR_SPACE_SYSTEM_MEMORY) ||
(space_id == ACPI_ADR_SPACE_SYSTEM_IO) ||
(space_id == ACPI_ADR_SPACE_DATA_TABLE)) {
return_VOID;
}Полагая что строгое соотвествие спецификации ACPI в данном случае бывает всегда — он вставил заглушку, убирающую вызов _REG метода для вроде как системных частей ACPI‑прошивки.
Чем и поломал восстановление статуса батареи при пробуждении ноутбука.
Благими намерениями выстелена дорога в Ад. (ц)
Исправление
Все что нужно сделать для исправления ситуации, это убрать из условия проверки константу ACPI_ADR_SPACE_SYSTEM_MEMORY:
if (
// (space_id == ACPI_ADR_SPACE_SYSTEM_MEMORY) ||
(space_id == ACPI_ADR_SPACE_SYSTEM_IO) ||
(space_id == ACPI_ADR_SPACE_DATA_TABLE)) {
return_VOID;
}Ну и опционально добавить отладку, чтобы убедиться в правильности работы:
if (space_id == ACPI_ADR_SPACE_SYSTEM_MEMORY) {
printk(KERN_DEBUG "PRO HEHE : Bypassing for battery is done");
}Отладка была включена в текущем ядре, само сообщение можно наблюдать на стартовой картинке к статье.
Для того чтобы убедиться в правильности работы, достаточно усыпить ноутбук, пробудить и подергать состояние батареи несколько раз:

Эпилог
Такой патч никогда не примут в аппстрим ядра, потому что он неправилен с точки зрения спецификации ACPI.
Собственно сама проблема с зависшей батареей появилась из-за того что некоторые вендоры класть хотели на стандарты и спецификации.
К сожалению такого рода проблемы в новых версиях ядра Linux появляются все чаще, поэтому и ситуация и ее решение — уже можно сказать типовые и подобным образом решаются ныне и многие другие проблемы с оборудованием.
Так что если на вашем ноутбуке также проявляется описанная проблема с «зависанием» батареи — теперь будете знать в какую сторону копать.
P.S.
Если вы внимательно смотрели на заглавную картинку к статье, могли заметить что автор использовал нестандартное ядро:
XanMod is a general-purpose Linux kernel distribution with custom settings and new features. Built to provide a stable, smooth and solid system experience.
The real-time version is recommended for critical runtime applications such as Linux gaming server / client for eSports, streaming, live productions and
ultra-low latency enthusiasts.
Подтверждаю, этот набор патчей ядра Linux действительно сильно ускоряет работу, что особенно ��аметно на некрожелезе времен молодости Брежнева, которое автор регулярно использует для укрепления стойкости духа.
P.P.S.
На март 2025 проблема все также актуальна и вряд ли будет решена в апстриме ядра в обозримом будущем.
Поэтому автор продолжает накладывать описанный патч (и еще несколько) при каждой пересборке ядра.
Еще добавлю, что это немного почищенная и обновленная версия статьи, оригинал которой находится в нашем блоге.