From 00ac4afb9f4f01026b437a536f9eca5da2cfe78b Mon Sep 17 00:00:00 2001 From: Alexander Boettcher Date: Thu, 13 Oct 2022 09:04:58 +0200 Subject: [PATCH] acpica: make battery report working for thinkpads tested on T460p, X201, T470p by periodically checking and reporting. Issue #4631 --- repos/libports/recipes/pkg/acpica/runtime | 4 +- repos/libports/run/acpica.run | 2 +- repos/libports/src/app/acpica/README | 2 +- repos/libports/src/app/acpica/ec.h | 4 +- repos/libports/src/app/acpica/os.cc | 135 ++++++++++++---------- 5 files changed, 81 insertions(+), 66 deletions(-) diff --git a/repos/libports/recipes/pkg/acpica/runtime b/repos/libports/recipes/pkg/acpica/runtime index 3df07ea803..e2cd58d221 100644 --- a/repos/libports/recipes/pkg/acpica/runtime +++ b/repos/libports/recipes/pkg/acpica/runtime @@ -1,4 +1,4 @@ - + @@ -16,6 +16,6 @@ - + diff --git a/repos/libports/run/acpica.run b/repos/libports/run/acpica.run index cd180a7290..8055927ecf 100644 --- a/repos/libports/run/acpica.run +++ b/repos/libports/run/acpica.run @@ -184,7 +184,7 @@ set config { - + diff --git a/repos/libports/src/app/acpica/README b/repos/libports/src/app/acpica/README index 5c654b8d53..c89b9d28af 100644 --- a/repos/libports/src/app/acpica/README +++ b/repos/libports/src/app/acpica/README @@ -46,7 +46,7 @@ Excerpt of important parts of the acpica configuration ! ! ! ... -! +! ! ! ! diff --git a/repos/libports/src/app/acpica/ec.h b/repos/libports/src/app/acpica/ec.h index 173568cbac..44f70943ba 100644 --- a/repos/libports/src/app/acpica/ec.h +++ b/repos/libports/src/app/acpica/ec.h @@ -80,10 +80,8 @@ class Ec : Acpica::Callback { State::access_t state = ec->ec_cmdsta->inb(ec->ec_port_cmdsta); - if (!State::Sci_evt::get(state)) { - Genode::error("unknown status ", Genode::Hex(state)); + if (!State::Sci_evt::get(state)) return ACPI_REENABLE_GPE; /* gpe is acked and re-enabled */ - } ec->ec_cmdsta->outb(ec->ec_port_cmdsta, QR_EC); do { diff --git a/repos/libports/src/app/acpica/os.cc b/repos/libports/src/app/acpica/os.cc index 0a576a90a5..869966a8d2 100644 --- a/repos/libports/src/app/acpica/os.cc +++ b/repos/libports/src/app/acpica/os.cc @@ -4,7 +4,7 @@ */ /* - * Copyright (C) 2016-2017 Genode Labs GmbH + * Copyright (C) 2016-2022 Genode Labs GmbH * * This file is part of the Genode OS framework, which is distributed * under the terms of the GNU Affero General Public License version 3. @@ -20,6 +20,7 @@ #include #include +#include #include #include @@ -45,14 +46,17 @@ namespace Acpica { #include "fixed.h" +using namespace Genode; + + struct Acpica::Statechange { - Genode::Signal_handler _dispatcher; - Genode::Attached_rom_dataspace _system_state; + Signal_handler _dispatcher; + Attached_rom_dataspace _system_state; bool _enable_reset; bool _enable_poweroff; - Statechange(Genode::Env &env, bool reset, bool poweroff) + Statechange(Env &env, bool reset, bool poweroff) : _dispatcher(env.ep(), *this, &Statechange::state_changed), _system_state(env, "system"), @@ -69,17 +73,16 @@ struct Acpica::Statechange if (!_system_state.valid()) return; - Genode::Xml_node system(_system_state.local_addr(), - _system_state.size()); + Xml_node system(_system_state.local_addr(), + _system_state.size()); - typedef Genode::String<32> State; + typedef String<32> State; State const state = system.attribute_value("state", State()); if (_enable_poweroff && state == "poweroff") { ACPI_STATUS res0 = AcpiEnterSleepStatePrep(5); ACPI_STATUS res1 = AcpiEnterSleepState(5); - Genode::error("system poweroff failed - " - "res=", Genode::Hex(res0), ",", Genode::Hex(res1)); + error("system poweroff failed - res=", Hex(res0), ",", Hex(res1)); return; } @@ -89,25 +92,29 @@ struct Acpica::Statechange res = AcpiReset(); } catch (...) { } - Genode::uint64_t const space_addr = AcpiGbl_FADT.ResetRegister.Address; - Genode::error("system reset failed - " - "err=", res, " " - "reset=", !!(AcpiGbl_FADT.Flags & ACPI_FADT_RESET_REGISTER), " " - "spaceid=", Genode::Hex(AcpiGbl_FADT.ResetRegister.SpaceId), " " - "addr=", Genode::Hex(space_addr)); + uint64_t const space_addr = AcpiGbl_FADT.ResetRegister.Address; + error("system reset failed - err=", res, + " reset=", !!(AcpiGbl_FADT.Flags & ACPI_FADT_RESET_REGISTER), + " spaceid=", Hex(AcpiGbl_FADT.ResetRegister.SpaceId), + " addr=", Hex(space_addr)); } } }; + struct Acpica::Main { - Genode::Env &env; - Genode::Heap heap { env.ram(), env.rm() }; + Env &env; + Heap heap { env.ram(), env.rm() }; - Genode::Attached_rom_dataspace config { env, "config" }; + Attached_rom_dataspace config { env, "config" }; - Genode::Signal_handler sci_irq; - Genode::Constructible sci_conn; + Signal_handler sci_irq; + Constructible sci_conn; + + Timer::Connection timer { env }; + Signal_handler timer_trigger { env.ep(), *this, + &Main::handle_timer }; Acpica::Reportstate * report { nullptr }; @@ -115,25 +122,25 @@ struct Acpica::Main unsigned unchanged_state_max; static struct Irq_handler { - UINT32 irq; - Genode::Irq_session::Trigger trigger; - Genode::Irq_session::Polarity polarity; - - ACPI_OSD_HANDLER handler; - void *context; + UINT32 irq; + Irq_session::Trigger trigger; + Irq_session::Polarity polarity; + ACPI_OSD_HANDLER handler; + void *context; } irq_handler; void init_acpica(); - Main(Genode::Env &env) + Main(Env &env) : env(env), sci_irq(env.ep(), *this, &Main::acpi_irq), - unchanged_state_max(config.xml().attribute_value("update_unchanged", 20U)) + unchanged_state_max(config.xml().attribute_value("update_unchanged", 10U)) { bool const enable_reset = config.xml().attribute_value("reset", false); bool const enable_poweroff = config.xml().attribute_value("poweroff", false); bool const enable_report = config.xml().attribute_value("report", false); + auto const periodic_ms = config.xml().attribute_value("report_period_ms", 0ULL); if (enable_report) report = new (heap) Acpica::Reportstate(env); @@ -148,19 +155,37 @@ struct Acpica::Main /* setup IRQ */ if (!irq_handler.handler) { - Genode::warning("no IRQ handling available"); + warning("no IRQ handling available"); return; } sci_conn.construct(env, irq_handler.irq, irq_handler.trigger, irq_handler.polarity); - Genode::log("SCI IRQ: ", irq_handler.irq, - " (", irq_handler.trigger, "-", irq_handler.polarity, ")"); + log("SCI IRQ: ", irq_handler.irq, " (", irq_handler.trigger, "-", + irq_handler.polarity, ")"); sci_conn->sigh(sci_irq); sci_conn->ack_irq(); + + if (periodic_ms) { + timer.sigh(timer_trigger); + timer.trigger_periodic(Microseconds(periodic_ms * 1000).value); + } } + + void handle_timer() + { + if (!irq_handler.handler) + return; + + irq_handler.handler(irq_handler.context); + + if (report) + report->generate_report(true /* force */); + } + + void acpi_irq() { if (!irq_handler.handler) @@ -182,9 +207,6 @@ struct Acpica::Main unchanged_state_count ++; if (unchanged_state_count >= unchanged_state_max) { - Genode::log("generate report because of ", - unchanged_state_count, " irqs without state " - "changes"); report->generate_report(true); unchanged_state_count = 0; } @@ -228,31 +250,29 @@ void Acpica::Main::init_acpica() if (false) { AcpiDbgLevel |= ACPI_LV_IO | ACPI_LV_INTERRUPTS | ACPI_LV_INIT_NAMES; AcpiDbgLayer |= ACPI_TABLES; - Genode::log("debugging level=", Genode::Hex(AcpiDbgLevel), - " layers=", Genode::Hex(AcpiDbgLayer)); + log("debugging level=", Hex(AcpiDbgLevel), + " layers=", Hex(AcpiDbgLayer)); } ACPI_STATUS status = AcpiInitializeSubsystem(); if (status != AE_OK) { - Genode::error("AcpiInitializeSubsystem failed, status=", status); + error("AcpiInitializeSubsystem failed, status=", status); return; } status = AcpiInitializeTables(nullptr, 0, true); if (status != AE_OK) { - Genode::error("AcpiInitializeTables failed, status=", status); + error("AcpiInitializeTables failed, status=", status); return; } status = AcpiLoadTables(); if (status != AE_OK) { - Genode::error("AcpiLoadTables failed, status=", status); + error("AcpiLoadTables failed, status=", status); return; } { - using Genode::Irq_session; - /* * ACPI Spec 2.1 General ACPI Terminology * @@ -269,8 +289,6 @@ void Acpica::Main::init_acpica() ACPI_STATUS status = AcpiGetTable(ACPI_STRING(ACPI_SIG_MADT), 0, (ACPI_TABLE_HEADER **)&madt); if (status == AE_OK) { - using Genode::String; - for_each_element(madt, (ACPI_SUBTABLE_HEADER *) nullptr, [&](ACPI_SUBTABLE_HEADER const * const s) { @@ -313,89 +331,88 @@ void Acpica::Main::init_acpica() status = AcpiEnableSubsystem(ACPI_FULL_INITIALIZATION); if (status != AE_OK) { - Genode::error("AcpiEnableSubsystem failed, status=", status); + error("AcpiEnableSubsystem failed, status=", status); return; } status = AcpiInitializeObjects(ACPI_NO_DEVICE_INIT); if (status != AE_OK) { - Genode::error("AcpiInitializeObjects (no devices) failed, status=", status); + error("AcpiInitializeObjects (no devices) failed, status=", status); return; } /* set APIC mode */ status = init_pic_mode(); if (status != AE_OK) { - Genode::error("Setting PIC mode failed, status=", status); + error("Setting PIC mode failed, status=", status); return; } /* Embedded controller */ status = AcpiGetDevices(ACPI_STRING("PNP0C09"), Ec::detect, this, nullptr); if (status != AE_OK) { - Genode::error("AcpiGetDevices failed, status=", status); + error("AcpiGetDevices failed, status=", status); return; } status = AcpiInitializeObjects(ACPI_FULL_INITIALIZATION); if (status != AE_OK) { - Genode::error("AcpiInitializeObjects (full init) failed, status=", status); + error("AcpiInitializeObjects (full init) failed, status=", status); return; } status = AcpiUpdateAllGpes(); if (status != AE_OK) { - Genode::error("AcpiUpdateAllGpes failed, status=", status); + error("AcpiUpdateAllGpes failed, status=", status); return; } status = AcpiEnableAllRuntimeGpes(); if (status != AE_OK) { - Genode::error("AcpiEnableAllRuntimeGpes failed, status=", status); + error("AcpiEnableAllRuntimeGpes failed, status=", status); return; } - /* note: ACPI_EVENT_PMTIMER claimed by nova kernel - not usable by us */ Fixed * acpi_fixed = new (heap) Fixed(report); status = AcpiInstallFixedEventHandler(ACPI_EVENT_POWER_BUTTON, Fixed::handle_power_button, acpi_fixed); if (status != AE_OK) - Genode::log("failed - power button registration - error=", status); + log("failed - power button registration - error=", status); status = AcpiInstallFixedEventHandler(ACPI_EVENT_SLEEP_BUTTON, Fixed::handle_sleep_button, acpi_fixed); if (status != AE_OK) - Genode::log("failed - sleep button registration - error=", status); + log("failed - sleep button registration - error=", status); /* AC Adapters and Power Source Objects */ status = AcpiGetDevices(ACPI_STRING("ACPI0003"), Ac::detect, this, nullptr); if (status != AE_OK) { - Genode::error("AcpiGetDevices (ACPI0003) failed, status=", status); + error("AcpiGetDevices (ACPI0003) failed, status=", status); return; } /* Smart battery control devices */ status = AcpiGetDevices(ACPI_STRING("PNP0C0A"), Battery::detect, this, nullptr); if (status != AE_OK) { - Genode::error("AcpiGetDevices (PNP0C0A) failed, status=", status); + error("AcpiGetDevices (PNP0C0A) failed, status=", status); return; } /* LID device */ status = AcpiGetDevices(ACPI_STRING("PNP0C0D"), Lid::detect, this, nullptr); if (status != AE_OK) { - Genode::error("AcpiGetDevices (PNP0C0D) failed, status=", status); + error("AcpiGetDevices (PNP0C0D) failed, status=", status); return; } /* Fujitsu HID device */ status = AcpiGetDevices(ACPI_STRING("FUJ02E3"), Fuj02e3::detect, this, nullptr); if (status != AE_OK) { - Genode::error("AcpiGetDevices (FUJ02E3) failed, status=", status); + error("AcpiGetDevices (FUJ02E3) failed, status=", status); return; } } @@ -408,7 +425,7 @@ ACPI_STATUS AcpiOsInstallInterruptHandler(UINT32 irq, ACPI_OSD_HANDLER handler, void *context) { if (irq != Acpica::Main::irq_handler.irq) { - Genode::error("SCI interrupt is ", Acpica::Main::irq_handler.irq, + error("SCI interrupt is ", Acpica::Main::irq_handler.irq, " but library requested ", irq); return AE_BAD_PARAMETER; } @@ -419,7 +436,7 @@ ACPI_STATUS AcpiOsInstallInterruptHandler(UINT32 irq, ACPI_OSD_HANDLER handler, } -void Component::construct(Genode::Env &env) +void Component::construct(Env &env) { /* XXX execute constructors of global statics */ env.exec_static_constructors();