From b73159fecf9b6b16f3a5628323bad438fc369664 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Herm=C3=A8s=20B=C3=A9lusca-Ma=C3=AFto?= Date: Sat, 13 Sep 2025 18:05:23 +0200 Subject: [PATCH] [BATTC][COMPBATT] Move the IOCTL_BATTERY_QUERY_STATUS wait hack to BATTC (#8384) CORE-20343 The 3-second timeout FIXME (instead of waiting indefinitely), made in the COMPBATT worker thread for the `IOCTL_BATTERY_QUERY_STATUS` case, was done because _*our*_ BATTC handler expects the batteries to always support the BTP (Battery Trip Point) feature for signaling a change of battery status, but in the cases where it isn't supported, any waits it tried for the battery to notify about a status change would never happen. Furthermore, following commit 3a6e0d4b65, the `SetStatusNotify()` call (_which always fails if the battery doesn't support the BTP feature_) would now always exit the `IOCTL_BATTERY_QUERY_STATUS` handling without any waiting nor battery polling [^1], and this would cause the COMPBATT worker thread to busy-poll again forever. The timeout FIXME is now moved to BATTC, instead of COMPBATT, since the actual fixes should be in BATTC. In particular, it should queue all the query IOCTLs and then serve them, either using the StatusNotify (BTP) functionality if the battery supports it, or if not, do a very-slow battery polling. I've also increased the timeout a little bit more (5 seconds and not 3). [^1]: Per the ACPI specification, it is expected that the operating system performs battery polling if the battery doesn't support BTP, see: https://uefi.org/htmlspecs/ACPI_Spec_6_4_html/10_Power_Source_and_Power_Meter_Devices/Power_Source_and_Power_Meter_Devices.html#btp-battery-trip-point --- drivers/battery/battc/battc.c | 9 +++++++-- drivers/battery/compbatt/compbatt.c | 4 ++-- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/drivers/battery/battc/battc.c b/drivers/battery/battc/battc.c index 33cbc438475..1d90b30f399 100644 --- a/drivers/battery/battc/battc.c +++ b/drivers/battery/battc/battc.c @@ -292,8 +292,13 @@ BatteryClassIoctl(PVOID ClassData, &BattNotify); if (!NT_SUCCESS(Status)) { - DPRINT1("SetStatusNotify failed (0x%x)\n", Status); - break; + DPRINT("SetStatusNotify failed (0x%x)\n", Status); + // HACK: Continue anyway; the non-zero timeout will limit polling rate. + // FIXME: Hardcoded (wait for 5 seconds) because ACPI notifications don't work... + BattWait.Timeout = 5000; + // FIXME 2: All these IOCTLs handled in BatteryClassIoctl() should actually + // be queued and be serviced by a worker thread that also handles the slow + // battery polling, in case the battery doesn't support status notifications. } ExAcquireFastMutex(&BattClass->Mutex); diff --git a/drivers/battery/compbatt/compbatt.c b/drivers/battery/compbatt/compbatt.c index 3edb3fb78a8..2b138492912 100644 --- a/drivers/battery/compbatt/compbatt.c +++ b/drivers/battery/compbatt/compbatt.c @@ -80,7 +80,7 @@ CompBattSystemControl( * location which contains the data of the individual battery. * * @param[in] Context - * An aribtrary pointer that points to context data, this paramater + * An arbitrary pointer that points to context data, this parameter * is unused. * * @return @@ -355,7 +355,7 @@ CompBattMonitorIrpCompleteWorker( /* Setup the necessary data to read battery status */ BatteryData->WaitStatus.BatteryTag = BatteryData->Tag; - BatteryData->WaitStatus.Timeout = 3000; // FIXME: Hardcoded (wait for 3 seconds) because we do not have ACPI notifications implemented yet... + BatteryData->WaitStatus.Timeout = -1; RtlCopyMemory(&BatteryData->WorkerBuffer.WorkerWaitStatus, &BatteryData->WaitStatus,