From 3d06be8d79e759c4574d1005e7cbc73d67a2839d Mon Sep 17 00:00:00 2001 From: Kate Hsuan Date: Wed, 19 Aug 2026 21:09:10 +0800 Subject: [PATCH] RHEL-117344 Update to the upstream version 0.1.0 and enable Nova Lake Update to the upstream version 0.1.0 and include the latest patches to enable Nova Lake CPU. Resolves: RHEL-117344 Signed-off-by: Kate Hsuan --- ...us-glib-dependency-at-Install-Depend.patch | 33 + 0001-lpmd_util-Remove-unused-variables.patch | 37 - ...u-Tablets-are-also-a-Mobile-platform.patch | 27 + ...roxy-state_manager-Fix-Werror-switch.patch | 26 - ...en-coded-if-in-configure.ac-with-AS_.patch | 54 + ...y-state_util-Remove-unused-variables.patch | 29 - 0004-build-avoid-use-of-test-.-a.patch | 30 + ...util-Drop-unused-function-read_tsc_c.patch | 33 - ...ng-in-error-message-when-libsystemd-.patch | 27 + ...istent-argument-quoting-in-configure.patch | 124 + ...le-isolation-fix-works-without-inter.patch | 45 + ...x-issue-106-incorrect-order-of-polli.patch | 48 + ...ne-Fix-deadlock-on-power-profile-swi.patch | 82 + 0010-Process-itmt-read-error.patch | 37 + 0011-lpmd_misc-Fix-ITMT.patch | 193 + 0012-make-itmt_init-to-void.patch | 74 + 0013-config-Fix-incorrect-cpu-numbers.patch | 46 + ...long-lines-into-markdown-readable-bl.patch | 61 + ...Emphasize-expectations-from-the-user.patch | 35 + 0016-man-Update-the-main-man-page.patch | 90 + ...Update-lpmd-control-utility-man-page.patch | 59 + ...neric-updates-to-the-config-man-page.patch | 137 + ...config-options-to-the-unused-section.patch | 177 + 0020-Add-Panther-Lake-4P0E4L.patch | 48 + 0021-Remove-power-group.patch | 30 + ...us-method-to-query-current-LPM-contr.patch | 121 + ...ix-restore-systemd-unit-install-path.patch | 26 + ...up-isolation-churn-during-WLT-pollin.patch | 83 + ...-build-breakage-with-the-last-commit.patch | 31 + 0026-git-Setup-gitignore.patch | 62 + ...nup-code-indentation-in-parse-states.patch | 171 + ...nfig-Rename-island-number-cores-tags.patch | 108 + ...ne-Count-system-of-specifing-active-.patch | 262 + ...Dynamic-core-type-cpumask-allocation.patch | 258 + ...L-keyword-for-active-P-E-L-cores-tag.patch | 173 + ...nfig-Simplify-the-M204-configuration.patch | 74 + ...-Fix-incorrect-struct-initialization.patch | 36 + ...LT-state-mask-and-notification-delay.patch | 224 + 0035-Arrow-Lake-enabling.patch | 217 + ...-platform-check-if-a-matching-config.patch | 230 + 0037-config-Nova-Lake-enabling.patch | 189 + ...ldcard-for-active_cpus-and-cpu-types.patch | 72 + 0039-data-Fix-active-cpu-spelling.patch | 57 + ...agnostic-config-fallback-for-unknown.patch | 43 + 0041-docs-Clarify-slider-config.patch | 38 + ...der-balance-and-offset-configuration.patch | 244 + ...actor-get_cgroup_systemd_vals-to-avo.patch | 115 + ...lpmd_cpu-Add-a-CPU-blacklist-cpumask.patch | 70 + ...lling-out-type-cpumasks-if-there-was.patch | 40 + ...t-level-complex-isolation-fix-blackl.patch | 154 + ...resh-cached-data-when-blacklisting-c.patch | 211 + ...umask-Refactor-getting-cached-values.patch | 118 + ...-the-state-name-when-an-empty-cpumas.patch | 76 + 0050-Use-return-value-of-lpmd_read_int.patch | 57 + 0051-all-Apply-kernel-formatting.patch | 9475 +++++++++++++++++ ...le-Makefile-to-use-without-autotools.patch | 209 + 0053-Minor-printf-formatting-fixes.patch | 42 + ...x-compilation-warning-on-buffer-size.patch | 28 + ..._exclude_copy-destination-population.patch | 34 + ...-is-enabled-don-t-disable-util-calcu.patch | 35 + intel-lpmd.spec | 75 +- sources | 2 +- 62 files changed, 14906 insertions(+), 136 deletions(-) create mode 100644 0001-Deprecate-the-dbus-glib-dependency-at-Install-Depend.patch delete mode 100644 0001-lpmd_util-Remove-unused-variables.patch create mode 100644 0002-lpmd_cpu-Tablets-are-also-a-Mobile-platform.patch delete mode 100644 0002-wlt_proxy-state_manager-Fix-Werror-switch.patch create mode 100644 0003-build-replace-open-coded-if-in-configure.ac-with-AS_.patch delete mode 100644 0003-wlt_proxy-state_util-Remove-unused-variables.patch create mode 100644 0004-build-avoid-use-of-test-.-a.patch delete mode 100644 0004-wlt_proxy-state_util-Drop-unused-function-read_tsc_c.patch create mode 100644 0005-build-fix-spelling-in-error-message-when-libsystemd-.patch create mode 100644 0006-build-apply-consistent-argument-quoting-in-configure.patch create mode 100644 0007-lpmd_cgroup-simple-isolation-fix-works-without-inter.patch create mode 100644 0008-state_machine-Fix-issue-106-incorrect-order-of-polli.patch create mode 100644 0009-lpmd_state_machine-Fix-deadlock-on-power-profile-swi.patch create mode 100644 0010-Process-itmt-read-error.patch create mode 100644 0011-lpmd_misc-Fix-ITMT.patch create mode 100644 0012-make-itmt_init-to-void.patch create mode 100644 0013-config-Fix-incorrect-cpu-numbers.patch create mode 100644 0014-readme-Reformat-long-lines-into-markdown-readable-bl.patch create mode 100644 0015-readme-Emphasize-expectations-from-the-user.patch create mode 100644 0016-man-Update-the-main-man-page.patch create mode 100644 0017-man-Update-lpmd-control-utility-man-page.patch create mode 100644 0018-man-Generic-updates-to-the-config-man-page.patch create mode 100644 0019-man-Move-unused-config-options-to-the-unused-section.patch create mode 100644 0020-Add-Panther-Lake-4P0E4L.patch create mode 100644 0021-Remove-power-group.patch create mode 100644 0022-Add-GetState-D-Bus-method-to-query-current-LPM-contr.patch create mode 100644 0023-fix-restore-systemd-unit-install-path.patch create mode 100644 0024-fix-prevent-cgroup-isolation-churn-during-WLT-pollin.patch create mode 100644 0025-Fix-build-breakage-with-the-last-commit.patch create mode 100644 0026-git-Setup-gitignore.patch create mode 100644 0027-lpmd_config-Cleanup-code-indentation-in-parse-states.patch create mode 100644 0028-lpmd_config-Rename-island-number-cores-tags.patch create mode 100644 0029-lpmd_state_machine-Count-system-of-specifing-active-.patch create mode 100644 0030-lpmd_cpumask-Dynamic-core-type-cpumask-allocation.patch create mode 100644 0031-lpmd_config-ALL-keyword-for-active-P-E-L-cores-tag.patch create mode 100644 0032-config-Simplify-the-M204-configuration.patch create mode 100644 0033-lpmd_cpu-Fix-incorrect-struct-initialization.patch create mode 100644 0034-Introduce-WLT-state-mask-and-notification-delay.patch create mode 100644 0035-Arrow-Lake-enabling.patch create mode 100644 0036-lpmd_config-Skip-platform-check-if-a-matching-config.patch create mode 100644 0037-config-Nova-Lake-enabling.patch create mode 100644 0038-lpmd_cpu-Add-wildcard-for-active_cpus-and-cpu-types.patch create mode 100644 0039-data-Fix-active-cpu-spelling.patch create mode 100644 0040-Enable-platform-agnostic-config-fallback-for-unknown.patch create mode 100644 0041-docs-Clarify-slider-config.patch create mode 100644 0042-Validate-slider-balance-and-offset-configuration.patch create mode 100644 0043-lpmd_cpumask-Refactor-get_cgroup_systemd_vals-to-avo.patch create mode 100644 0044-lpmd_cpu-Add-a-CPU-blacklist-cpumask.patch create mode 100644 0045-lpmd_cpu-Skip-filling-out-type-cpumasks-if-there-was.patch create mode 100644 0046-lpmd_cpumask-init-level-complex-isolation-fix-blackl.patch create mode 100644 0047-lpmd_cpumask-Refresh-cached-data-when-blacklisting-c.patch create mode 100644 0048-lpmd_cpumask-Refactor-getting-cached-values.patch create mode 100644 0049-lpmd_proc-Export-the-state-name-when-an-empty-cpumas.patch create mode 100644 0050-Use-return-value-of-lpmd_read_int.patch create mode 100644 0051-all-Apply-kernel-formatting.patch create mode 100644 0052-Add-a-simple-Makefile-to-use-without-autotools.patch create mode 100644 0053-Minor-printf-formatting-fixes.patch create mode 100644 0054-lpmd_config-Fix-compilation-warning-on-buffer-size.patch create mode 100644 0055-Fix-cpumask_exclude_copy-destination-population.patch create mode 100644 0056-When-GFX-trigger-is-enabled-don-t-disable-util-calcu.patch diff --git a/0001-Deprecate-the-dbus-glib-dependency-at-Install-Depend.patch b/0001-Deprecate-the-dbus-glib-dependency-at-Install-Depend.patch new file mode 100644 index 0000000..dc80166 --- /dev/null +++ b/0001-Deprecate-the-dbus-glib-dependency-at-Install-Depend.patch @@ -0,0 +1,33 @@ +From 48fc07ee76506f8412f5770116d19a337254caf3 Mon Sep 17 00:00:00 2001 +From: Bin Li +Date: Fri, 19 Dec 2025 22:23:18 +0800 +Subject: [PATCH 01/56] Deprecate the dbus-glib dependency at Install + Dependencies + +--- + README.md | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/README.md b/README.md +index 292ee76..d65ae0d 100644 +--- a/README.md ++++ b/README.md +@@ -17,13 +17,13 @@ man intel_lpmd_config.xml + ### Fedora + + ```sh +-dnf install automake autoconf-archive gcc glib2-devel dbus-glib-devel libxml2-devel libnl3-devel systemd-devel gtk-doc upower-devel ++dnf install automake autoconf-archive gcc glib2-devel libxml2-devel libnl3-devel systemd-devel gtk-doc upower-devel + ``` + + ### Ubuntu + + ```sh +-sudo apt install autoconf autoconf-archive gcc libglib2.0-dev libdbus-1-dev libdbus-glib-1-dev libxml2-dev libnl-3-dev libnl-genl-3-dev libsystemd-dev gtk-doc-tools libupower-glib-dev ++sudo apt install autoconf autoconf-archive gcc libglib2.0-dev libdbus-1-dev libxml2-dev libnl-3-dev libnl-genl-3-dev libsystemd-dev gtk-doc-tools libupower-glib-dev + ``` + + ### OpenSUSE +-- +2.55.0 + diff --git a/0001-lpmd_util-Remove-unused-variables.patch b/0001-lpmd_util-Remove-unused-variables.patch deleted file mode 100644 index 75a4766..0000000 --- a/0001-lpmd_util-Remove-unused-variables.patch +++ /dev/null @@ -1,37 +0,0 @@ -From c2cea33c873146f1b6186c02fe79d1a2bb1c7867 Mon Sep 17 00:00:00 2001 -From: Kate Hsuan -Date: Fri, 2 May 2025 16:49:00 +0800 -Subject: [PATCH 1/4] lpmd_util: Remove unused variables - -Remove unused variables. ---- - src/lpmd_util.c | 3 --- - 1 file changed, 3 deletions(-) - -diff --git a/src/lpmd_util.c b/src/lpmd_util.c -index cd3123a..55f7874 100644 ---- a/src/lpmd_util.c -+++ b/src/lpmd_util.c -@@ -83,7 +83,6 @@ static int probe_gfx_util_sysfs(void) - { - FILE *fp; - char buf[8]; -- bool gt0_is_gt; - - if (access("/sys/class/drm/card0/device/tile0/gt0/gtidle/idle_residency_ms", R_OK)) - return 1; -@@ -119,11 +118,9 @@ static int get_gfx_util_sysfs(unsigned long long time_ms) - { - static unsigned long long gfx_rc6_prev = ULLONG_MAX, sam_mc6_prev = ULLONG_MAX; - unsigned long long gfx_rc6, sam_mc6; -- unsigned long long val; - FILE *fp; - int gfx_util, sam_util; - int ret; -- int i; - - gfx_util = sam_util = -1; - --- -2.49.0 - diff --git a/0002-lpmd_cpu-Tablets-are-also-a-Mobile-platform.patch b/0002-lpmd_cpu-Tablets-are-also-a-Mobile-platform.patch new file mode 100644 index 0000000..2742b24 --- /dev/null +++ b/0002-lpmd_cpu-Tablets-are-also-a-Mobile-platform.patch @@ -0,0 +1,27 @@ +From 3f642fc7bb5f7798e53acb8be9ede2b99a88eac1 Mon Sep 17 00:00:00 2001 +From: Qubic +Date: Tue, 17 Feb 2026 17:57:30 +0100 +Subject: [PATCH 02/56] lpmd_cpu: Tablets are also a Mobile platform see: + https://uefi.org/htmlspecs/ACPI_Spec_6_4_html/05_ACPI_Software_Programming_Model/ACPI_Software_Programming_Model.html#preferred-pm-profile-system-types + +Signed-off-by: Qubic +--- + src/lpmd_cpu.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/src/lpmd_cpu.c b/src/lpmd_cpu.c +index caa6d11..e611b78 100644 +--- a/src/lpmd_cpu.c ++++ b/src/lpmd_cpu.c +@@ -96,7 +96,7 @@ int detect_supported_platform(lpmd_config_t *lpmd_config) + return -1; + } + +- if (val != 2) { ++ if (val != 2 && val != 8) { + lpmd_log_info("Non-Mobile PM profile detected. %s returns %d\n", PATH_PM_PROFILE, val); + return -1; + } +-- +2.55.0 + diff --git a/0002-wlt_proxy-state_manager-Fix-Werror-switch.patch b/0002-wlt_proxy-state_manager-Fix-Werror-switch.patch deleted file mode 100644 index 19537c7..0000000 --- a/0002-wlt_proxy-state_manager-Fix-Werror-switch.patch +++ /dev/null @@ -1,26 +0,0 @@ -From 311b7929d4c821630fabf5293ec5b4bec5411162 Mon Sep 17 00:00:00 2001 -From: Kate Hsuan -Date: Fri, 2 May 2025 16:49:42 +0800 -Subject: [PATCH 2/4] wlt_proxy: state_manager: Fix -Werror=switch - -Fix the swicth expression to avoid -Werror=switch warnning. ---- - src/wlt_proxy/state_manager.c | 2 ++ - 1 file changed, 2 insertions(+) - -diff --git a/src/wlt_proxy/state_manager.c b/src/wlt_proxy/state_manager.c -index 7841135..9753442 100644 ---- a/src/wlt_proxy/state_manager.c -+++ b/src/wlt_proxy/state_manager.c -@@ -285,6 +285,8 @@ int staytime_to_staycount(enum state_idx state) - case PERF_MODE: - stay_count = (int)PERF_MODE_STAY/get_poll_ms(PERF_MODE); - break; -+ default: -+ break; - } - return stay_count; - } --- -2.49.0 - diff --git a/0003-build-replace-open-coded-if-in-configure.ac-with-AS_.patch b/0003-build-replace-open-coded-if-in-configure.ac-with-AS_.patch new file mode 100644 index 0000000..01df0ce --- /dev/null +++ b/0003-build-replace-open-coded-if-in-configure.ac-with-AS_.patch @@ -0,0 +1,54 @@ +From e1b353ab97f820654e402e549d43939987a5b512 Mon Sep 17 00:00:00 2001 +From: Jan Engelhardt +Date: Fri, 16 Jan 2026 11:18:08 +0100 +Subject: [PATCH 03/56] build: replace open-coded `if` in configure.ac with + `AS_IF` +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +The manual says: "This macro should be used instead of plain ‘if’ in +code outside of an ‘AC_DEFUN’ macro, when the contents of the ‘if’ +use ‘AC_REQUIRE’ directly or indirectly". Since one cannot know +whether something is going to be AC_REQUIRED indirectly, it is safer +to just always use AS_IF. + +Signed-off-by: Jan Engelhardt +--- + configure.ac | 10 +++++----- + 1 file changed, 5 insertions(+), 5 deletions(-) + +diff --git a/configure.ac b/configure.ac +index 36ed1d0..8bf5a78 100644 +--- a/configure.ac ++++ b/configure.ac +@@ -18,11 +18,11 @@ AM_MAINTAINER_MODE([enable]) + GTK_DOC_CHECK([1.11],[--flavour no-tmpl]) + + AC_ARG_WITH(dbus-sys-dir, AS_HELP_STRING([--with-dbus-sys-dir=DIR], [where D-BUS system.d directory is])) +-if test -n "$with_dbus_sys_dir" ; then ++AS_IF([test -n "$with_dbus_sys_dir"], [ + DBUS_SYS_DIR="$with_dbus_sys_dir" +-else ++], [ + DBUS_SYS_DIR="/etc/dbus-1/system.d" +-fi ++]) + AC_SUBST(DBUS_SYS_DIR) + + # paths +@@ -34,9 +34,9 @@ PKG_PROG_PKG_CONFIG + AC_ARG_WITH([systemdsystemunitdir], + AS_HELP_STRING([--with-systemdsystemunitdir=DIR], [Directory for systemd service files]), + [], [with_systemdsystemunitdir=$($PKG_CONFIG --variable=systemdsystemunitdir systemd)]) +-if test "x$with_systemdsystemunitdir" != xno; then ++AS_IF(["x$with_systemdsystemunitdir" != xno], [ + AC_SUBST([systemdsystemunitdir], [$with_systemdsystemunitdir]) +-fi ++]) + + AM_CONDITIONAL(HAVE_SYSTEMD, [test -n "$with_systemdsystemunitdir" -a "x$with_systemdsystemunitdir" != xno ]) + +-- +2.55.0 + diff --git a/0003-wlt_proxy-state_util-Remove-unused-variables.patch b/0003-wlt_proxy-state_util-Remove-unused-variables.patch deleted file mode 100644 index 15151a8..0000000 --- a/0003-wlt_proxy-state_util-Remove-unused-variables.patch +++ /dev/null @@ -1,29 +0,0 @@ -From 4277f3496dc51f89ed0815e0f51659338f7a6ba9 Mon Sep 17 00:00:00 2001 -From: Kate Hsuan -Date: Fri, 2 May 2025 16:52:16 +0800 -Subject: [PATCH 3/4] wlt_proxy: state_util: Remove unused variables - -Remove unused variables. ---- - src/wlt_proxy/state_util.c | 3 +-- - 1 file changed, 1 insertion(+), 2 deletions(-) - -diff --git a/src/wlt_proxy/state_util.c b/src/wlt_proxy/state_util.c -index 95422c8..9d633d5 100644 ---- a/src/wlt_proxy/state_util.c -+++ b/src/wlt_proxy/state_util.c -@@ -381,10 +381,9 @@ static int read_aperf_mperf_tsc_perf(struct thread_data *t, int cpu) { - /*Calc perf [cpu utilization per core] difference from MSR registers */ - int update_perf_diffs(float *sum_norm_perf, int stat_init_only) { - -- int fd, maxed_cpu = -1; -+ int maxed_cpu = -1; - float min_load = 100.0, min_s0 = 1.0, next_s0 = 1.0; - float max_load = 0, max_2nd_load = 0, max_3rd_load = 0, next_load = 0; -- uint64_t aperf_raw, mperf_raw, pperf_raw, tsc_raw, poll_cpu_us = 0; - int t, min_s0_cpu = 0, first_pass = 1; - - for (t = 0; t < get_max_online_cpu(); t++) { --- -2.49.0 - diff --git a/0004-build-avoid-use-of-test-.-a.patch b/0004-build-avoid-use-of-test-.-a.patch new file mode 100644 index 0000000..e6edd93 --- /dev/null +++ b/0004-build-avoid-use-of-test-.-a.patch @@ -0,0 +1,30 @@ +From 0911dcf1d2350f99f02198bbfb00cc31c317efc5 Mon Sep 17 00:00:00 2001 +From: Jan Engelhardt +Date: Fri, 16 Jan 2026 11:21:27 +0100 +Subject: [PATCH 04/56] build: avoid use of `test ... -a` + +The use of `-a` is non-portable, and it has been actively removed +from POSIX.1-2024 +. + +Signed-off-by: Jan Engelhardt +--- + configure.ac | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/configure.ac b/configure.ac +index 8bf5a78..4f79d86 100644 +--- a/configure.ac ++++ b/configure.ac +@@ -38,7 +38,7 @@ AS_IF(["x$with_systemdsystemunitdir" != xno], [ + AC_SUBST([systemdsystemunitdir], [$with_systemdsystemunitdir]) + ]) + +-AM_CONDITIONAL(HAVE_SYSTEMD, [test -n "$with_systemdsystemunitdir" -a "x$with_systemdsystemunitdir" != xno ]) ++AM_CONDITIONAL(HAVE_SYSTEMD, [test -n "$with_systemdsystemunitdir" && test "x$with_systemdsystemunitdir" != xno]) + + # print configuration + echo +-- +2.55.0 + diff --git a/0004-wlt_proxy-state_util-Drop-unused-function-read_tsc_c.patch b/0004-wlt_proxy-state_util-Drop-unused-function-read_tsc_c.patch deleted file mode 100644 index 39d03c8..0000000 --- a/0004-wlt_proxy-state_util-Drop-unused-function-read_tsc_c.patch +++ /dev/null @@ -1,33 +0,0 @@ -From af6d8f93a0a1041bd936b8901707e1253c5e5279 Mon Sep 17 00:00:00 2001 -From: Kate Hsuan -Date: Fri, 2 May 2025 17:07:21 +0800 -Subject: [PATCH 4/4] wlt_proxy: state_util: Drop unused function - read_tsc_config() - -Drop the unused function read_tsc_config(). ---- - src/wlt_proxy/state_util.c | 8 -------- - 1 file changed, 8 deletions(-) - -diff --git a/src/wlt_proxy/state_util.c b/src/wlt_proxy/state_util.c -index 9d633d5..f35242e 100644 ---- a/src/wlt_proxy/state_util.c -+++ b/src/wlt_proxy/state_util.c -@@ -268,14 +268,6 @@ static unsigned int read_mperf_config(void) { - return read_perf_counter_info_n(path, format); - } - --/*helper - pperf reading */ --static unsigned int read_tsc_config(void) { -- const char *const path = "/sys/bus/event_source/devices/msr/events/tsc"; -- const char *const format = "event=%x"; -- -- return read_perf_counter_info_n(path, format); --} -- - /*helper - pperf reading */ - static unsigned int read_msr_type(void) { - const char *const path = "/sys/bus/event_source/devices/msr/type"; --- -2.49.0 - diff --git a/0005-build-fix-spelling-in-error-message-when-libsystemd-.patch b/0005-build-fix-spelling-in-error-message-when-libsystemd-.patch new file mode 100644 index 0000000..2adc13c --- /dev/null +++ b/0005-build-fix-spelling-in-error-message-when-libsystemd-.patch @@ -0,0 +1,27 @@ +From e08ccef11217a1b0cd7355ba5708fce56a1d02cd Mon Sep 17 00:00:00 2001 +From: Jan Engelhardt +Date: Fri, 16 Jan 2026 11:41:50 +0100 +Subject: [PATCH 05/56] build: fix spelling in error message when libsystemd is + absent + +Signed-off-by: Jan Engelhardt +--- + configure.ac | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/configure.ac b/configure.ac +index 4f79d86..d35d75b 100644 +--- a/configure.ac ++++ b/configure.ac +@@ -69,7 +69,7 @@ PKG_CHECK_MODULES(libnlgenl30, [libnl-genl-3.0], libnlgenl30=yes, libnlgenl30=no + + PKG_CHECK_MODULES([SYSTEMD], [libsystemd], [], + [PKG_CHECK_MODULES([SYSTEMD], [libsystemd-daemon], [], +- AC_MSG_ERROR([libsystemd support requested but found]))]) ++ AC_MSG_ERROR([libsystemd support requested but not found]))]) + + PKG_CHECK_MODULES(UPOWER, upower-glib) + +-- +2.55.0 + diff --git a/0006-build-apply-consistent-argument-quoting-in-configure.patch b/0006-build-apply-consistent-argument-quoting-in-configure.patch new file mode 100644 index 0000000..0e70b15 --- /dev/null +++ b/0006-build-apply-consistent-argument-quoting-in-configure.patch @@ -0,0 +1,124 @@ +From ec31f9c65057dd9f2aa41449e994ba8af7569041 Mon Sep 17 00:00:00 2001 +From: Jan Engelhardt +Date: Fri, 16 Jan 2026 11:43:09 +0100 +Subject: [PATCH 06/56] build: apply consistent argument quoting in + configure.ac + +Signed-off-by: Jan Engelhardt +--- + configure.ac | 44 ++++++++++++++++++++++---------------------- + 1 file changed, 22 insertions(+), 22 deletions(-) + +diff --git a/configure.ac b/configure.ac +index d35d75b..b212c4d 100644 +--- a/configure.ac ++++ b/configure.ac +@@ -1,4 +1,4 @@ +-AC_PREREQ(1.0) ++AC_PREREQ([1.0]) + + m4_define([lpmd_major_version], [0]) + m4_define([lpmd_minor_version], [1.0]) +@@ -9,7 +9,7 @@ AC_INIT([intel_lpmd], [lpmd_version], [], [intel_lpmd]) + m4_ifdef([AM_SILENT_RULES],[AM_SILENT_RULES([yes])]) + + AC_CONFIG_MACRO_DIR([m4]) +-AC_CONFIG_AUX_DIR(build-aux) ++AC_CONFIG_AUX_DIR([build-aux]) + AC_CONFIG_HEADERS([config.h]) + + AM_INIT_AUTOMAKE([1.11 foreign no-define subdir-objects]) +@@ -17,28 +17,28 @@ AM_MAINTAINER_MODE([enable]) + + GTK_DOC_CHECK([1.11],[--flavour no-tmpl]) + +-AC_ARG_WITH(dbus-sys-dir, AS_HELP_STRING([--with-dbus-sys-dir=DIR], [where D-BUS system.d directory is])) ++AC_ARG_WITH([dbus-sys-dir], [AS_HELP_STRING([--with-dbus-sys-dir=DIR], [where D-BUS system.d directory is])]) + AS_IF([test -n "$with_dbus_sys_dir"], [ + DBUS_SYS_DIR="$with_dbus_sys_dir" + ], [ + DBUS_SYS_DIR="/etc/dbus-1/system.d" + ]) +-AC_SUBST(DBUS_SYS_DIR) ++AC_SUBST([DBUS_SYS_DIR]) + + # paths +-AC_SUBST(lpmd_binary, "$sbindir/$PACKAGE", [Binary executable]) +-AC_SUBST(lpmd_confdir, "$sysconfdir/$PACKAGE", [Configuration directory]) +-AC_SUBST(lpmd_rundir, "$localstatedir/run/$PACKAGE", [Runtime state directory]) ++AC_SUBST([lpmd_binary], ["$sbindir/$PACKAGE"], [Binary executable]) ++AC_SUBST([lpmd_confdir], ["$sysconfdir/$PACKAGE"], [Configuration directory]) ++AC_SUBST([lpmd_rundir], ["$localstatedir/run/$PACKAGE"], [Runtime state directory]) + + PKG_PROG_PKG_CONFIG + AC_ARG_WITH([systemdsystemunitdir], +- AS_HELP_STRING([--with-systemdsystemunitdir=DIR], [Directory for systemd service files]), +- [], [with_systemdsystemunitdir=$($PKG_CONFIG --variable=systemdsystemunitdir systemd)]) ++ [AS_HELP_STRING([--with-systemdsystemunitdir=DIR], [Directory for systemd service files])], ++ [], [with_systemdsystemunitdir=$($PKG_CONFIG --variable=systemdsystemunitdir systemd)]) + AS_IF(["x$with_systemdsystemunitdir" != xno], [ + AC_SUBST([systemdsystemunitdir], [$with_systemdsystemunitdir]) + ]) + +-AM_CONDITIONAL(HAVE_SYSTEMD, [test -n "$with_systemdsystemunitdir" && test "x$with_systemdsystemunitdir" != xno]) ++AM_CONDITIONAL([HAVE_SYSTEMD], [test -n "$with_systemdsystemunitdir" && test "x$with_systemdsystemunitdir" != xno]) + + # print configuration + echo +@@ -52,26 +52,26 @@ echo " lpmd_rundir: $lpmd_rundir" + echo + + GETTEXT_PACKAGE=intel_lpmd +-AC_SUBST(GETTEXT_PACKAGE) +-AC_DEFINE_UNQUOTED(GETTEXT_PACKAGE,"$GETTEXT_PACKAGE", [Gettext package]) ++AC_SUBST([GETTEXT_PACKAGE]) ++AC_DEFINE_UNQUOTED([GETTEXT_PACKAGE], ["$GETTEXT_PACKAGE"], [Gettext package]) + + GLIB_VERSION_DEFINES="-DGLIB_VERSION_MIN_REQUIRED=GLIB_VERSION_2_26" + +-PKG_CHECK_MODULES(GLIB, gio-unix-2.0 >= 2.22 gmodule-2.0 glib-2.0 gobject-2.0) ++PKG_CHECK_MODULES([GLIB], [gio-unix-2.0 >= 2.22 gmodule-2.0 glib-2.0 gobject-2.0]) + GLIB_CFLAGS="$GLIB_CFLAGS $GLIB_VERSION_DEFINES" +-AC_SUBST(GLIB_CFLAGS) +-AC_SUBST(GLIB_LIBS) ++AC_SUBST([GLIB_CFLAGS]) ++AC_SUBST([GLIB_LIBS]) + +-PKG_CHECK_MODULES(XML, libxml-2.0 >= 2.4) ++PKG_CHECK_MODULES([XML], [libxml-2.0 >= 2.4]) + +-PKG_CHECK_MODULES(libnl30, [libnl-3.0], libnl30=yes, libnl30=no) +-PKG_CHECK_MODULES(libnlgenl30, [libnl-genl-3.0], libnlgenl30=yes, libnlgenl30=no) ++PKG_CHECK_MODULES([libnl30], [libnl-3.0], [libnl30=yes], [libnl30=no]) ++PKG_CHECK_MODULES([libnlgenl30], [libnl-genl-3.0], libnlgenl30=yes, libnlgenl30=no) + + PKG_CHECK_MODULES([SYSTEMD], [libsystemd], [], + [PKG_CHECK_MODULES([SYSTEMD], [libsystemd-daemon], [], +- AC_MSG_ERROR([libsystemd support requested but not found]))]) ++ [AC_MSG_ERROR([libsystemd support requested but not found])])]) + +-PKG_CHECK_MODULES(UPOWER, upower-glib) ++PKG_CHECK_MODULES([UPOWER], [upower-glib]) + + AC_PATH_PROG([GDBUS_CODEGEN],[gdbus-codegen]) + +@@ -81,14 +81,14 @@ AC_C_CONST + AC_C_INLINE + AC_TYPE_SIZE_T + +-AC_ARG_ENABLE(werror, AS_HELP_STRING([--disable-werror], [Disable -Werror])) ++AC_ARG_ENABLE([werror], [AS_HELP_STRING([--disable-werror], [Disable -Werror])]) + AS_IF([test "x$enable_werror" != "xno"], [CFLAGS="$CFLAGS -Werror"]) + + AC_CONFIG_FILES([Makefile + data/Makefile + tools/Makefile]) + +-AC_ARG_ENABLE(gdbus, ++AC_ARG_ENABLE([gdbus], + [AS_HELP_STRING([--disable-gdbus], + [Switch DBus backend to glib-dbus. (Default: GDBus)])], + [], +-- +2.55.0 + diff --git a/0007-lpmd_cgroup-simple-isolation-fix-works-without-inter.patch b/0007-lpmd_cgroup-simple-isolation-fix-works-without-inter.patch new file mode 100644 index 0000000..26d2da5 --- /dev/null +++ b/0007-lpmd_cgroup-simple-isolation-fix-works-without-inter.patch @@ -0,0 +1,45 @@ +From 9b40a73836b81f339fa419b594052c2c587964e4 Mon Sep 17 00:00:00 2001 +From: Maciej Wieczor-Retman +Date: Thu, 12 Mar 2026 15:22:15 +0100 +Subject: [PATCH 07/56] lpmd_cgroup: simple isolation fix - works without + interference + +cgroup isolation mode doesn't work in LPMD because when writing +'isolated' to cpuset.cpus.partition file the expectation is that +cpuset.cpus will be a subset of cpuset.cpus.exclusive of that cgroup. + +The simple fix is to write the same content to cpuset.cpus and +cpuset.cpus.exclusive when switching into the isolated mode. + +However a problem can appear if there are any other cgroups on the +system that have exclusive cpus claimed. For one LPMD will just shut +down if it can't set affinity into any cpu it wants during core type +discovery phase. Aside from that using this simple version of the fix +will later result in creating an invalid cgroup partition. + +Signed-off-by: Maciej Wieczor-Retman +--- + src/lpmd_cgroup.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +diff --git a/src/lpmd_cgroup.c b/src/lpmd_cgroup.c +index 46a3c50..5b53179 100644 +--- a/src/lpmd_cgroup.c ++++ b/src/lpmd_cgroup.c +@@ -177,10 +177,12 @@ static int process_cpu_isolate(lpmd_config_state_t *state) + return 1; + + if (!cpumask_equal(state->cpumask_idx, CPUMASK_ONLINE)) { +- if (lpmd_write_str ("/sys/fs/cgroup/lpm/cpuset.cpus", get_cpu_isolation_str(state->cpumask_idx), LPMD_LOG_DEBUG)) ++ if (lpmd_write_str ("/sys/fs/cgroup/lpm/cpuset.cpus.exclusive", get_cpu_isolation_str(state->cpumask_idx), LPMD_LOG_DEBUG)) + return 1; + if (lpmd_write_str ("/sys/fs/cgroup/lpm/cpuset.cpus.partition", "isolated", LPMD_LOG_DEBUG)) + return 1; ++ if (lpmd_write_str ("/sys/fs/cgroup/lpm/cpuset.cpus", get_cpu_isolation_str(state->cpumask_idx), LPMD_LOG_DEBUG)) ++ return 1; + } else { + if (lpmd_write_str ("/sys/fs/cgroup/lpm/cpuset.cpus", get_cpu_isolation_str(CPUMASK_ONLINE), LPMD_LOG_DEBUG)) + return 1; +-- +2.55.0 + diff --git a/0008-state_machine-Fix-issue-106-incorrect-order-of-polli.patch b/0008-state_machine-Fix-issue-106-incorrect-order-of-polli.patch new file mode 100644 index 0000000..f7cae38 --- /dev/null +++ b/0008-state_machine-Fix-issue-106-incorrect-order-of-polli.patch @@ -0,0 +1,48 @@ +From 9bc60393b78df98a80ceec5b50dc487e8778f187 Mon Sep 17 00:00:00 2001 +From: Maciej Wieczor-Retman +Date: Wed, 11 Feb 2026 18:45:10 +0100 +Subject: [PATCH 08/56] state_machine: Fix issue #106 - incorrect order of + polling interval writes + +When WLT proxy is enabled it's supposed to set it's own polling timeout. +The problem is in the state machine an early return happens - that +disables polling timeout - when the non-proxy polling is disabled. Given +that it has nothing to do with the proxy polling it should not interfere +in the proxy setting it's own timeouts. + +Change order of the early returns so that it happens after the WLT proxy +check - thereby not overwriting the interval assigned by the proxy code. + +Signed-off-by: Maciej Wieczor-Retman +--- + src/lpmd_state_machine.c | 8 ++++---- + 1 file changed, 4 insertions(+), 4 deletions(-) + +diff --git a/src/lpmd_state_machine.c b/src/lpmd_state_machine.c +index f1b736a..1f40c02 100644 +--- a/src/lpmd_state_machine.c ++++ b/src/lpmd_state_machine.c +@@ -174,16 +174,16 @@ static int get_config_state_interval(lpmd_config_t *config, int idx) + { + lpmd_config_state_t *state = &config->config_states[idx]; + ++ /* wlt proxy updates polling separately */ ++ if (config->wlt_proxy_enable) ++ return 0; ++ + /* Start polling only when needed */ + if (!polling_enabled) { + config->data.polling_interval = -1; + return 0; + } + +- /* wlt proxy updates polling separately */ +- if (config->wlt_proxy_enable) +- return 0; +- + /* Always start with minumum polling interval for a new state */ + if (idx != current_idx) { + config->data.polling_interval = state->min_poll_interval; +-- +2.55.0 + diff --git a/0009-lpmd_state_machine-Fix-deadlock-on-power-profile-swi.patch b/0009-lpmd_state_machine-Fix-deadlock-on-power-profile-swi.patch new file mode 100644 index 0000000..32934a4 --- /dev/null +++ b/0009-lpmd_state_machine-Fix-deadlock-on-power-profile-swi.patch @@ -0,0 +1,82 @@ +From 256ae2ba3ec0847b2a5f570509f7eccefb19ad45 Mon Sep 17 00:00:00 2001 +From: Maciej Wieczor-Retman +Date: Tue, 31 Mar 2026 22:51:43 +0200 +Subject: [PATCH 09/56] lpmd_state_machine: Fix deadlock on power profile + switch + +If one profile, let's say the balanced one, is set to enable AUTO LPMD, +and another one like the performance one, has LPMD OFF, then a deadlock +might happen when using the wlt proxy system. Basically when going into +the OFF state, polling gets disabled and there is no specific code flow +to get it enabled again after switching back to an AUTO state. + +This only affects the wlt proxy as other polling and non-polling systems +seem to be able to get themselves back up again. + +Reinitialize the polling interval when switching power profiles. + +Signed-off-by: Maciej Wieczor-Retman +--- + src/include/lpmd.h | 2 ++ + src/lpmd_proc.c | 5 ++++- + src/lpmd_state_machine.c | 8 ++++++++ + 3 files changed, 14 insertions(+), 1 deletion(-) + +diff --git a/src/include/lpmd.h b/src/include/lpmd.h +index 6319a41..447ffdd 100644 +--- a/src/include/lpmd.h ++++ b/src/include/lpmd.h +@@ -284,6 +284,8 @@ enum power_profile_daemon_mode { + PPD_INVALID + }; + ++#define DEF_POLLING_INTERVAL 100 ++ + /* lpmd_main.c */ + int in_debug_mode(void); + int do_platform_check(void); +diff --git a/src/lpmd_proc.c b/src/lpmd_proc.c +index e6d2445..450b890 100644 +--- a/src/lpmd_proc.c ++++ b/src/lpmd_proc.c +@@ -150,6 +150,9 @@ static void power_profiles_changed_cb(void) + } else { + lpmd_log_warn("Ignore unsupported power profile: %s\n", active_profile); + } ++ ++ if (lpmd_config.wlt_proxy_enable) ++ lpmd_config.data.polling_interval = DEF_POLLING_INTERVAL; + } + } + +@@ -300,7 +303,7 @@ static void* lpmd_core_main_loop(void *arg) + { + int n; + +- lpmd_config.data.polling_interval = 100; ++ lpmd_config.data.polling_interval = DEF_POLLING_INTERVAL; + + for (;;) { + +diff --git a/src/lpmd_state_machine.c b/src/lpmd_state_machine.c +index 1f40c02..9e7bcf2 100644 +--- a/src/lpmd_state_machine.c ++++ b/src/lpmd_state_machine.c +@@ -396,6 +396,14 @@ int lpmd_enter_next_state(void) + } + + idx = choose_next_state(config); ++ ++ /* ++ * After switching power profiles polling gets disabled and needs to be ++ * updated. ++ */ ++ if (config->data.polling_interval == -1 && polling_enabled && idx != DEFAULT_OFF) ++ get_config_state_interval(config, idx); ++ + /* No action needed, keep previous idx and interval */ + if (idx == STATE_NONE) + goto end; +-- +2.55.0 + diff --git a/0010-Process-itmt-read-error.patch b/0010-Process-itmt-read-error.patch new file mode 100644 index 0000000..f037aa3 --- /dev/null +++ b/0010-Process-itmt-read-error.patch @@ -0,0 +1,37 @@ +From 01285c1b192fe586e9106bdd370b8646bf474294 Mon Sep 17 00:00:00 2001 +From: Srinivas Pandruvada +Date: Fri, 10 Apr 2026 16:41:45 -0700 +Subject: [PATCH 10/56] Process itmt read error + +When fail to read PATH_ITMT_CONTROL, return error. + +Signed-off-by: Srinivas Pandruvada +--- + src/lpmd_misc.c | 7 +++++-- + 1 file changed, 5 insertions(+), 2 deletions(-) + +diff --git a/src/lpmd_misc.c b/src/lpmd_misc.c +index b993b4d..b315bf0 100644 +--- a/src/lpmd_misc.c ++++ b/src/lpmd_misc.c +@@ -28,12 +28,15 @@ static int saved_itmt = SETTING_IGNORE; + + int get_itmt(void) + { +- int val; ++ int val, ret; + + if (!has_itmt) + return -1; + +- lpmd_read_int(PATH_ITMT_CONTROL, &val, -1); ++ ret = lpmd_read_int(PATH_ITMT_CONTROL, &val, -1); ++ if (ret) ++ return -1; ++ + return val; + } + +-- +2.55.0 + diff --git a/0011-lpmd_misc-Fix-ITMT.patch b/0011-lpmd_misc-Fix-ITMT.patch new file mode 100644 index 0000000..a57cf76 --- /dev/null +++ b/0011-lpmd_misc-Fix-ITMT.patch @@ -0,0 +1,193 @@ +From fec5fa9152769152ab7bfc933fbcf05fbfaddece Mon Sep 17 00:00:00 2001 +From: Srinivas Pandruvada +Date: Fri, 10 Apr 2026 17:06:31 -0700 +Subject: [PATCH 11/56] lpmd_misc: Fix ITMT + +ITMT became broken when the enabling file was moved to the debugfs. The +data in the file also changed from printing out 0 or 1 to printing out N +or Y characters. However 0 and 1 are still accepted for writing. + +Change the file that's being accesses to the debugfs and add helpers for +the Y/N format. + +Signed-off-by: Maciej Wieczor-Retman +[Also kept the legacy /procfs control when debugfs doesn't exist] +Signed-off-by: Srinivas Pandruvada +--- + src/include/lpmd.h | 2 ++ + src/lpmd_helpers.c | 72 ++++++++++++++++++++++++++++++++++++++++++++++ + src/lpmd_misc.c | 32 ++++++++++++++++++--- + 3 files changed, 102 insertions(+), 4 deletions(-) + +diff --git a/src/include/lpmd.h b/src/include/lpmd.h +index 447ffdd..d14156f 100644 +--- a/src/include/lpmd.h ++++ b/src/include/lpmd.h +@@ -410,6 +410,8 @@ int lpmd_write_str_append(const char *name, char *str, int print_level); + int lpmd_write_int(const char *name, int val, int print_level); + int lpmd_open(const char *name, int print_level); + int lpmd_read_int(const char *name, int *val, int print_level); ++int lpmd_read_yn(const char *name, int *val, int print_level); ++int lpmd_write_yn(const char *name, int val, int print_level); + char* get_time(void); + void time_start(void); + char* time_delta(void); +diff --git a/src/lpmd_helpers.c b/src/lpmd_helpers.c +index f316912..2e27369 100644 +--- a/src/lpmd_helpers.c ++++ b/src/lpmd_helpers.c +@@ -252,6 +252,78 @@ int lpmd_read_int(const char *name, int *val, int print_level) + + } + ++int lpmd_write_yn(const char *name, int val, int print_level) ++{ ++ char str[5]; ++ int ret; ++ ++ if (!name) ++ return 0; ++ ++ ret = snprintf(str, 4, "%d", val); ++ if (ret < 0) ++ return 1; ++ ++ return _write_str (name, str, print_level, 2, "r+"); ++} ++ ++int lpmd_read_yn(const char *name, int *val, int print_level) ++{ ++ char prefix[16]; ++ FILE *filep; ++ int i, ret; ++ ++ if (!name || !val) ++ return 1; ++ ++ if (print_level >= 15) ++ return 1; ++ ++ if (print_level < 0) { ++ prefix[0] = '\0'; ++ } ++ else { ++ for (i = 0; i < print_level; i++) ++ prefix[i] = '\t'; ++ prefix[i] = '\0'; ++ } ++ ++ filep = fopen (name, "r"); ++ if (!filep) { ++ lpmd_log_error ("%sOpen %s failed\n", prefix, name); ++ return 1; ++ } ++ ++ ret = fgetc(filep); ++ if (ret == EOF) { ++ if (feof(filep)) { ++ lpmd_log_error ("%sRead %s failed due to EOF\n", prefix, name); ++ } else if (ferror(filep)) { ++ lpmd_log_error ("%sRead %s failed, error %s\n", prefix, name, strerror(errno)); ++ } ++ fclose (filep); ++ return 1; ++ } ++ ++ fclose (filep); ++ ++ if (ret == 'Y') { ++ *val = 1; ++ } else if (ret == 'N') { ++ *val = 0; ++ } else { ++ lpmd_log_error ("%sRead %s failed, read %c\n", prefix, name, ret); ++ return 1; ++ } ++ ++ if (print_level >= 0) ++ lpmd_log_debug ("%sRead \"%c\" from %s\n", prefix, *val, name); ++ ++ return 0; ++ ++} ++ ++ + /* + * lpmd_open does not require print on success + * print_level: -1: don't print on error +diff --git a/src/lpmd_misc.c b/src/lpmd_misc.c +index b315bf0..18fc9a6 100644 +--- a/src/lpmd_misc.c ++++ b/src/lpmd_misc.c +@@ -22,6 +22,7 @@ + + /* ITMT Management */ + #define PATH_ITMT_CONTROL "/proc/sys/kernel/sched_itmt_enabled" ++#define PATH_ITMT_CONTROL_DEBUGFS "/sys/kernel/debug/x86/sched_itmt_enabled" + + static int has_itmt; + static int saved_itmt = SETTING_IGNORE; +@@ -33,15 +34,30 @@ int get_itmt(void) + if (!has_itmt) + return -1; + ++ ret = lpmd_read_yn(PATH_ITMT_CONTROL_DEBUGFS, &val, -1); ++ if (!ret) ++ return val; ++ ++ lpmd_log_debug("Read ITMT debugfs failed, fallback to sysctl\n"); + ret = lpmd_read_int(PATH_ITMT_CONTROL, &val, -1); +- if (ret) +- return -1; ++ if (ret) { ++ lpmd_log_error("Read ITMT sysctl failed\n"); ++ return -1; ++ } + + return val; + } + + int itmt_init(void) + { ++ ++ if (lpmd_read_yn(PATH_ITMT_CONTROL_DEBUGFS, &saved_itmt, -1)) { ++ lpmd_log_debug("ITMT debugfs not detected\n"); ++ } else { ++ has_itmt = 1; ++ return 0; ++ } ++ + if (lpmd_read_int(PATH_ITMT_CONTROL, &saved_itmt, -1)) + lpmd_log_debug("ITMT not detected\n"); + else +@@ -52,6 +68,8 @@ int itmt_init(void) + + int process_itmt(lpmd_config_state_t *state) + { ++ int ret; ++ + if (!has_itmt) + return 0; + +@@ -60,10 +78,16 @@ int process_itmt(lpmd_config_state_t *state) + lpmd_log_debug("Ignore ITMT\n"); + return 0; + case SETTING_RESTORE: +- return lpmd_write_int(PATH_ITMT_CONTROL, saved_itmt, -1); ++ ret = lpmd_write_yn(PATH_ITMT_CONTROL_DEBUGFS, saved_itmt, -1); ++ if (ret) ++ return lpmd_write_int(PATH_ITMT_CONTROL, saved_itmt, -1); ++ return ret; + default: + lpmd_log_debug ("%s ITMT\n", state->itmt_state ? "Enable" : "Disable"); +- return lpmd_write_int(PATH_ITMT_CONTROL, state->itmt_state, -1); ++ ret = lpmd_write_yn(PATH_ITMT_CONTROL_DEBUGFS, state->itmt_state, -1); ++ if (ret) ++ return lpmd_write_int(PATH_ITMT_CONTROL, state->itmt_state, -1); ++ return ret; + } + } + +-- +2.55.0 + diff --git a/0012-make-itmt_init-to-void.patch b/0012-make-itmt_init-to-void.patch new file mode 100644 index 0000000..f4dba5e --- /dev/null +++ b/0012-make-itmt_init-to-void.patch @@ -0,0 +1,74 @@ +From 9b789e1727986df2703db152ed7aa11e6a508313 Mon Sep 17 00:00:00 2001 +From: Srinivas Pandruvada +Date: Fri, 10 Apr 2026 17:31:38 -0700 +Subject: [PATCH 12/56] make itmt_init() to void + +itmt_init() only returns 0, no use of using return value. + +Signed-off-by: Srinivas Pandruvada +--- + src/include/lpmd.h | 2 +- + src/lpmd_misc.c | 6 ++---- + src/lpmd_proc.c | 4 +--- + 3 files changed, 4 insertions(+), 8 deletions(-) + +diff --git a/src/include/lpmd.h b/src/include/lpmd.h +index d14156f..223467b 100644 +--- a/src/include/lpmd.h ++++ b/src/include/lpmd.h +@@ -335,7 +335,7 @@ int wlt_exit(void); + int wlt_update(int fd); + + /* lpmd_misc.c */ +-int itmt_init(void); ++void itmt_init(void); + int get_itmt(void); + int process_itmt(lpmd_config_state_t *state); + +diff --git a/src/lpmd_misc.c b/src/lpmd_misc.c +index 18fc9a6..77725e4 100644 +--- a/src/lpmd_misc.c ++++ b/src/lpmd_misc.c +@@ -48,22 +48,20 @@ int get_itmt(void) + return val; + } + +-int itmt_init(void) ++void itmt_init(void) + { + + if (lpmd_read_yn(PATH_ITMT_CONTROL_DEBUGFS, &saved_itmt, -1)) { + lpmd_log_debug("ITMT debugfs not detected\n"); + } else { + has_itmt = 1; +- return 0; ++ return; + } + + if (lpmd_read_int(PATH_ITMT_CONTROL, &saved_itmt, -1)) + lpmd_log_debug("ITMT not detected\n"); + else + has_itmt = 1; +- +- return 0; + } + + int process_itmt(lpmd_config_state_t *state) +diff --git a/src/lpmd_proc.c b/src/lpmd_proc.c +index 450b890..ad58c29 100644 +--- a/src/lpmd_proc.c ++++ b/src/lpmd_proc.c +@@ -408,9 +408,7 @@ int lpmd_main(void) + if (ret) + return ret; + +- ret = itmt_init(); +- if (ret) +- return ret; ++ itmt_init(); + + ret = epp_epb_init(); + if (ret) +-- +2.55.0 + diff --git a/0013-config-Fix-incorrect-cpu-numbers.patch b/0013-config-Fix-incorrect-cpu-numbers.patch new file mode 100644 index 0000000..429354c --- /dev/null +++ b/0013-config-Fix-incorrect-cpu-numbers.patch @@ -0,0 +1,46 @@ +From bb67af59b038ea965c93a1ec8b184f5ab167d2c6 Mon Sep 17 00:00:00 2001 +From: Maciej Wieczor-Retman +Date: Fri, 12 Dec 2025 13:49:25 +0100 +Subject: [PATCH 13/56] config: Fix incorrect cpu numbers + +The cpu name in the config file is described as having 16 cores while +the specific tags in the config file try to enable higher core indices +than 16. + +Correct the indices. + +Signed-off-by: Maciej Wieczor-Retman +--- + data/intel_lpmd_config_F6_M204.xml | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +diff --git a/data/intel_lpmd_config_F6_M204.xml b/data/intel_lpmd_config_F6_M204.xml +index ba5d4e4..a67fa8b 100644 +--- a/data/intel_lpmd_config_F6_M204.xml ++++ b/data/intel_lpmd_config_F6_M204.xml +@@ -146,19 +146,19 @@ for Intel Energy Optimizer (LPMD) daemon + 1 + UTIL_IDLE + 1 +- 16-19 ++ 12-15 + + + 2 + UTIL_IDLE_SUSTAIN + 2 +- 0-19 ++ 0-15 + + + 3 + UTIL_IDLE_BURSTY + 3 +- 0-19 ++ 0-15 + + + +-- +2.55.0 + diff --git a/0014-readme-Reformat-long-lines-into-markdown-readable-bl.patch b/0014-readme-Reformat-long-lines-into-markdown-readable-bl.patch new file mode 100644 index 0000000..fd42d96 --- /dev/null +++ b/0014-readme-Reformat-long-lines-into-markdown-readable-bl.patch @@ -0,0 +1,61 @@ +From 9466f9555bd83f51dac06c20141ddd76a48279f8 Mon Sep 17 00:00:00 2001 +From: Maciej Wieczor-Retman +Date: Tue, 7 Apr 2026 17:17:14 +0200 +Subject: [PATCH 14/56] readme: Reformat long lines into markdown readable + blocks + +Get the readme source to a readable format for editing. + +Signed-off-by: Maciej Wieczor-Retman +--- + README.md | 20 ++++++++++++++------ + 1 file changed, 14 insertions(+), 6 deletions(-) + +diff --git a/README.md b/README.md +index d65ae0d..e446ee2 100644 +--- a/README.md ++++ b/README.md +@@ -1,6 +1,11 @@ + # Intel Low Power Mode Daemon + +-Intel Low Power Mode Daemon (lpmd) is a Linux daemon designed to optimize active idle power. It selects the most power-efficient CPUs based on a configuration file or CPU topology. Depending on system utilization and other hints, it puts the system into Low Power Mode by activating the power-efficient CPUs and disabling the rest, and restores the system from Low Power Mode by activating all CPUs. ++Intel Low Power Mode Daemon (lpmd) is a Linux daemon designed to optimize active ++idle power. It selects the most power-efficient CPUs based on a configuration ++file or CPU topology. Depending on system utilization and other hints, it puts ++the system into Low Power Mode by activating the power-efficient CPUs and ++disabling the rest, and restores the system from Low Power Mode by activating ++all CPUs. + + ## Usage + +@@ -40,10 +45,13 @@ make + sudo make install + ``` + +-The generated artifacts are copied to respective directories under `/usr/local`. If a custom install path is preferred other than system default, make sure `--localstatedir` and `--sysconfdir` are set to the right path that the system can understand. If installed via RPM then artifacts would be under `/usr`. +- +-Example command for installation using prefix under `/opt/lpmd_install` dir with `--localstatedir` and `--sysconfdir` set to system default ++The generated artifacts are copied to respective directories under `/usr/local`. ++If a custom install path is preferred other than system default, make sure ++`--localstatedir` and `--sysconfdir` are set to the right path that the system ++can understand. If installed via RPM then artifacts would be under `/usr`. + ++Example command for installation using prefix under `/opt/lpmd_install` dir with ++`--localstatedir` and `--sysconfdir` set to system default + + ```sh + ./autogen.sh prefix=/opt/lpmd_install --localstatedir=/var --sysconfdir=/etc +@@ -87,8 +95,8 @@ Start `lpmd` using: + sudo sh tests/lpm_test_interface.sh 4 + ``` + +-Run a workload and monitor `lpmd` to ensure it puts the system in the appropriate state based on the load. +- ++Run a workload and monitor `lpmd` to ensure it puts the system in the ++appropriate state based on the load. + + ## Releases + +-- +2.55.0 + diff --git a/0015-readme-Emphasize-expectations-from-the-user.patch b/0015-readme-Emphasize-expectations-from-the-user.patch new file mode 100644 index 0000000..896824a --- /dev/null +++ b/0015-readme-Emphasize-expectations-from-the-user.patch @@ -0,0 +1,35 @@ +From 720cf64206367b0e9857e49b7a59f9df3a963261 Mon Sep 17 00:00:00 2001 +From: Maciej Wieczor-Retman +Date: Tue, 7 Apr 2026 20:31:53 +0200 +Subject: [PATCH 15/56] readme: Emphasize expectations from the user + +Make clear how to start the program to avoid confusion around the +default behavior. + +Signed-off-by: Maciej Wieczor-Retman +--- + README.md | 8 +++++++- + 1 file changed, 7 insertions(+), 1 deletion(-) + +diff --git a/README.md b/README.md +index e446ee2..fb420e8 100644 +--- a/README.md ++++ b/README.md +@@ -7,7 +7,13 @@ the system into Low Power Mode by activating the power-efficient CPUs and + disabling the rest, and restores the system from Low Power Mode by activating + all CPUs. + +-## Usage ++## Before You Start ++ ++**Please note** that the installed configuration files serve as templates of ++best practices for specific platform models and disable lpmd by default. For ++LPMD to start the user is expected to either edit the main ++"intel_lpmd_config.xml" config file or after starting the program, enable LPMD ++by using the intel_lpmd_control tool. + + Refer to the man pages for command line arguments and XML configurations: + +-- +2.55.0 + diff --git a/0016-man-Update-the-main-man-page.patch b/0016-man-Update-the-main-man-page.patch new file mode 100644 index 0000000..75e785b --- /dev/null +++ b/0016-man-Update-the-main-man-page.patch @@ -0,0 +1,90 @@ +From bae9adf43fba53c0d28e1ca0793320c713499f96 Mon Sep 17 00:00:00 2001 +From: Maciej Wieczor-Retman +Date: Fri, 27 Mar 2026 18:11:58 +0100 +Subject: [PATCH 16/56] man: Update the main man page + +Update the main man page with new informations about LPMD. Mention what +are the expectation towards the user, clear up intel_lpmd_control +section since it has it's own man page and add how to enable the system +service persistently in the examples section. + +Signed-off-by: Maciej Wieczor-Retman +--- + man/intel_lpmd.8 | 46 +++++++++++++++++++++++++--------------------- + 1 file changed, 25 insertions(+), 21 deletions(-) + +diff --git a/man/intel_lpmd.8 b/man/intel_lpmd.8 +index 1002457..8e36e73 100644 +--- a/man/intel_lpmd.8 ++++ b/man/intel_lpmd.8 +@@ -21,7 +21,7 @@ + .\" + .\" Copyright (C) 2012 Intel Corporation. All rights reserved. + .\" +-.TH intel_lpmd "8" "1 Jun 2023" ++.TH intel_lpmd "8" "08 Apr 2026" + + .SH NAME + intel_lpmd \- Intel Energy Optimizer (LPMD) Daemon +@@ -31,25 +31,24 @@ intel_lpmd \- Intel Energy Optimizer (LPMD) Daemon + + .SH DESCRIPTION + .B intel_lpmd +-is a Linux daemon used for energy optimization on Intel hybrid systems. +-This daemon uses a configuration file "intel_lpmd_config.xml". +-Based on the configuration, it will choose right set of CPUs +-to enable. For example, this daemon can monitor system utilization +-and choose a set of low power CPUs to enable and disable the rest. +-This enable disable of CPUs are done using Linux cpuset feature +-of intel power clamp driver. +- +-There is a control utility distributed along with this daemon. +-This control utility is called "intel_lpmd_control". This utility +-can be used to set different modes for this daemon. +-For example: +-intel_lpmd_control ON +- To turn on low power mode operation. +-intel_lpmd_control OFF +- To turn off low power mode operation. +-intel_lpmd_control AUTO +- To turn on low power mode operation in auto mode, which +- allows low power mode based on system utilization. ++is a Linux daemon used for energy optimization on Intel hybrid systems. This ++daemon uses a configuration file called "intel_lpmd_config.xml". The other ++installed configuration files are to be treated as best practice templates. The ++main configuration file should be edited by the user to enable LPMD and it's ++desired functionalities. Based on the configuration and system utilization LPMD ++can: ++ ++- choose the best set of CPU cores to enable for a given moment in time ++ ++- choose the best EPP (energe performance preference) and EPB (energy ++performance bias) value ++ ++- pick the best SoC power slider settings ++ ++There is a control utility distributed along with this daemon. It's called ++"intel_lpmd_control" and it can be used to change modes in the running LPMD ++instance. ++ + .SH OPTIONS + .TP + .B -h --help +@@ -88,8 +87,13 @@ Run intel_lpmd with log directed to stdout + .B intel_lpmd --systemd --dbus-enable + Run intel_lpmd as a service with logs directed to system journal + ++.TP ++.B sudo systemctl enable intel_lpmd.service --now ++Enable and run intel_lpmd as a systemd service that's persistent after system ++reboot. ++ + .SH SEE ALSO +-intel_lpmd_config.xml(5) ++intel_lpmd_config.xml(5), intel_lpmd_control(8) + + .SH AUTHOR + Written by Zhang Rui +-- +2.55.0 + diff --git a/0017-man-Update-lpmd-control-utility-man-page.patch b/0017-man-Update-lpmd-control-utility-man-page.patch new file mode 100644 index 0000000..df173f6 --- /dev/null +++ b/0017-man-Update-lpmd-control-utility-man-page.patch @@ -0,0 +1,59 @@ +From a75414281d43e2154bd9f3aa2f7b47618c437796 Mon Sep 17 00:00:00 2001 +From: Maciej Wieczor-Retman +Date: Tue, 7 Apr 2026 22:16:14 +0200 +Subject: [PATCH 17/56] man: Update lpmd control utility man page + +Cleanup the long lines and link in the config man page at the end. + +Signed-off-by: Maciej Wieczor-Retman +--- + man/intel_lpmd_control.8 | 11 +++++++---- + 1 file changed, 7 insertions(+), 4 deletions(-) + +diff --git a/man/intel_lpmd_control.8 b/man/intel_lpmd_control.8 +index 347dbde..854cd6f 100644 +--- a/man/intel_lpmd_control.8 ++++ b/man/intel_lpmd_control.8 +@@ -21,7 +21,7 @@ + .\" + .\" Copyright (C) 2025 Intel Corporation. All rights reserved. + .\" +-.TH intel_lpmd_control "8" "7 Mar 2025" ++.TH intel_lpmd_control "8" "8 Apr 2026" + + .SH NAME + intel_lpmd_control \- Control utility for the Intel Low Power Mode Daemon (LPMD) +@@ -31,7 +31,9 @@ intel_lpmd_control \- Control utility for the Intel Low Power Mode Daemon (LPMD) + + .SH DESCRIPTION + .B intel_lpmd_control +-is a command-line utility used to control the Intel Low Power Mode Daemon (LPMD). It allows users to enable, disable, or set the daemon to automatic mode based on system utilization. ++is a command-line utility used to control the Intel Low Power Mode Daemon ++(LPMD). It allows users to enable, disable, or set the daemon to automatic mode ++based on system utilization. + + .SH OPTIONS + .TP +@@ -42,7 +44,8 @@ Enables low power mode operation. + Disables low power mode operation. + .TP + .B AUTO +-Enables low power mode operation in automatic mode, allowing system utilization to determine low power state activation. ++Enables operation in automatic mode, allowing system utilization to determine ++low power state activation. + + .SH EXAMPLES + .TP +@@ -56,7 +59,7 @@ Turns off low power mode operation. + Turns on low power mode operation in automatic mode. + + .SH SEE ALSO +-.B intel_lpmd(8) ++.B intel_lpmd_config.xml(5), intel_lpmd(8) + + .SH AUTHOR + Written by Deepak Sundar +\ No newline at end of file +-- +2.55.0 + diff --git a/0018-man-Generic-updates-to-the-config-man-page.patch b/0018-man-Generic-updates-to-the-config-man-page.patch new file mode 100644 index 0000000..a815cdd --- /dev/null +++ b/0018-man-Generic-updates-to-the-config-man-page.patch @@ -0,0 +1,137 @@ +From f851bd0647ce9892635bd31ca30a6babf3a7efb6 Mon Sep 17 00:00:00 2001 +From: Maciej Wieczor-Retman +Date: Wed, 8 Apr 2026 19:45:00 +0200 +Subject: [PATCH 18/56] man: Generic updates to the config man page + +Cleanup some topics that expanded since they were written. Make general +cleanups and small corrections to typos or style. + +Signed-off-by: Maciej Wieczor-Retman +[Change MTL to Lunar Lake] +Signed-off-by: Srinivas Pandruvada +--- + man/intel_lpmd_config.xml.5 | 53 +++++++++++++++++++------------------ + 1 file changed, 27 insertions(+), 26 deletions(-) + +diff --git a/man/intel_lpmd_config.xml.5 b/man/intel_lpmd_config.xml.5 +index 2792665..507939a 100644 +--- a/man/intel_lpmd_config.xml.5 ++++ b/man/intel_lpmd_config.xml.5 +@@ -21,7 +21,7 @@ + .\" + .\" Copyright (C) 2012 Intel Corporation. All rights reserved. + .\" +-.TH intel_lpmd_config.xml "5" "1 Jun 2023" ++.TH intel_lpmd_config.xml "5" "8 Apr 2026" + + .SH NAME + intel_lpmd_config.xml \- Configuration file for intel_lpmd +@@ -30,18 +30,22 @@ $(TDCONFDIR)/etc/intel_lpmd/intel_lpmd_config.xml + + .SH DESCRIPTION + .B intel_lpmd_config.xml +-is a configuration file for the Intel Low Power Mode Daemon. +-It is used to describe the lp_mode_cpus to use in Low Power Mode, +-as well as the way to restrict work to those CPUs. It also describes +-if and how the HFI monitor and utilization monitor works. The location +-of this file depends on the configuration option used during build time. ++is a configuration file for the Intel Low Power Mode Daemon. It's used to ++describe states and rules of switching between the states. These states are ++custom, user defined sets of parameters that the platform should use for optimal ++performance and energy saving. The rules of switching refer to what system ++information dictates whether a change of state is needed or not. It can be ++either information from a hardware source or software calculated if the hardware ++features are not supported. ++ + .PP + .B lp_mode_cpus +-is a set of active CPUs when system is in Low Power Mode. +-This usually equals a group of most power efficient CPUs on a platform to +-achieve best power saving. When not specified, intel_lpmd tool can detect this +-automatically. E.g. it uses an E-core Module on Intel Alderlake platform, and +-it uses the Low Power E-cores on SoC Die on Intel Meteorlake platform. ++is a set of active CPUs when system is in Low Power Mode. This usually equals a ++group of most power efficient CPUs on a platform to achieve best power saving. ++When not specified, intel_lpmd tool can detect this automatically. E.g. it uses ++L-cores on Intel PantherLake platform, the E-core Module on Intel Alderlake ++platform, and it uses the Low Power E-cores on SoC Die on Intel Meteorlake ++platform. + .PP + .B Mode + specifies the way to migrate the tasks to the lp_mode_cpus. +@@ -56,8 +60,8 @@ lp_mode_cpus only. + Mode 2: Force idle injection to the non-lp_mode_cpus and leverage the + scheduler to schedule the other tasks to the lp_mode_cpus. + .PP +-.B PerformanceDef +-specifies the default behavior when power setting is set to Performance. ++.B PerformanceDef / BalancedDef / PowersaverDef ++specifies the default behavior for a given power profile. + .IP \(bu 2 + -1 : Never enter Low Power Mode. + .IP \(bu 2 +@@ -65,12 +69,6 @@ specifies the default behavior when power setting is set to Performance. + .IP \(bu 2 + 1 : Always stay in Low Power Mode. + .PP +-.B BalancedDef +-specifies the default behavior when power setting is set to Balanced. +-.PP +-.B PowersaverDef +-specifies the default behavior when power setting is set to Power saver. +-.PP + .B HfiLpmEnable + specifies if the HFI monitor can capture the HFI hints for Low Power Mode. + .PP +@@ -127,16 +125,18 @@ Setting to 0 or leaving this empty disables this hysteresis algorithm. + Avoid changing scheduler ITMT flag. This means that during transition to + low power mode, ITMT flag is not changed. This reduces latency during + switching. This flag is not used when configuration uses "State" based +-configuration, where this flag can be defined per state. ++configuration, where this flag can be defined per state. ITMT is only relevant ++for platforms before Lunar Lake and the debugfs file is not present on later ++platforms. + .PP + .B States + Allows one to define per platform low power states. Each state defines + has an entry condition and set of parameters to use. + + .SH State Definition +-There can be multiple State configuration can be present. Each +-configuration is valid for a platform. A State header defines parameters, +-which are used to match a platform. ++There can be multiple state configurations present. Each configuration is valid ++for a platform. A state header defines parameters, which are used to match a ++platform. + .B CPUFamily + CPU generation to match. + .PP +@@ -160,7 +160,7 @@ A name for the state. + .PP + .B EntrySystemLoadThres + System Entry load threshold in percent. System utilization is different +-based on the number of CPUs are active in a configuration. This value ++based on the number of active CPUs in a configuration. This value + is calculated from /proc/stat sysfs. To enter into this state, the + system utilization must be less or equal to this value. + .PP +@@ -186,13 +186,14 @@ EPP to apply for this state. -1 to ignore. + EPB to apply for this state. -1 to ignore. + .PP + .B ITMTState +-Set the state of ITMT flag. -1 to ignore. ++Set the state of ITMT flag. -1 to ignore. ITMT is only relevant for platforms ++before MTL and the debugfs file is not present on later platforms. + .PP + .B IRQMigrate + Migrate IRQs to the active CPUs in this state. -1 to ignore. + .PP + .B MinPollInterval +-Minimum polling interval in milli seconds. ++Minimum polling interval in milliseconds. + .PP + .B MaxPollInterval + Maximum polling interval in milli seconds. This is optional, +-- +2.55.0 + diff --git a/0019-man-Move-unused-config-options-to-the-unused-section.patch b/0019-man-Move-unused-config-options-to-the-unused-section.patch new file mode 100644 index 0000000..26a3ad8 --- /dev/null +++ b/0019-man-Move-unused-config-options-to-the-unused-section.patch @@ -0,0 +1,177 @@ +From f7bb8c57d709df3faaec3edbda3db7c0c79006a8 Mon Sep 17 00:00:00 2001 +From: Maciej Wieczor-Retman +Date: Wed, 8 Apr 2026 20:08:33 +0200 +Subject: [PATCH 19/56] man: Move unused config options to the unused section + +Some options are not currently doing anything. Move them out of the +proper part of the man page to avoid confusing users. + +Signed-off-by: Maciej Wieczor-Retman +--- + man/intel_lpmd_config.xml.5 | 108 +++++++++++------------------------- + 1 file changed, 32 insertions(+), 76 deletions(-) + +diff --git a/man/intel_lpmd_config.xml.5 b/man/intel_lpmd_config.xml.5 +index 507939a..e6bea7c 100644 +--- a/man/intel_lpmd_config.xml.5 ++++ b/man/intel_lpmd_config.xml.5 +@@ -86,7 +86,6 @@ specifies the system utilization threshold for entering Low Power Mode. + The system workload is considered to fit the lp_mode_cpus capacity when system + utilization is under this threshold. + Setting to 0 or leaving this empty disables the utilization monitor. +- + .PP + .B util_exit_threshold + specifies the CPU utilization threshold for exiting Low Power Mode. +@@ -94,33 +93,6 @@ The system workload is considered to not fit the lp_mode_cpus capacity when + the utilization of the busiest lp_mode_cpus is above this threshold. + Setting to 0 or leaving this empty disables the utilization monitor. + .PP +-.B EntryDelayMS +-specifies the sample interval used by the utilization Monitor when system +-wants to enter Low Power Mode based on system utilization. +-Setting to 0 or leaving this empty will cause the utilization Monitor to use +-the default interval, 1000 milli seconds. +-.PP +-.B ExitDelayMS +-specifies the sample interval used by the utilization Monitor when system +-wants to exit Low Power Mode based on CPU utilization. +-Setting to 0 or leaving this empty will cause the utilization Monitor to use +-the adaptive value. The adaptive interval is based on CPU utilization. +-The busier the CPU is, the shorter interval the utilization monitor uses. +-.PP +-.B EntryHystMS +-specifies a hysteresis threshold when system is in Low Power Mode. +-If set, when the previous average time stayed in Low Power Mode is lower than +-this value, the current enter Low Power Mode request will be ignored because +-it is expected that the system will exit Low Power Mode soon. +-Setting to 0 or leaving this empty disables this hysteresis algorithm. +-.PP +-.B ExitHystMS +-specifies a hysteresis threshold when system is not in Low Power Mode. +-If set, when the previous average time stayed out of Low-Power-Mode is lower +-than this value, the current exit Low Power Mode request will be ignored +-because it is expected that the system will enter Low Power Mode soon. +-Setting to 0 or leaving this empty disables this hysteresis algorithm. +-.PP + .B IgnoreITMT + Avoid changing scheduler ITMT flag. This means that during transition to + low power mode, ITMT flag is not changed. This reduces latency during +@@ -272,30 +244,6 @@ The configuration file format conforms to XML specifications. + --> + Example threshold + +- +- Example delay +- +- +- Example delay +- +- +- Example hyst +- +- +- Example hyst +- + ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ 0 ++ ++ ++ -1 ++ ++ ++ -1 ++ ++ ++ -1 ++ ++ ++ 0 ++ ++ ++ 1 ++ ++ ++ 1024 ++ ++ ++ 0 ++ ++ ++ 0 ++ ++ ++ 10 ++ ++ ++ 95 ++ ++ ++ 0 ++ ++ ++ 0 ++ ++ ++ 0 ++ ++ ++ 0 ++ ++ ++ 0 ++ ++ ++ ++ 6 ++ 181 ++ * ++ ++ 1 ++ UTIL_BL ++ 3 ++ 128 ++ 6 ++ 1 ++ ALL ++ ALL ++ ++ ++ 2 ++ UTIL_IDLE_SUSTAIN ++ 2 ++ 64 ++ 4 ++ * ++ ++ ++ 3 ++ UTIL_IDLE_BURSTY ++ 3 ++ 128 ++ 6 ++ * ++ ++ ++ +diff --git a/src/lpmd_cpu.c b/src/lpmd_cpu.c +index e57b672..4eb1ab6 100644 +--- a/src/lpmd_cpu.c ++++ b/src/lpmd_cpu.c +@@ -40,6 +40,7 @@ static struct cpu_model_entry id_table[] = { + { 6, 0xbf }, // Raptorlake S + { 6, 0xaa }, // Meteorlake + { 6, 0xac }, // Meteorlake ++ { 6, 0xb5 }, // ArrowLake + { 6, 0xbd }, // Lunarlake + { 6, 0xcc }, // Pantherlake + { 0, 0 } // Last Invalid entry +-- +2.55.0 + diff --git a/0036-lpmd_config-Skip-platform-check-if-a-matching-config.patch b/0036-lpmd_config-Skip-platform-check-if-a-matching-config.patch new file mode 100644 index 0000000..60ec48c --- /dev/null +++ b/0036-lpmd_config-Skip-platform-check-if-a-matching-config.patch @@ -0,0 +1,230 @@ +From 3d269dadacc56e4db587dad6f4299ad72c247fee Mon Sep 17 00:00:00 2001 +From: Maciej Wieczor-Retman +Date: Wed, 17 Dec 2025 20:24:10 +0100 +Subject: [PATCH 36/56] lpmd_config: Skip platform check if a matching config + file exists + +A platform that's not added to the model list in the source code is +discarded early when launching the program. + +For easier scaling it's beneficial to accept platforms that have a +matching configuration file in the appropriate directory. + +Skip matching the platform model to the source code defined list of +supported models if a matching config file exists. + +Signed-off-by: Maciej Wieczor-Retman +[srinivas: Fix coverity error for uninitialized file_name] +Signed-off-by: Srinivas Pandruvada +--- + src/include/lpmd.h | 4 ++++ + src/lpmd_config.c | 60 ++++++++++++++++++++++++++++++++++++---------- + src/lpmd_cpu.c | 27 +++++++++++++++------ + 3 files changed, 71 insertions(+), 20 deletions(-) + +diff --git a/src/include/lpmd.h b/src/include/lpmd.h +index f13fcb8..cf9a4fd 100644 +--- a/src/include/lpmd.h ++++ b/src/include/lpmd.h +@@ -105,6 +105,7 @@ typedef struct { + } message_capsul_t; + + #define MAX_STR_LENGTH 256 ++#define MAX_FILE_NAME_PATH 128 + #define MAX_CONFIG_STATES 10 + #define MAX_STATE_NAME 32 + #define MAX_CONFIG_LEN 64 +@@ -227,6 +228,7 @@ typedef struct { + char cpu_config[MAX_CONFIG_LEN]; + int config_state_count; + int tdp; ++ char file_name[MAX_FILE_NAME_PATH]; + + int balance_slider_def_ac; + int slider_offset_def_ac; +@@ -319,6 +321,7 @@ void update_reason(int reason); + int intel_dbus_server_init(gboolean (*exit_handler)(void)); + + /* lpmd_config.c */ ++int match_config_file(int family, int model, int tdp, char *save_file_name); + int lpmd_get_config(lpmd_config_t *lpmd_config); + + /* lpmd_state_machine.c */ +@@ -372,6 +375,7 @@ int check_cpu_hotplug(void); + int detect_supported_platform(lpmd_config_t *lpmd_config); + int detect_cpu_topo(lpmd_config_t *lpmd_config); + int detect_lpm_cpus(char *cmd_cpus); ++int get_tdp(void); + + int is_cpu_ecore(int cpu); + int is_cpu_pcore(int cpu); +diff --git a/src/lpmd_config.c b/src/lpmd_config.c +index b459651..f9179cb 100644 +--- a/src/lpmd_config.c ++++ b/src/lpmd_config.c +@@ -23,7 +23,6 @@ + #include + + #define CONFIG_FILE_NAME "intel_lpmd_config.xml" +-#define MAX_FILE_NAME_PATH 128 + + static void save_string_or_zero(char * tmp_value, char * dst_string, int dest_size) + { +@@ -428,31 +427,64 @@ err: xmlFree (tmp_value); + return LPMD_SUCCESS; + } + +-int lpmd_get_config(lpmd_config_t *lpmd_config) ++int match_config_file(int family, int model, int tdp, char *save_file_name) + { + char file_name[MAX_FILE_NAME_PATH]; ++ struct stat s; ++ int ret; ++ ++ snprintf(file_name, MAX_FILE_NAME_PATH, ++ "%s/intel_lpmd_config_F%d_M%d_T%d.xml", TDCONFDIR, family, ++ model, tdp); ++ ++ lpmd_log_msg ("Looking for config file %s\n", file_name); ++ ret = stat (file_name, &s); ++ if (!ret) { ++ strncpy(save_file_name, file_name, MAX_FILE_NAME_PATH); ++ return ret; ++ } ++ ++ snprintf(file_name, MAX_FILE_NAME_PATH, ++ "%s/intel_lpmd_config_F%d_M%d.xml", TDCONFDIR, family, model); ++ ++ lpmd_log_msg("Looking for config file %s\n", file_name); ++ ++ ret = stat(file_name, &s); ++ if (!ret) { ++ strncpy(save_file_name, file_name, MAX_FILE_NAME_PATH); ++ return ret; ++ } ++ ++ return ret; ++} ++ ++int lpmd_get_config(lpmd_config_t *lpmd_config) ++{ ++ char file_name_str[MAX_FILE_NAME_PATH]; + xmlNode *root_element; + xmlNode *cur_node; ++ char *file_name; + struct stat s; + xmlDoc *doc; + + if (!lpmd_config) + return LPMD_ERROR; + +- +- snprintf(file_name, MAX_FILE_NAME_PATH, "%s/intel_lpmd_config_F%d_M%d_T%d.xml", +- TDCONFDIR, lpmd_config->cpu_family, lpmd_config->cpu_model, lpmd_config->tdp); +- +- lpmd_log_msg ("Looking for config file %s\n", file_name); +- if (!stat (file_name, &s)) ++ /* ++ * If a config file was already found skip looking for it the second ++ * time. ++ */ ++ if (strcmp(lpmd_config->file_name, "")) { ++ file_name = lpmd_config->file_name; + goto process_xml; ++ } + +- snprintf(file_name, MAX_FILE_NAME_PATH, "%s/intel_lpmd_config_F%d_M%d.xml", +- TDCONFDIR, lpmd_config->cpu_family, lpmd_config->cpu_model); +- lpmd_log_msg ("Looking for config file %s\n", file_name); +- if (!stat (file_name, &s)) +- goto process_xml; ++ file_name = file_name_str; + ++ /* ++ * If a model specific config file was not found use the generic ++ * config file. ++ */ + snprintf (file_name, MAX_FILE_NAME_PATH, "%s/%s", TDCONFDIR, CONFIG_FILE_NAME); + + lpmd_log_msg ("Reading configuration file %s\n", file_name); +@@ -462,6 +494,8 @@ int lpmd_get_config(lpmd_config_t *lpmd_config) + return LPMD_ERROR; + } + ++ strncpy(lpmd_config->file_name, file_name, MAX_FILE_NAME_PATH - 1); ++ + process_xml: + doc = xmlReadFile (file_name, NULL, 0); + if (doc == NULL) { +diff --git a/src/lpmd_cpu.c b/src/lpmd_cpu.c +index 4eb1ab6..bb3ecd3 100644 +--- a/src/lpmd_cpu.c ++++ b/src/lpmd_cpu.c +@@ -49,7 +49,8 @@ static struct cpu_model_entry id_table[] = { + int detect_supported_platform(lpmd_config_t *lpmd_config) + { + unsigned int eax, ebx, ecx, edx; +- unsigned int max_level, family, model, stepping; ++ unsigned int max_level, family, model, stepping, tdp; ++ char file_name[MAX_FILE_NAME_PATH] = "\0"; + int val; + + cpuid(0, eax, ebx, ecx, edx); +@@ -69,9 +70,16 @@ int detect_supported_platform(lpmd_config_t *lpmd_config) + if (family == 6) + model += ((eax >> 16) & 0xf) << 4; + ++ tdp = get_tdp(); ++ + lpmd_log_info("%u CPUID levels; family:model:stepping 0x%x:%x:%x (%u:%u:%u)\n", + max_level, family, model, stepping, family, model, stepping); + ++ if (!match_config_file(family, model, tdp, file_name)) { ++ lpmd_log_info("Found a config file matching the platform model - skipping platform check\n"); ++ goto end; ++ } ++ + if (!do_platform_check()) { + lpmd_log_info("Ignore platform check\n"); + goto end; +@@ -125,6 +133,11 @@ int detect_supported_platform(lpmd_config_t *lpmd_config) + end: + lpmd_config->cpu_family = family; + lpmd_config->cpu_model = model; ++ lpmd_config->tdp = tdp; ++ if (file_name[0] != '\0') ++ strncpy(lpmd_config->file_name, file_name, MAX_FILE_NAME_PATH); ++ else ++ lpmd_config->file_name[0] = '\0'; + + return 0; + } +@@ -206,7 +219,7 @@ int is_cpu_lcore(int cpu) + } + + #define PATH_RAPL "/sys/class/powercap" +-static int get_tdp(void) ++int get_tdp(void) + { + FILE *filep; + DIR *dir; +@@ -368,11 +381,11 @@ int detect_cpu_topo(lpmd_config_t *lpmd_config) + } + } + +- tdp = get_tdp(); +- lpmd_log_info("Detected %d Pcores, %d Ecores, %d Lcores, TDP %dW\n", pcores, ecores, lcores, tdp); +- ret = snprintf(lpmd_config->cpu_config, MAX_CONFIG_LEN - 1, " %dP%dE%dL-%dW ", pcores, ecores, lcores, tdp); +- +- lpmd_config->tdp = tdp; ++ lpmd_log_info("Detected %d Pcores, %d Ecores, %d Lcores, TDP %dW\n", ++ pcores, ecores, lcores, lpmd_config->tdp); ++ ret = snprintf(lpmd_config->cpu_config, MAX_CONFIG_LEN - 1, ++ " %dP%dE%dL-%dW ", pcores, ecores, lcores, ++ lpmd_config->tdp); + + return 0; + } +-- +2.55.0 + diff --git a/0037-config-Nova-Lake-enabling.patch b/0037-config-Nova-Lake-enabling.patch new file mode 100644 index 0000000..bf55dac --- /dev/null +++ b/0037-config-Nova-Lake-enabling.patch @@ -0,0 +1,189 @@ +From 7789bdfed92fe2eae62bb50a7fcdc33d43300c55 Mon Sep 17 00:00:00 2001 +From: Maciej Wieczor-Retman +Date: Thu, 29 Jan 2026 21:08:19 +0100 +Subject: [PATCH 37/56] config: Nova Lake enabling + +Add the Nova Lake config file. With the recent addition of config file +based model matching, installing this file is enough to enable LPMD on +the Nova Lake platform. + +Signed-off-by: Maciej Wieczor-Retman +--- + data/intel_lpmd_config_F18_M1.xml | 165 ++++++++++++++++++++++++++++++ + 1 file changed, 165 insertions(+) + create mode 100644 data/intel_lpmd_config_F18_M1.xml + +diff --git a/data/intel_lpmd_config_F18_M1.xml b/data/intel_lpmd_config_F18_M1.xml +new file mode 100644 +index 0000000..9772ec3 +--- /dev/null ++++ b/data/intel_lpmd_config_F18_M1.xml +@@ -0,0 +1,165 @@ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ -1 ++ ++ ++ -1 ++ ++ ++ -1 ++ ++ ++ 0 ++ ++ ++ 1 ++ ++ ++ 0 ++ ++ ++ 15 ++ ++ ++ 0 ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ 0 ++ ++ ++ 1 ++ 3 ++ 0 ++ 3 ++ ++ ++ 18 ++ 1 ++ * ++ ++ 1 ++ UTIL_IDLE ++ 1 ++ ALL ++ ++ ++ 2 ++ UTIL_IDLE_SUSTAIN ++ 2 ++ * ++ ++ ++ 3 ++ UTIL_IDLE_BURSTY ++ 3 ++ * ++ ++ ++ ++ +-- +2.55.0 + diff --git a/0038-lpmd_cpu-Add-wildcard-for-active_cpus-and-cpu-types.patch b/0038-lpmd_cpu-Add-wildcard-for-active_cpus-and-cpu-types.patch new file mode 100644 index 0000000..84a3d4f --- /dev/null +++ b/0038-lpmd_cpu-Add-wildcard-for-active_cpus-and-cpu-types.patch @@ -0,0 +1,72 @@ +From 77a697a502db74ccd3ac727f6729167602451664 Mon Sep 17 00:00:00 2001 +From: Maciej Wieczor-Retman +Date: Tue, 10 Feb 2026 13:52:46 +0100 +Subject: [PATCH 38/56] lpmd_cpu: Add wildcard * for active_cpus and cpu types + +Allow using the star "*" wildcard operator in the configuration of which +cpu cores should be used. It's use is synonymous to the "ALL" / "all" +keywords. + +Signed-off-by: Maciej Wieczor-Retman +--- + src/include/lpmd.h | 1 + + src/lpmd_config.c | 2 +- + src/lpmd_cpumask.c | 2 +- + src/lpmd_state_machine.c | 3 ++- + 4 files changed, 5 insertions(+), 3 deletions(-) + +diff --git a/src/include/lpmd.h b/src/include/lpmd.h +index cf9a4fd..456e65e 100644 +--- a/src/include/lpmd.h ++++ b/src/include/lpmd.h +@@ -323,6 +323,7 @@ int intel_dbus_server_init(gboolean (*exit_handler)(void)); + /* lpmd_config.c */ + int match_config_file(int family, int model, int tdp, char *save_file_name); + int lpmd_get_config(lpmd_config_t *lpmd_config); ++int is_wildcard(char *str); + + /* lpmd_state_machine.c */ + int update_lpmd_state(int state); +diff --git a/src/lpmd_config.c b/src/lpmd_config.c +index f9179cb..8527e94 100644 +--- a/src/lpmd_config.c ++++ b/src/lpmd_config.c +@@ -114,7 +114,7 @@ static void lpmd_parse_state(xmlDoc *doc, xmlNode *a_node, lpmd_config_t *config + } + } + +-static int is_wildcard(char *str) ++int is_wildcard(char *str) + { + if (!str) + return 1; +diff --git a/src/lpmd_cpumask.c b/src/lpmd_cpumask.c +index 9d41931..6b9b6a8 100644 +--- a/src/lpmd_cpumask.c ++++ b/src/lpmd_cpumask.c +@@ -228,7 +228,7 @@ int cpumask_init_cpus_type(char * buf, enum cpumask_idx idx, unsigned char **cma + int nr_cpus = 0; + char * end; + +- if (!strncmp(buf, "ALL", strlen("ALL")) || !strncmp(buf, "all", strlen("all"))) ++ if (!strncmp(buf, "ALL", strlen("ALL")) || !strncmp(buf, "all", strlen("all")) || is_wildcard(buf)) + count = count_cpu_type_cores(cmasks[type]); + else { + errno = 0; +diff --git a/src/lpmd_state_machine.c b/src/lpmd_state_machine.c +index 593de9e..677dc0d 100644 +--- a/src/lpmd_state_machine.c ++++ b/src/lpmd_state_machine.c +@@ -638,7 +638,8 @@ static int build_state_cpumask_activecpus(lpmd_config_state_t *state) + return -2; + + if (!strncmp(state->active_cpus, "all", sizeof("all")) || +- !strncmp(state->active_cpus, "ALL", sizeof("ALL"))) { ++ !strncmp(state->active_cpus, "ALL", sizeof("ALL")) || ++ is_wildcard(state->active_cpus)) { + state->cpumask_idx = CPUMASK_ONLINE; + return 0; + } +-- +2.55.0 + diff --git a/0039-data-Fix-active-cpu-spelling.patch b/0039-data-Fix-active-cpu-spelling.patch new file mode 100644 index 0000000..2dab443 --- /dev/null +++ b/0039-data-Fix-active-cpu-spelling.patch @@ -0,0 +1,57 @@ +From 10044d978632ceb21616bfe2c8824dcbbec0b8b9 Mon Sep 17 00:00:00 2001 +From: Maciej Wieczor-Retman +Date: Tue, 10 Feb 2026 14:15:16 +0100 +Subject: [PATCH 39/56] data: Fix active cpu spelling + +Lowercase 'cpus' were causing this tag to not get loaded properly when +constructing cpu bitmasks. + +Signed-off-by: Maciej Wieczor-Retman +--- + data/intel_lpmd_config_F18_M1.xml | 4 ++-- + data/intel_lpmd_config_F6_M204.xml | 4 ++-- + 2 files changed, 4 insertions(+), 4 deletions(-) + +diff --git a/data/intel_lpmd_config_F18_M1.xml b/data/intel_lpmd_config_F18_M1.xml +index 9772ec3..732b107 100644 +--- a/data/intel_lpmd_config_F18_M1.xml ++++ b/data/intel_lpmd_config_F18_M1.xml +@@ -152,13 +152,13 @@ for Intel Energy Optimizer (LPMD) daemon + 2 + UTIL_IDLE_SUSTAIN + 2 +- * ++ * + + + 3 + UTIL_IDLE_BURSTY + 3 +- * ++ * + + + +diff --git a/data/intel_lpmd_config_F6_M204.xml b/data/intel_lpmd_config_F6_M204.xml +index 9029f13..83a0fb2 100644 +--- a/data/intel_lpmd_config_F6_M204.xml ++++ b/data/intel_lpmd_config_F6_M204.xml +@@ -152,13 +152,13 @@ for Intel Energy Optimizer (LPMD) daemon + 2 + UTIL_IDLE_SUSTAIN + 2 +- * ++ * + + + 3 + UTIL_IDLE_BURSTY + 3 +- * ++ * + + + +-- +2.55.0 + diff --git a/0040-Enable-platform-agnostic-config-fallback-for-unknown.patch b/0040-Enable-platform-agnostic-config-fallback-for-unknown.patch new file mode 100644 index 0000000..076899f --- /dev/null +++ b/0040-Enable-platform-agnostic-config-fallback-for-unknown.patch @@ -0,0 +1,43 @@ +From 1eea93c6f96ca435161101f685345383ea6d8f18 Mon Sep 17 00:00:00 2001 +From: Mohsin Shariff +Date: Fri, 27 Feb 2026 20:25:31 +0530 +Subject: [PATCH 40/56] Enable platform-agnostic config fallback for unknown + platforms + +- Remove hard platform whitelist check failure (return -1) +- Unknown platforms now continue to config loading instead of exiting +- Allows fallback to generic intel_lpmd_config.xml for unsupported models +- Improves daemon robustness for new/preview platforms like M213 +- Updated log messages to indicate fallback attempt + +[srinivas: Fixed log message and sign-off of the author] +Signed-off-by: Mohsin Shariff +Signed-off-by: Srinivas Pandruvada +--- + src/lpmd_cpu.c | 5 ++--- + 1 file changed, 2 insertions(+), 3 deletions(-) + +diff --git a/src/lpmd_cpu.c b/src/lpmd_cpu.c +index bb3ecd3..9080584 100644 +--- a/src/lpmd_cpu.c ++++ b/src/lpmd_cpu.c +@@ -120,14 +120,13 @@ int detect_supported_platform(lpmd_config_t *lpmd_config) + + /* Unsupported model */ + if (!id_table[val].family) { +- lpmd_log_info("Platform not supported yet.\n"); +- lpmd_log_debug("Supported platforms:\n"); ++ lpmd_log_info("Platform model %d not in supported platform list. Attempt fallback to generic config.\n", model); ++ lpmd_log_debug("Supported platforms (with optimized configs):\n"); + val = 0; + while (id_table[val].family) { + lpmd_log_debug("\tfamily %d model %d\n", id_table[val].family, id_table[val].model); + val++; + } +- return -1; + } + + end: +-- +2.55.0 + diff --git a/0041-docs-Clarify-slider-config.patch b/0041-docs-Clarify-slider-config.patch new file mode 100644 index 0000000..b09bc58 --- /dev/null +++ b/0041-docs-Clarify-slider-config.patch @@ -0,0 +1,38 @@ +From 38cb4c6052fd54aae28fba05e623537fba2096c2 Mon Sep 17 00:00:00 2001 +From: Mohsin Shariff +Date: Mon, 2 Mar 2026 11:03:54 +0530 +Subject: [PATCH 41/56] docs: Clarify slider config + +docs: Clarify slider config is for Panther Lake and later platforms + +[srinivas: Changed PTL to Panther Lake and sign-off of the author] +Signed-off-by: Mohsin Shariff +Signed-off-by: Srinivas Pandruvada +--- + data/intel_lpmd_config.xml | 11 +++++++++++ + 1 file changed, 11 insertions(+) + +diff --git a/data/intel_lpmd_config.xml b/data/intel_lpmd_config.xml +index 2ef361a..f9e8876 100644 +--- a/data/intel_lpmd_config.xml ++++ b/data/intel_lpmd_config.xml +@@ -102,5 +102,16 @@ for Intel Energy Optimizer (LPMD) daemon + --> + 0 + ++ ++ 1 ++ 3 ++ 0 ++ 3 ++ + + +-- +2.55.0 + diff --git a/0042-Validate-slider-balance-and-offset-configuration.patch b/0042-Validate-slider-balance-and-offset-configuration.patch new file mode 100644 index 0000000..16c7c95 --- /dev/null +++ b/0042-Validate-slider-balance-and-offset-configuration.patch @@ -0,0 +1,244 @@ +From 4935e3fd8a766cd9924ec03275d3b5dc652df038 Mon Sep 17 00:00:00 2001 +From: Mohsin Shariff +Date: Mon, 13 Apr 2026 13:53:25 -0700 +Subject: [PATCH 42/56] Validate slider balance and offset configuration + +Make sure that slider balance and offset values are configured under limits. +Slider value can be set from 1-5 and offset can be from 0-6. + +[srinivas: Squashed all related commits and added commit log] +Signed-off-by: Mohsin Shariff +Signed-off-by: Srinivas Pandruvada +--- + src/include/lpmd.h | 15 ++++++ + src/lpmd_config.c | 124 ++++++++++++++++++++++++++++++++++++++------- + 2 files changed, 121 insertions(+), 18 deletions(-) + +diff --git a/src/include/lpmd.h b/src/include/lpmd.h +index 456e65e..8c7193d 100644 +--- a/src/include/lpmd.h ++++ b/src/include/lpmd.h +@@ -86,6 +86,19 @@ static int dummy_printf(const char *__restrict __format, ...) + #define LPMD_ERROR -1 + #define LPMD_FATAL_ERROR -2 + ++/* Slider parameter types for explicit type-safe validation */ ++enum slider_param_type { ++ SLIDER_TYPE_BALANCE, ++ SLIDER_TYPE_OFFSET, ++ SLIDER_TYPE_MAX ++}; ++ ++// Slider validation defines ++#define SLIDER_BALANCE_MIN 1 ++#define SLIDER_BALANCE_MAX 5 ++#define SLIDER_OFFSET_MIN 0 ++#define SLIDER_OFFSET_MAX 6 ++ + // Dbus related + /* Well-known name for this service. */ + #define INTEL_LPMD_SERVICE_NAME "org.freedesktop.intel_lpmd" +@@ -180,6 +193,7 @@ typedef struct { + int itmt_state; + int irq_migrate; + ++ /* balance: 1-5, offset: 0-6, or -1 to disable */ + int balance_slider_ac; + int slider_offset_ac; + int balance_slider_dc; +@@ -230,6 +244,7 @@ typedef struct { + int tdp; + char file_name[MAX_FILE_NAME_PATH]; + ++ /* balance: 1-5, offset: 0-6, or -1 to disable */ + int balance_slider_def_ac; + int slider_offset_def_ac; + int balance_slider_def_dc; +diff --git a/src/lpmd_config.c b/src/lpmd_config.c +index 8527e94..cfeb910 100644 +--- a/src/lpmd_config.c ++++ b/src/lpmd_config.c +@@ -24,6 +24,82 @@ + + #define CONFIG_FILE_NAME "intel_lpmd_config.xml" + ++static int validate_slider_value(int value, const char *param_name, int state_id, ++ int min_val, int max_val) ++{ ++ /* -1 is a special value meaning "ignore/disable" */ ++ if (value == -1) ++ return LPMD_SUCCESS; /* Valid */ ++ ++ if (value < min_val || value > max_val) { ++ if (state_id >= 0) { ++ /* State-level parameter */ ++ lpmd_log_error("Invalid %s value: %d in state ID %d. " ++ "Valid range: %d-%d or %d to disable\n", ++ param_name, value, state_id, ++ min_val, max_val, -1); ++ } else { ++ /* Global/default parameter */ ++ lpmd_log_error("Invalid %s (global default) value: %d. " ++ "Valid range: %d-%d or %d to disable\n", ++ param_name, value, ++ min_val, max_val, -1); ++ } ++ return LPMD_ERROR; /* Invalid */ ++ } ++ ++ return LPMD_SUCCESS; /* Valid */ ++} ++ ++/* ++ * Helper function to parse and validate slider parameters. ++ * Handles both parsing (with error checking) and range validation in one call. ++ * Returns 0 on success, LPMD_ERROR on failure (fail-fast approach). ++ */ ++static int read_slider_and_validate(int *dest_ptr, const char *src_value, ++ const char *param_name, int state_id, ++ enum slider_param_type type) ++{ ++ char *endptr; ++ int value; ++ ++ errno = 0; ++ value = strtol(src_value, &endptr, 10); ++ ++ /* Check for parsing errors */ ++ if (errno == ERANGE || endptr == src_value) { ++ if (state_id >= 0) { ++ lpmd_log_error("Failed to parse %s value: '%s' is not a valid integer in state ID %d\n", ++ param_name, src_value, state_id); ++ } else { ++ lpmd_log_error("Failed to parse %s value: '%s' is not a valid integer\n", ++ param_name, src_value); ++ } ++ return LPMD_ERROR; ++ } ++ ++ /* Validate the parsed value based on type */ ++ switch (type) { ++ case SLIDER_TYPE_OFFSET: ++ if (validate_slider_value(value, param_name, state_id, ++ SLIDER_OFFSET_MIN, SLIDER_OFFSET_MAX) != LPMD_SUCCESS) ++ return LPMD_ERROR; ++ break; ++ case SLIDER_TYPE_BALANCE: ++ if (validate_slider_value(value, param_name, state_id, ++ SLIDER_BALANCE_MIN, SLIDER_BALANCE_MAX) != LPMD_SUCCESS) ++ return LPMD_ERROR; ++ break; ++ default: ++ lpmd_log_error("Unexpected slider type value: %d\n", type); ++ return LPMD_ERROR; ++ } ++ ++ /* Success - update the destination pointer */ ++ *dest_ptr = value; ++ return LPMD_SUCCESS; ++} ++ + static void save_string_or_zero(char * tmp_value, char * dst_string, int dest_size) + { + if (!strncmp (tmp_value, "-1", strlen ("-1"))) +@@ -37,6 +113,7 @@ static void lpmd_parse_state(xmlDoc *doc, xmlNode *a_node, lpmd_config_t *config + xmlNode *cur_node = NULL; + char *tmp_value; + char *pos; ++ int ret = 0; + lpmd_config_state_t *state = &config->config_states[idx]; + + if (!doc || !a_node || !state) +@@ -101,16 +178,17 @@ static void lpmd_parse_state(xmlDoc *doc, xmlNode *a_node, lpmd_config_t *config + if (!strncmp((const char*)cur_node->name, "ActiveCPUs", strlen("ActiveCPUs"))) + save_string_or_zero(tmp_value, state->active_cpus, sizeof(state->active_cpus)); + if (!strncmp((const char*)cur_node->name, "BalanceSliderAC", strlen("BalanceSliderAC"))) +- state->balance_slider_ac = strtol (tmp_value, &pos, 10); ++ ret = read_slider_and_validate(&state->balance_slider_ac, tmp_value, "BalanceSliderAC", state->id, SLIDER_TYPE_BALANCE); + if (!strncmp((const char*)cur_node->name, "SliderOffsetAC", strlen("SliderOffsetAC"))) +- state->slider_offset_ac = strtol (tmp_value, &pos, 10); +- ++ ret = read_slider_and_validate(&state->slider_offset_ac, tmp_value, "SliderOffsetAC", state->id, SLIDER_TYPE_OFFSET); + if (!strncmp((const char*)cur_node->name, "BalanceSliderDC", strlen("BalanceSliderDC"))) +- state->balance_slider_dc = strtol (tmp_value, &pos, 10); ++ ret = read_slider_and_validate(&state->balance_slider_dc, tmp_value, "BalanceSliderDC", state->id, SLIDER_TYPE_BALANCE); + if (!strncmp((const char*)cur_node->name, "SliderOffsetDC", strlen("SliderOffsetDC"))) +- state->slider_offset_dc = strtol (tmp_value, &pos, 10); ++ ret = read_slider_and_validate(&state->slider_offset_dc, tmp_value, "SliderOffsetDC", state->id, SLIDER_TYPE_OFFSET); + + xmlFree(tmp_value); ++ if (ret) ++ return; + } + } + +@@ -216,6 +294,7 @@ static int lpmd_fill_config(xmlDoc *doc, xmlNode *a_node, lpmd_config_t *lpmd_co + xmlNode *cur_node = NULL; + char *tmp_value; + char *pos; ++ int config_error = 0; /* Track if we encountered a parsing error */ + + if (!doc || !a_node || !lpmd_config) + return LPMD_ERROR; +@@ -390,21 +469,24 @@ static int lpmd_fill_config(xmlDoc *doc, xmlNode *a_node, lpmd_config_t *lpmd_co + lpmd_parse_states(doc, cur_node->children, lpmd_config); + } + else if (!strncmp((const char*)cur_node->name, "BalancedSliderAC", strlen ("BalancedSliderAC"))) { +- errno = 0; +- lpmd_config->balance_slider_def_ac = strtol (tmp_value, &pos, 10); +- ++ if (read_slider_and_validate(&lpmd_config->balance_slider_def_ac, tmp_value, "BalancedSliderAC", -1, SLIDER_TYPE_BALANCE) != 0) { ++ goto err; ++ } + } + else if (!strncmp((const char*)cur_node->name, "BalancedSliderDC", strlen ("BalancedSliderDC"))) { +- errno = 0; +- lpmd_config->balance_slider_def_dc = strtol (tmp_value, &pos, 10); ++ if (read_slider_and_validate(&lpmd_config->balance_slider_def_dc, tmp_value, "BalancedSliderDC", -1, SLIDER_TYPE_BALANCE) != 0) { ++ goto err; ++ } + } + else if (!strncmp((const char*)cur_node->name, "SliderOffsetAC", strlen ("SliderOffsetAC"))) { +- errno = 0; +- lpmd_config->slider_offset_def_ac = strtol (tmp_value, &pos, 10); ++ if (read_slider_and_validate(&lpmd_config->slider_offset_def_ac, tmp_value, "SliderOffsetAC", -1, SLIDER_TYPE_OFFSET) != 0) { ++ goto err; ++ } + } + else if (!strncmp((const char*)cur_node->name, "SliderOffsetDC", strlen ("SliderOffsetDC"))) { +- errno = 0; +- lpmd_config->slider_offset_def_dc = strtol (tmp_value, &pos, 10); ++ if (read_slider_and_validate(&lpmd_config->slider_offset_def_dc, tmp_value, "SliderOffsetDC", -1, SLIDER_TYPE_OFFSET) != 0) { ++ goto err; ++ } + } + else { + if (!strncmp((const char*)cur_node->name, "HfiSuvEnable", strlen("HfiSuvEnable"))) { +@@ -416,14 +498,20 @@ static int lpmd_fill_config(xmlDoc *doc, xmlNode *a_node, lpmd_config_t *lpmd_co + } + xmlFree (tmp_value); + continue; +-err: xmlFree (tmp_value); +- lpmd_log_error ("node type: Element, name: %s value: %s\n", cur_node->name, +- tmp_value); +- return LPMD_ERROR; ++err: ++ lpmd_log_error("node type: Element, name: %s value: %s\n", cur_node->name, ++ tmp_value); ++ xmlFree(tmp_value); ++ config_error = 1; /* Mark that a parsing error occurred */ ++ break; /* Exit loop and validate before returning error */ + } + } + } + ++ /* If a parsing error occurred, return error */ ++ if (config_error) ++ return LPMD_ERROR; ++ + return LPMD_SUCCESS; + } + +-- +2.55.0 + diff --git a/0043-lpmd_cpumask-Refactor-get_cgroup_systemd_vals-to-avo.patch b/0043-lpmd_cpumask-Refactor-get_cgroup_systemd_vals-to-avo.patch new file mode 100644 index 0000000..0a464cb --- /dev/null +++ b/0043-lpmd_cpumask-Refactor-get_cgroup_systemd_vals-to-avo.patch @@ -0,0 +1,115 @@ +From 88a42cafb9695f6111e3133d72986df8e26c1c58 Mon Sep 17 00:00:00 2001 +From: Maciej Wieczor-Retman +Date: Mon, 16 Mar 2026 16:05:58 +0100 +Subject: [PATCH 43/56] lpmd_cpumask: Refactor get_cgroup_systemd_vals() to + avoid passing the size + +Passing size as an argument in unnecessary as it can be obtained through +the get_max_cpus() global LPMD call. + +Signed-off-by: Maciej Wieczor-Retman +--- + src/include/lpmd.h | 2 +- + src/lpmd_cgroup.c | 8 ++++---- + src/lpmd_cpumask.c | 15 +++++++-------- + 3 files changed, 12 insertions(+), 13 deletions(-) + +diff --git a/src/include/lpmd.h b/src/include/lpmd.h +index 8c7193d..123c785 100644 +--- a/src/include/lpmd.h ++++ b/src/include/lpmd.h +@@ -427,7 +427,7 @@ char* get_cpus_hexstr(enum cpumask_idx idx); + char *get_proc_irq_str(enum cpumask_idx idx); + char *get_irqbalance_str(enum cpumask_idx idx); + char *get_cpu_isolation_str(enum cpumask_idx idx); +-uint8_t *get_cgroup_systemd_vals(enum cpumask_idx idx, int *size); ++uint8_t *get_cgroup_systemd_vals(enum cpumask_idx idx); + + /* socket.c */ + int socket_init_connection(char *name); +diff --git a/src/lpmd_cgroup.c b/src/lpmd_cgroup.c +index e74c8cf..1dddce0 100644 +--- a/src/lpmd_cgroup.c ++++ b/src/lpmd_cgroup.c +@@ -115,10 +115,10 @@ finish: if (ret >= 0) { + + static int restore_systemd_cgroup(void) + { +- int size; ++ int size = get_max_cpus() / 8; + uint8_t *vals; + +- vals = get_cgroup_systemd_vals(CPUMASK_ONLINE, &size); ++ vals = get_cgroup_systemd_vals(CPUMASK_ONLINE); + if (!vals) + return -1; + +@@ -131,11 +131,11 @@ static int restore_systemd_cgroup(void) + + static int update_systemd_cgroup(lpmd_config_state_t *state) + { +- int size; ++ int size = get_max_cpus() / 8; + uint8_t *vals; + int ret; + +- vals = get_cgroup_systemd_vals(state->cpumask_idx, &size); ++ vals = get_cgroup_systemd_vals(state->cpumask_idx); + if (!vals) + return -1; + +diff --git a/src/lpmd_cpumask.c b/src/lpmd_cpumask.c +index 6b9b6a8..95d3781 100644 +--- a/src/lpmd_cpumask.c ++++ b/src/lpmd_cpumask.c +@@ -502,11 +502,12 @@ static char* get_cpus_str_reverse(enum cpumask_idx idx) + return cpumasks[idx].str_reverse; + } + +-static uint8_t *get_cpus_hexvals(enum cpumask_idx idx, int *size) ++static uint8_t *get_cpus_hexvals(enum cpumask_idx idx) + { +- int i, j, k; ++ int size = topo_max_cpus / 8; + uint8_t v = 0; + uint8_t *vals; ++ int i, j, k; + + if (!cpumasks[idx].mask) + return NULL; +@@ -514,12 +515,10 @@ static uint8_t *get_cpus_hexvals(enum cpumask_idx idx, int *size) + if (!CPU_COUNT_S(size_cpumask, cpumasks[idx].mask)) + return NULL; + +- *size = topo_max_cpus / 8; +- + if (cpumasks[idx].hexvals) + return cpumasks[idx].hexvals; + +- vals = calloc (*size, 1); ++ vals = calloc (size, 1); + if (!vals) + return NULL; + +@@ -527,7 +526,7 @@ static uint8_t *get_cpus_hexvals(enum cpumask_idx idx, int *size) + j = i % 8; + k = i / 8; + +- if (k >= *size) { ++ if (k >= size) { + lpmd_log_error ("size too big\n"); + free(vals); + return NULL; +@@ -565,7 +564,7 @@ char *get_cpu_isolation_str(enum cpumask_idx idx) + return get_cpus_str_reverse(idx); + } + +-uint8_t *get_cgroup_systemd_vals(enum cpumask_idx idx, int *size) ++uint8_t *get_cgroup_systemd_vals(enum cpumask_idx idx) + { +- return get_cpus_hexvals(idx, size); ++ return get_cpus_hexvals(idx); + } +-- +2.55.0 + diff --git a/0044-lpmd_cpu-Add-a-CPU-blacklist-cpumask.patch b/0044-lpmd_cpu-Add-a-CPU-blacklist-cpumask.patch new file mode 100644 index 0000000..905b366 --- /dev/null +++ b/0044-lpmd_cpu-Add-a-CPU-blacklist-cpumask.patch @@ -0,0 +1,70 @@ +From d31613630df19ac191590dd4c0cbed2a38fedc2d Mon Sep 17 00:00:00 2001 +From: Maciej Wieczor-Retman +Date: Tue, 17 Mar 2026 13:16:13 +0100 +Subject: [PATCH 44/56] lpmd_cpu: Add a CPU blacklist cpumask + +Add a new cpumask that's used to clearing cores from other cpumasks. +Fill the new cpumask with CPUs that couldn't be reached with +sched_setaffinity() indicating that they are not available. + +The specific context of this change is for cases when CPUs are claimed by +other cgroups as exclusive and therefore are not available for the lpm +cgroup. For the cgroup isolation mode this results in LPMD not working +correctly. + +Signed-off-by: Maciej Wieczor-Retman +--- + src/include/lpmd.h | 1 + + src/lpmd_cpu.c | 4 +++- + src/lpmd_cpumask.c | 1 + + 3 files changed, 5 insertions(+), 1 deletion(-) + +diff --git a/src/include/lpmd.h b/src/include/lpmd.h +index 123c785..08ded1c 100644 +--- a/src/include/lpmd.h ++++ b/src/include/lpmd.h +@@ -271,6 +271,7 @@ enum cpumask_idx { + CPUMASK_HFI_BANNED, + CPUMASK_HFI_LAST, + CPUMASK_UTIL, ++ CPUMASK_BLACKLIST, + CPUMASK_USER, + CPUMASK_MAX = CPUMASK_USER + NUM_USER_CPUMASKS, + CPUMASK_NONE = CPUMASK_MAX, +diff --git a/src/lpmd_cpu.c b/src/lpmd_cpu.c +index 9080584..fc3fe4b 100644 +--- a/src/lpmd_cpu.c ++++ b/src/lpmd_cpu.c +@@ -152,6 +152,7 @@ int is_cpu_atom(int cpu) + + if (cpu_migrate(cpu) < 0) { + lpmd_log_error("Failed to migrated to cpu%d\n", cpu); ++ cpumask_add_cpu(cpu, CPUMASK_BLACKLIST); + return -1; + } + +@@ -169,7 +170,8 @@ static int is_cpu_in_l3(int cpu) + + if (cpu_migrate(cpu) < 0) { + lpmd_log_error("Failed to migrated to cpu%d\n", cpu); +- err (1, "cpu migrate"); ++ cpumask_add_cpu(cpu, CPUMASK_BLACKLIST); ++ return -1; + } + + for(subleaf = 0;; subleaf++) { +diff --git a/src/lpmd_cpumask.c b/src/lpmd_cpumask.c +index 95d3781..b1b6d6b 100644 +--- a/src/lpmd_cpumask.c ++++ b/src/lpmd_cpumask.c +@@ -43,6 +43,7 @@ static struct lpm_cpus cpumasks[CPUMASK_MAX] = { + [CPUMASK_HFI] = { .name = "HFI Low Power", }, + [CPUMASK_HFI_BANNED] = { .name = "HFI BANNED", }, + [CPUMASK_HFI_LAST] = { .name = "HFI LAST", }, ++ [CPUMASK_BLACKLIST] = { .name = "Blacklist", }, + }; + + int is_cpu_online(int cpu) +-- +2.55.0 + diff --git a/0045-lpmd_cpu-Skip-filling-out-type-cpumasks-if-there-was.patch b/0045-lpmd_cpu-Skip-filling-out-type-cpumasks-if-there-was.patch new file mode 100644 index 0000000..f724178 --- /dev/null +++ b/0045-lpmd_cpu-Skip-filling-out-type-cpumasks-if-there-was.patch @@ -0,0 +1,40 @@ +From cfeccc5ddf0be8c3594e26cc5b413b91bfc1548b Mon Sep 17 00:00:00 2001 +From: Maciej Wieczor-Retman +Date: Tue, 17 Mar 2026 13:21:52 +0100 +Subject: [PATCH 45/56] lpmd_cpu: Skip filling out type cpumasks if there was + an error + +Don't add CPUs to type related cpumasks if their discovery function +ended with an error. + +Signed-off-by: Maciej Wieczor-Retman +--- + src/lpmd_cpu.c | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +diff --git a/src/lpmd_cpu.c b/src/lpmd_cpu.c +index fc3fe4b..7a4ca9f 100644 +--- a/src/lpmd_cpu.c ++++ b/src/lpmd_cpu.c +@@ -368,15 +368,15 @@ int detect_cpu_topo(lpmd_config_t *lpmd_config) + for (i = 0; i < get_max_cpus(); i++) { + if (!is_cpu_online(i)) + continue; +- if (is_cpu_pcore(i)) { ++ if (is_cpu_pcore(i) > 0) { + pcores++; + lpmd_config->core_type_masks[P_CORE][i / 8] |= 1 << (i % 8); + } +- else if (is_cpu_ecore(i)) { ++ else if (is_cpu_ecore(i) > 0) { + ecores++; + lpmd_config->core_type_masks[E_CORE][i / 8] |= 1 << (i % 8); + } +- else if (is_cpu_lcore(i)) { ++ else if (is_cpu_lcore(i) > 0) { + lcores++; + lpmd_config->core_type_masks[L_CORE][i / 8] |= 1 << (i % 8); + } +-- +2.55.0 + diff --git a/0046-lpmd_cpumask-init-level-complex-isolation-fix-blackl.patch b/0046-lpmd_cpumask-init-level-complex-isolation-fix-blackl.patch new file mode 100644 index 0000000..87f2262 --- /dev/null +++ b/0046-lpmd_cpumask-init-level-complex-isolation-fix-blackl.patch @@ -0,0 +1,154 @@ +From 1d313da29ec41be617e6118a6a5766be74e7f1fa Mon Sep 17 00:00:00 2001 +From: Maciej Wieczor-Retman +Date: Thu, 12 Mar 2026 23:41:18 +0100 +Subject: [PATCH 46/56] lpmd_cpumask: init level complex isolation fix - + blacklist unavailable CPUs + +To use the isolated cgroup feature the cpuset.cpus.exclusive file needs +to be filled with available CPUs - only then a subset of these CPUs can +be written into cpuset.cpus. Otherwise the isolated mode is not in a +valid state. + +While the simple case of all CPUs being available works after being +patched, the case of some other cgroup claiming exclusive ownership of a +couple of CPUs causes the isolated mode in LPMD to be broken again. The +CPUs claimed by the other cgroup need to be taken into account. + +Use the Blacklist CPUs mechanism to exclude the cores that were found to +be unavailable during topology discovery. The blacklist cpumask should +be complete after the topology is discovered. The unavailable cores are +detected by checking onto which core the program cannot be migrated. All +the calls to update other cpumasks are done after that. + +Signed-off-by: Maciej Wieczor-Retman +--- + src/include/lpmd.h | 1 + + src/lpmd_cpu.c | 3 +++ + src/lpmd_cpumask.c | 46 ++++++++++++++++++++++++++++++++++++++-------- + 3 files changed, 42 insertions(+), 8 deletions(-) + +diff --git a/src/include/lpmd.h b/src/include/lpmd.h +index 08ded1c..2f7fdcf 100644 +--- a/src/include/lpmd.h ++++ b/src/include/lpmd.h +@@ -414,6 +414,7 @@ void free_cpu_type_masks(lpmd_config_t *lpmd_config); + int allocate_cpu_type_masks(lpmd_config_t *lpmd_config); + + int cpumask_add_cpu(int cpu, enum cpumask_idx idx); ++int cpumask_blacklist(enum cpumask_idx idx); + int cpumask_init_cpus(char *buf, enum cpumask_idx idx); + int cpumask_init_cpus_type(char * buf, enum cpumask_idx idx, unsigned char **cmasks, enum core_type type); + int cpumask_nr_cpus(enum cpumask_idx idx); +diff --git a/src/lpmd_cpu.c b/src/lpmd_cpu.c +index 7a4ca9f..ed270f2 100644 +--- a/src/lpmd_cpu.c ++++ b/src/lpmd_cpu.c +@@ -382,6 +382,9 @@ int detect_cpu_topo(lpmd_config_t *lpmd_config) + } + } + ++ /* Clear the CPUs claimed by other cgroups from the ONLINE mask */ ++ cpumask_blacklist(CPUMASK_ONLINE); ++ + lpmd_log_info("Detected %d Pcores, %d Ecores, %d Lcores, TDP %dW\n", + pcores, ecores, lcores, lpmd_config->tdp); + ret = snprintf(lpmd_config->cpu_config, MAX_CONFIG_LEN - 1, +diff --git a/src/lpmd_cpumask.c b/src/lpmd_cpumask.c +index b1b6d6b..e6a98b2 100644 +--- a/src/lpmd_cpumask.c ++++ b/src/lpmd_cpumask.c +@@ -243,19 +243,21 @@ int cpumask_init_cpus_type(char * buf, enum cpumask_idx idx, unsigned char **cma + cpumask_add_cpu(current, idx); + next = get_next_cpu_cmask(current + 1, type, cmasks[type]); + if(next == current) /* Couldn't find next core of the provided type */ +- return nr_cpus; ++ goto blacklist; + nr_cpus++; + current = next; + } + +- return nr_cpus; ++blacklist: ++ cpumask_blacklist(idx); ++ ++ return CPU_COUNT_S(size_cpumask, cpumasks[idx].mask); + } + + int cpumask_init_cpus(char *buf, enum cpumask_idx idx) + { + unsigned int start, end; + char *next; +- int nr_cpus = 0; + + if (buf[0] == '\0') + return 0; +@@ -279,7 +281,6 @@ int cpumask_init_cpus(char *buf, enum cpumask_idx idx) + start = strtoul (next, &next, 10); + + cpumask_add_cpu (start, idx); +- nr_cpus++; + + if (*next == '\0') + break; +@@ -304,10 +305,8 @@ int cpumask_init_cpus(char *buf, enum cpumask_idx idx) + if (end <= start) + goto error; + +- while (++start <= end) { ++ while (++start <= end) + cpumask_add_cpu (start, idx); +- nr_cpus++; +- } + + if (*next == ',') + next += 1; +@@ -315,7 +314,9 @@ int cpumask_init_cpus(char *buf, enum cpumask_idx idx) + goto error; + } + +- return nr_cpus; ++ cpumask_blacklist(idx); ++ ++ return CPU_COUNT_S(size_cpumask, cpumasks[idx].mask); + error: + lpmd_log_error ("CPU string malformed: %s\n", buf); + return -1; +@@ -547,6 +548,35 @@ set_val: if (j == 7) { + return cpumasks[idx].hexvals; + } + ++int cpumask_blacklist(enum cpumask_idx idx) ++{ ++ if (!cpumasks[idx].mask) ++ alloc_cpu_set (&cpumasks[idx].mask); ++ ++ /* Return due to blacklist not getting initialized yet. */ ++ if (!cpumasks[CPUMASK_BLACKLIST].mask) { ++ alloc_cpu_set (&cpumasks[CPUMASK_BLACKLIST].mask); ++ return LPMD_ERROR; ++ } ++ ++ /* Return due to blacklist being empty. */ ++ if (!CPU_COUNT_S(size_cpumask, cpumasks[CPUMASK_BLACKLIST].mask)) ++ return LPMD_ERROR; ++ ++ /* Otherwise clear blacklisted cpus from the chosen cpumask */ ++ for (int i = 0 ; i < topo_max_cpus ; i++) ++ if (CPU_ISSET_S(i, size_cpumask, cpumasks[CPUMASK_BLACKLIST].mask)) ++ CPU_CLR_S(i, size_cpumask, cpumasks[idx].mask); ++ ++ if (!CPU_COUNT_S(size_cpumask, cpumasks[idx].mask)) { ++ lpmd_log_error("%s : cpumask[%d] is empty after blacklisting due to unavailable cpus\n", cpumasks[idx].name, idx); ++ lpmd_log_error("It's possible another cgroup claimed all cores required by cpumask[%d]\n", idx); ++ } ++ ++ return LPMD_SUCCESS; ++} ++ ++ + char *get_proc_irq_str(enum cpumask_idx idx) + { + return get_cpus_hexstr(idx); +-- +2.55.0 + diff --git a/0047-lpmd_cpumask-Refresh-cached-data-when-blacklisting-c.patch b/0047-lpmd_cpumask-Refresh-cached-data-when-blacklisting-c.patch new file mode 100644 index 0000000..e8456dc --- /dev/null +++ b/0047-lpmd_cpumask-Refresh-cached-data-when-blacklisting-c.patch @@ -0,0 +1,211 @@ +From 50e0d1eaea860d00adb56ac162c3de346742c3ed Mon Sep 17 00:00:00 2001 +From: Maciej Wieczor-Retman +Date: Tue, 17 Mar 2026 13:16:31 +0100 +Subject: [PATCH 47/56] lpmd_cpumask: Refresh cached data when blacklisting + cpus + +When blacklisting CPUs they are cleared from their cpumask. Other cached +data like hexadecimal representation of the cpumask or decimal numerical +strings for /sys/fs purposes need to be updated when the cpumask +changes. Otherwise only the cached value is displayed since so far the +idea was that once initialized the cached values wouldn't change. + +Signed-off-by: Maciej Wieczor-Retman +--- + src/include/lpmd.h | 4 +-- + src/lpmd_cpu.c | 2 +- + src/lpmd_cpumask.c | 55 ++++++++++++++++++++++++++-------------- + src/lpmd_state_machine.c | 4 +-- + 4 files changed, 41 insertions(+), 24 deletions(-) + +diff --git a/src/include/lpmd.h b/src/include/lpmd.h +index 2f7fdcf..2e9ff33 100644 +--- a/src/include/lpmd.h ++++ b/src/include/lpmd.h +@@ -424,8 +424,8 @@ int cpumask_equal(enum cpumask_idx idx1, enum cpumask_idx idx2); + void cpumask_copy(enum cpumask_idx source, enum cpumask_idx dest); + void cpumask_exclude_copy(enum cpumask_idx source, enum cpumask_idx dest, enum cpumask_idx exlude); + +-char *get_cpus_str(enum cpumask_idx idx); +-char* get_cpus_hexstr(enum cpumask_idx idx); ++char* get_cpus_str(enum cpumask_idx idx, bool refresh); ++char* get_cpus_hexstr(enum cpumask_idx idx, bool refresh); + char *get_proc_irq_str(enum cpumask_idx idx); + char *get_irqbalance_str(enum cpumask_idx idx); + char *get_cpu_isolation_str(enum cpumask_idx idx); +diff --git a/src/lpmd_cpu.c b/src/lpmd_cpu.c +index ed270f2..aa7c1da 100644 +--- a/src/lpmd_cpu.c ++++ b/src/lpmd_cpu.c +@@ -516,7 +516,7 @@ int detect_lpm_cpus(char *cmd_cpus) + + end: if (cpumask_has_cpu(CPUMASK_LPM_DEFAULT)) + lpmd_log_info ("\tUse CPU %s as Default Low Power CPUs (%s)\n", +- get_cpus_str (CPUMASK_LPM_DEFAULT), str); ++ get_cpus_str (CPUMASK_LPM_DEFAULT, false), str); + + return 0; + } +diff --git a/src/lpmd_cpumask.c b/src/lpmd_cpumask.c +index e6a98b2..796004e 100644 +--- a/src/lpmd_cpumask.c ++++ b/src/lpmd_cpumask.c +@@ -441,7 +441,7 @@ static int cpumask_to_hexstr(cpu_set_t *mask, char *str, int size) + return 0; + } + +-char* get_cpus_str(enum cpumask_idx idx) ++char* get_cpus_str(enum cpumask_idx idx, bool refresh) + { + if (!cpumasks[idx].mask) + return NULL; +@@ -449,10 +449,13 @@ char* get_cpus_str(enum cpumask_idx idx) + if (!CPU_COUNT_S(size_cpumask, cpumasks[idx].mask)) + return NULL; + +- if (cpumasks[idx].str) +- return cpumasks[idx].str; ++ if (cpumasks[idx].str) { ++ if (!refresh) ++ return cpumasks[idx].str; ++ } else { ++ cpumasks[idx].str = calloc (MAX_STR_LENGTH, 1); ++ } + +- cpumasks[idx].str = calloc (MAX_STR_LENGTH, 1); + if (!cpumasks[idx].str) + err (3, "STR_ALLOC"); + +@@ -460,7 +463,7 @@ char* get_cpus_str(enum cpumask_idx idx) + return cpumasks[idx].str; + } + +-char* get_cpus_hexstr(enum cpumask_idx idx) ++char* get_cpus_hexstr(enum cpumask_idx idx, bool refresh) + { + if (!cpumasks[idx].mask) + return NULL; +@@ -468,10 +471,14 @@ char* get_cpus_hexstr(enum cpumask_idx idx) + if (!CPU_COUNT_S(size_cpumask, cpumasks[idx].mask)) + return NULL; + +- if (cpumasks[idx].hexstr) +- return cpumasks[idx].hexstr; ++ if (cpumasks[idx].hexstr) { ++ /* Already was allocated, it's okay to use the cached version */ ++ if (!refresh) ++ return cpumasks[idx].hexstr; ++ } else { ++ cpumasks[idx].hexstr = calloc (MAX_STR_LENGTH, 1); ++ } + +- cpumasks[idx].hexstr = calloc (MAX_STR_LENGTH, 1); + if (!cpumasks[idx].hexstr) + err (3, "STR_ALLOC"); + +@@ -479,7 +486,7 @@ char* get_cpus_hexstr(enum cpumask_idx idx) + return cpumasks[idx].hexstr; + } + +-static char* get_cpus_str_reverse(enum cpumask_idx idx) ++static char* get_cpus_str_reverse(enum cpumask_idx idx, bool refresh) + { + cpu_set_t *mask; + +@@ -489,10 +496,13 @@ static char* get_cpus_str_reverse(enum cpumask_idx idx) + if (!CPU_COUNT_S(size_cpumask, cpumasks[idx].mask)) + return NULL; + +- if (cpumasks[idx].str_reverse) +- return cpumasks[idx].str_reverse; ++ if (cpumasks[idx].str_reverse) { ++ if (!refresh) ++ return cpumasks[idx].str_reverse; ++ } else { ++ cpumasks[idx].str_reverse = calloc (MAX_STR_LENGTH, 1); ++ } + +- cpumasks[idx].str_reverse = calloc (MAX_STR_LENGTH, 1); + if (!cpumasks[idx].str_reverse) + err (3, "STR_ALLOC"); + +@@ -504,7 +514,7 @@ static char* get_cpus_str_reverse(enum cpumask_idx idx) + return cpumasks[idx].str_reverse; + } + +-static uint8_t *get_cpus_hexvals(enum cpumask_idx idx) ++static uint8_t *get_cpus_hexvals(enum cpumask_idx idx, bool refresh) + { + int size = topo_max_cpus / 8; + uint8_t v = 0; +@@ -518,7 +528,8 @@ static uint8_t *get_cpus_hexvals(enum cpumask_idx idx) + return NULL; + + if (cpumasks[idx].hexvals) +- return cpumasks[idx].hexvals; ++ if (!refresh) ++ return cpumasks[idx].hexvals; + + vals = calloc (size, 1); + if (!vals) +@@ -568,6 +579,12 @@ int cpumask_blacklist(enum cpumask_idx idx) + if (CPU_ISSET_S(i, size_cpumask, cpumasks[CPUMASK_BLACKLIST].mask)) + CPU_CLR_S(i, size_cpumask, cpumasks[idx].mask); + ++ /* Update any relevant cached data. */ ++ cpumasks[idx].hexstr = get_cpus_hexstr(idx, true); ++ cpumasks[idx].str = get_cpus_str(idx, true); ++ cpumasks[idx].str_reverse = get_cpus_str_reverse(idx, true); ++ cpumasks[idx].hexvals = get_cpus_hexvals(idx, true); ++ + if (!CPU_COUNT_S(size_cpumask, cpumasks[idx].mask)) { + lpmd_log_error("%s : cpumask[%d] is empty after blacklisting due to unavailable cpus\n", cpumasks[idx].name, idx); + lpmd_log_error("It's possible another cgroup claimed all cores required by cpumask[%d]\n", idx); +@@ -579,23 +596,23 @@ int cpumask_blacklist(enum cpumask_idx idx) + + char *get_proc_irq_str(enum cpumask_idx idx) + { +- return get_cpus_hexstr(idx); ++ return get_cpus_hexstr(idx, false); + } + + char *get_irqbalance_str(enum cpumask_idx idx) + { +- return get_cpus_str_reverse(idx); ++ return get_cpus_str_reverse(idx, false); + } + + char *get_cpu_isolation_str(enum cpumask_idx idx) + { + if (idx == CPUMASK_ONLINE) +- return get_cpus_str(idx); ++ return get_cpus_str(idx, false); + else +- return get_cpus_str_reverse(idx); ++ return get_cpus_str_reverse(idx, false); + } + + uint8_t *get_cgroup_systemd_vals(enum cpumask_idx idx) + { +- return get_cpus_hexvals(idx); ++ return get_cpus_hexvals(idx, false); + } +diff --git a/src/lpmd_state_machine.c b/src/lpmd_state_machine.c +index 677dc0d..8964b9a 100644 +--- a/src/lpmd_state_machine.c ++++ b/src/lpmd_state_machine.c +@@ -370,9 +370,9 @@ static void dump_data(lpmd_config_t *config, int idx) + } + + if (state->cpumask_idx != CPUMASK_NONE) +- offset += snprintf(buf + offset , MAX_STR_LENGTH - offset, "CPUMASK [%s] ", get_cpus_hexstr(state->cpumask_idx)); ++ offset += snprintf(buf + offset , MAX_STR_LENGTH - offset, "CPUMASK [%s] ", get_cpus_hexstr(state->cpumask_idx, false)); + else +- offset += snprintf(buf + offset , MAX_STR_LENGTH - offset, "CPUMASK [%s] ", get_cpus_hexstr(CPUMASK_ONLINE)); ++ offset += snprintf(buf + offset , MAX_STR_LENGTH - offset, "CPUMASK [%s] ", get_cpus_hexstr(CPUMASK_ONLINE, false)); + + offset += snprintf(buf + offset , MAX_STR_LENGTH - offset, "ITMT [%d] ", get_itmt()); + +-- +2.55.0 + diff --git a/0048-lpmd_cpumask-Refactor-getting-cached-values.patch b/0048-lpmd_cpumask-Refactor-getting-cached-values.patch new file mode 100644 index 0000000..7180afc --- /dev/null +++ b/0048-lpmd_cpumask-Refactor-getting-cached-values.patch @@ -0,0 +1,118 @@ +From c48bf5e87ce9ef232cc228dfa6325ff6c99123e3 Mon Sep 17 00:00:00 2001 +From: Maciej Wieczor-Retman +Date: Mon, 16 Mar 2026 16:23:42 +0100 +Subject: [PATCH 48/56] lpmd_cpumask: Refactor getting cached values + +Getting cached values have common init code that checks a few simple +values or allocates the space in case it's the first time the cached +value is accessed. + +Move it all to a helper to simplify these calls. + +Signed-off-by: Maciej Wieczor-Retman +--- + src/lpmd_cpumask.c | 60 ++++++++++++++++++---------------------------- + 1 file changed, 23 insertions(+), 37 deletions(-) + +diff --git a/src/lpmd_cpumask.c b/src/lpmd_cpumask.c +index 796004e..2a446cf 100644 +--- a/src/lpmd_cpumask.c ++++ b/src/lpmd_cpumask.c +@@ -441,23 +441,33 @@ static int cpumask_to_hexstr(cpu_set_t *mask, char *str, int size) + return 0; + } + +-char* get_cpus_str(enum cpumask_idx idx, bool refresh) ++int get_cached_value_init(enum cpumask_idx idx, bool refresh, ++ char **cached_str, const char *cached_name) + { + if (!cpumasks[idx].mask) +- return NULL; ++ return LPMD_ERROR; + + if (!CPU_COUNT_S(size_cpumask, cpumasks[idx].mask)) +- return NULL; ++ return LPMD_ERROR; + +- if (cpumasks[idx].str) { ++ if (*cached_str) { + if (!refresh) +- return cpumasks[idx].str; ++ return LPMD_SUCCESS; + } else { +- cpumasks[idx].str = calloc (MAX_STR_LENGTH, 1); ++ *cached_str = calloc (MAX_STR_LENGTH, 1); + } + +- if (!cpumasks[idx].str) +- err (3, "STR_ALLOC"); ++ if (!(*cached_str)) ++ err (3, "%s_ALLOC", cached_name); ++ ++ return LPMD_SUCCESS; ++} ++ ++char* get_cpus_str(enum cpumask_idx idx, bool refresh) ++{ ++ int ret = get_cached_value_init(idx, refresh, &cpumasks[idx].str, "STR"); ++ if (ret) ++ return NULL; + + cpumask_to_str (cpumasks[idx].mask, cpumasks[idx].str, MAX_STR_LENGTH); + return cpumasks[idx].str; +@@ -465,23 +475,10 @@ char* get_cpus_str(enum cpumask_idx idx, bool refresh) + + char* get_cpus_hexstr(enum cpumask_idx idx, bool refresh) + { +- if (!cpumasks[idx].mask) +- return NULL; +- +- if (!CPU_COUNT_S(size_cpumask, cpumasks[idx].mask)) ++ int ret = get_cached_value_init(idx, refresh, &cpumasks[idx].hexstr, "HEXSTR"); ++ if (ret) + return NULL; + +- if (cpumasks[idx].hexstr) { +- /* Already was allocated, it's okay to use the cached version */ +- if (!refresh) +- return cpumasks[idx].hexstr; +- } else { +- cpumasks[idx].hexstr = calloc (MAX_STR_LENGTH, 1); +- } +- +- if (!cpumasks[idx].hexstr) +- err (3, "STR_ALLOC"); +- + cpumask_to_hexstr (cpumasks[idx].mask, cpumasks[idx].hexstr, MAX_STR_LENGTH); + return cpumasks[idx].hexstr; + } +@@ -489,23 +486,12 @@ char* get_cpus_hexstr(enum cpumask_idx idx, bool refresh) + static char* get_cpus_str_reverse(enum cpumask_idx idx, bool refresh) + { + cpu_set_t *mask; ++ int ret; + +- if (!cpumasks[idx].mask) +- return NULL; +- +- if (!CPU_COUNT_S(size_cpumask, cpumasks[idx].mask)) ++ ret = get_cached_value_init(idx, refresh, &cpumasks[idx].str_reverse, "STR_REVERSE"); ++ if (ret) + return NULL; + +- if (cpumasks[idx].str_reverse) { +- if (!refresh) +- return cpumasks[idx].str_reverse; +- } else { +- cpumasks[idx].str_reverse = calloc (MAX_STR_LENGTH, 1); +- } +- +- if (!cpumasks[idx].str_reverse) +- err (3, "STR_ALLOC"); +- + alloc_cpu_set (&mask); + CPU_XOR_S(size_cpumask, mask, cpumasks[idx].mask, cpumasks[CPUMASK_ONLINE].mask); + cpumask_to_str (mask, cpumasks[idx].str_reverse, MAX_STR_LENGTH); +-- +2.55.0 + diff --git a/0049-lpmd_proc-Export-the-state-name-when-an-empty-cpumas.patch b/0049-lpmd_proc-Export-the-state-name-when-an-empty-cpumas.patch new file mode 100644 index 0000000..92d7d1c --- /dev/null +++ b/0049-lpmd_proc-Export-the-state-name-when-an-empty-cpumas.patch @@ -0,0 +1,76 @@ +From c01f695e4c8fcb23696db7e39c430c7605a15361 Mon Sep 17 00:00:00 2001 +From: Maciej Wieczor-Retman +Date: Mon, 16 Mar 2026 20:01:16 +0100 +Subject: [PATCH 49/56] lpmd_proc: Export the state name when an empty cpumask + is caught + +Blacklisting CPUs can result in empty cpumask if some other cgroup +claims all cores present in a given cpumask. A warning without the state +name is not very useful for the user that might want to debug this. + +Try matching the state name by the cpumask idx. It should work for user +defined states as they receive unique cpumask indexes. + +Signed-off-by: Maciej Wieczor-Retman +--- + src/include/lpmd.h | 2 ++ + src/lpmd_cpumask.c | 3 ++- + src/lpmd_proc.c | 15 +++++++++++++++ + 3 files changed, 19 insertions(+), 1 deletion(-) + +diff --git a/src/include/lpmd.h b/src/include/lpmd.h +index 2e9ff33..cab53b0 100644 +--- a/src/include/lpmd.h ++++ b/src/include/lpmd.h +@@ -329,6 +329,8 @@ void lpmd_set_auto(void); + int is_on_battery(void); + int get_ppd_mode(void); + ++char *user_cpumask_idx_to_state_name(enum cpumask_idx idx); ++ + /* lpmd_proc.c: init func */ + int lpmd_main(void); + void update_reason(int reason); +diff --git a/src/lpmd_cpumask.c b/src/lpmd_cpumask.c +index 2a446cf..3d6a22b 100644 +--- a/src/lpmd_cpumask.c ++++ b/src/lpmd_cpumask.c +@@ -572,7 +572,8 @@ int cpumask_blacklist(enum cpumask_idx idx) + cpumasks[idx].hexvals = get_cpus_hexvals(idx, true); + + if (!CPU_COUNT_S(size_cpumask, cpumasks[idx].mask)) { +- lpmd_log_error("%s : cpumask[%d] is empty after blacklisting due to unavailable cpus\n", cpumasks[idx].name, idx); ++ char *state_name = user_cpumask_idx_to_state_name(idx); ++ lpmd_log_error("%s: cpumask[%d] is empty after blacklisting due to unavailable cpus\n", state_name, idx); + lpmd_log_error("It's possible another cgroup claimed all cores required by cpumask[%d]\n", idx); + } + +diff --git a/src/lpmd_proc.c b/src/lpmd_proc.c +index 91d1d15..3c3fafb 100644 +--- a/src/lpmd_proc.c ++++ b/src/lpmd_proc.c +@@ -298,6 +298,21 @@ void update_reason(int reason) + lpmd_config.data.need_update |= 1 << reason; + } + ++/* ++ * This function should only work for user defined states - the ones located in ++ * config files inside the tag. Others like the default ones can share ++ * their cpumasks with other states and therefore can't be uniquely identified ++ * by their cpumask idx. ++ */ ++char *user_cpumask_idx_to_state_name(enum cpumask_idx idx) { ++ ++ for (int i = 0 ; i < MAX_STATES ; i++) { ++ if (lpmd_config.config_states[i].cpumask_idx == idx) ++ return lpmd_config.config_states[i].name; ++ } ++ return NULL; ++} ++ + // LPMD processing thread. This is callback to pthread lpmd_core_main + static void* lpmd_core_main_loop(void *arg) + { +-- +2.55.0 + diff --git a/0050-Use-return-value-of-lpmd_read_int.patch b/0050-Use-return-value-of-lpmd_read_int.patch new file mode 100644 index 0000000..8e862a8 --- /dev/null +++ b/0050-Use-return-value-of-lpmd_read_int.patch @@ -0,0 +1,57 @@ +From 978e8f1efe56b1b01e93c159ca4b612f1ba244c6 Mon Sep 17 00:00:00 2001 +From: Srinivas Pandruvada +Date: Mon, 20 Apr 2026 10:53:59 -0700 +Subject: [PATCH 50/56] Use return value of lpmd_read_int() + +Don't ignore return value of lpmd_read_int(). Return error to caller +to handle. + +Signed-off-by: Srinivas Pandruvada +--- + src/lpmd_misc.c | 6 ++++-- + src/lpmd_state_machine.c | 4 ++-- + 2 files changed, 6 insertions(+), 4 deletions(-) + +diff --git a/src/lpmd_misc.c b/src/lpmd_misc.c +index 77725e4..b0def2b 100644 +--- a/src/lpmd_misc.c ++++ b/src/lpmd_misc.c +@@ -381,6 +381,7 @@ static char *get_ppd_default_epp(void) + int get_epp_epb(int *epp, char *epp_str, int size, int *epb) + { + char path[MAX_STR_LENGTH]; ++ int ret; + + *epp = -1; + epp_str[0] = '\0'; +@@ -389,9 +390,10 @@ int get_epp_epb(int *epp, char *epp_str, int size, int *epb) + get_epp (path, epp, epp_str, size); + epp_str[size - 1] = '\0'; + ++ *epb = -1; + snprintf(path, MAX_STR_LENGTH, "/sys/devices/system/cpu/cpu%d/power/energy_perf_bias", 0); +- lpmd_read_int(path, epb, -1); +- return 0; ++ ret = lpmd_read_int(path, epb, -1); ++ return ret; + } + + int process_epp_epb(lpmd_config_state_t *state) +diff --git a/src/lpmd_state_machine.c b/src/lpmd_state_machine.c +index 8964b9a..9927377 100644 +--- a/src/lpmd_state_machine.c ++++ b/src/lpmd_state_machine.c +@@ -376,8 +376,8 @@ static void dump_data(lpmd_config_t *config, int idx) + + offset += snprintf(buf + offset , MAX_STR_LENGTH - offset, "ITMT [%d] ", get_itmt()); + +- get_epp_epb(&epp, epp_str, 32, &epb); +- if (epp == -1) ++ int ret = get_epp_epb(&epp, epp_str, 32, &epb); ++ if (ret || epp == -1) + offset += snprintf(buf + offset , MAX_STR_LENGTH - offset, "EPB [%d] EPP[%s] ", epb, epp_str); + else + offset += snprintf(buf + offset , MAX_STR_LENGTH - offset, "EPB [%d] EPP[%d] ", epb, epp); +-- +2.55.0 + diff --git a/0051-all-Apply-kernel-formatting.patch b/0051-all-Apply-kernel-formatting.patch new file mode 100644 index 0000000..a2486ae --- /dev/null +++ b/0051-all-Apply-kernel-formatting.patch @@ -0,0 +1,9475 @@ +From 2396820384bc2e1d9b08d96e4a5f5c7c280e8356 Mon Sep 17 00:00:00 2001 +From: Maciej Wieczor-Retman +Date: Mon, 18 May 2026 21:54:09 +0200 +Subject: [PATCH 51/56] all: Apply kernel formatting + +Project wide changes after scanning the codebase with Linux kernel +checkpatch and applying fixes to achieve kernel formatting style. + +Patch tries to mirror [1], with slight chagnes to accomodate new +features added before posting [1]. + +[srinivas: Fix license] + +Signed-off-by: Fabio M. De Francesco +Co-developed-by: Maciej Wieczor-Retman +Signed-off-by: Maciej Wieczor-Retman +--- + data/intel_lpmd_config_F6_M204.xml | 2 +- + man/intel_lpmd.8 | 25 +- + man/intel_lpmd_config.xml.5 | 25 +- + man/intel_lpmd_control.8 | 27 +- + src/include/lpmd.h | 123 ++-- + src/include/thermal.h | 25 +- + src/lpmd_cgroup.c | 141 ++--- + src/lpmd_config.c | 694 ++++++++++----------- + src/lpmd_cpu.c | 174 +++--- + src/lpmd_cpumask.c | 125 ++-- + src/lpmd_dbus_server.c | 129 ++-- + src/lpmd_helpers.c | 203 +++--- + src/lpmd_hfi.c | 253 ++++---- + src/lpmd_irq.c | 175 +++--- + src/lpmd_main.c | 296 ++++----- + src/lpmd_misc.c | 184 +++--- + src/lpmd_proc.c | 299 ++++----- + src/lpmd_socket.c | 93 ++- + src/lpmd_state_machine.c | 373 ++++++----- + src/lpmd_uevent.c | 78 +-- + src/lpmd_util.c | 112 ++-- + src/lpmd_wlt.c | 33 +- + src/wlt_proxy/include/state_common.h | 129 ++-- + src/wlt_proxy/include/wlt_proxy.h | 28 +- + src/wlt_proxy/spike_mgmt.c | 258 ++++---- + src/wlt_proxy/state_machine.c | 565 ++++++++--------- + src/wlt_proxy/state_manager.c | 361 ++++++----- + src/wlt_proxy/state_util.c | 893 ++++++++++++++------------- + src/wlt_proxy/wlt_proxy.c | 42 +- + tests/lpm_test_interface.sh | 2 + + tools/intel_lpmd_control.c | 134 ++-- + 31 files changed, 2800 insertions(+), 3201 deletions(-) + +diff --git a/data/intel_lpmd_config_F6_M204.xml b/data/intel_lpmd_config_F6_M204.xml +index 83a0fb2..3ede29b 100644 +--- a/data/intel_lpmd_config_F6_M204.xml ++++ b/data/intel_lpmd_config_F6_M204.xml +@@ -74,7 +74,7 @@ for Intel Energy Optimizer (LPMD) daemon + + 15 + +diff --git a/man/intel_lpmd.8 b/man/intel_lpmd.8 +index 8e36e73..413d4c3 100644 +--- a/man/intel_lpmd.8 ++++ b/man/intel_lpmd.8 +@@ -1,26 +1,5 @@ +-.\" intel_lpmd (8) manual page +-.\" +-.\" This is free documentation; you can redistribute it and/or +-.\" modify it under the terms of the GNU General Public License as +-.\" published by the Free Software Foundation; either version 2 of +-.\" the License, or (at your option) any later version. +-.\" +-.\" The GNU General Public License's references to "object code" +-.\" and "executables" are to be interpreted as the output of any +-.\" document formatting or typesetting system, including +-.\" intermediate and printed output. +-.\" +-.\" This manual is distributed in the hope that it will be useful, +-.\" but WITHOUT ANY WARRANTY; without even the implied warranty of +-.\" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +-.\" GNU General Public License for more details. +-.\" +-.\" You should have received a copy of the GNU General Public Licence along +-.\" with this manual; if not, write to the Free Software Foundation, Inc., +-.\" 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +-.\" +-.\" Copyright (C) 2012 Intel Corporation. All rights reserved. +-.\" ++.\" SPDX-License-Identifier: GPL-2.0-or-later ++.\" Copyright (C) 2026 Intel Corporation + .TH intel_lpmd "8" "08 Apr 2026" + + .SH NAME +diff --git a/man/intel_lpmd_config.xml.5 b/man/intel_lpmd_config.xml.5 +index 013448e..eed4175 100644 +--- a/man/intel_lpmd_config.xml.5 ++++ b/man/intel_lpmd_config.xml.5 +@@ -1,26 +1,5 @@ +-.\" intel_lpmd_config.xml(5) manual page +-.\" +-.\" This is free documentation; you can redistribute it and/or +-.\" modify it under the terms of the GNU General Public License as +-.\" published by the Free Software Foundation; either version 2 of +-.\" the License, or (at your option) any later version. +-.\" +-.\" The GNU General Public License's references to "object code" +-.\" and "executables" are to be interpreted as the output of any +-.\" document formatting or typesetting system, including +-.\" intermediate and printed output. +-.\" +-.\" This manual is distributed in the hope that it will be useful, +-.\" but WITHOUT ANY WARRANTY; without even the implied warranty of +-.\" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +-.\" GNU General Public License for more details. +-.\" +-.\" You should have received a copy of the GNU General Public Licence along +-.\" with this manual; if not, write to the Free Software Foundation, Inc., +-.\" 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +-.\" +-.\" Copyright (C) 2012 Intel Corporation. All rights reserved. +-.\" ++.\" SPDX-License-Identifier: GPL-2.0-or-later ++.\" Copyright (C) 2026 Intel Corporation + .TH intel_lpmd_config.xml "5" "8 Apr 2026" + + .SH NAME +diff --git a/man/intel_lpmd_control.8 b/man/intel_lpmd_control.8 +index 854cd6f..a1f008d 100644 +--- a/man/intel_lpmd_control.8 ++++ b/man/intel_lpmd_control.8 +@@ -1,26 +1,5 @@ +-.\" intel_lpmd_control (8) manual page +-.\" +-.\" This is free documentation; you can redistribute it and/or +-.\" modify it under the terms of the GNU General Public License as +-.\" published by the Free Software Foundation; either version 2 of +-.\" the License, or (at your option) any later version. +-.\" +-.\" The GNU General Public License's references to "object code" +-.\" and "executables" are to be interpreted as the output of any +-.\" document formatting or typesetting system, including +-.\" intermediate and printed output. +-.\" +-.\" This manual is distributed in the hope that it will be useful, +-.\" but WITHOUT ANY WARRANTY; without even the implied warranty of +-.\" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +-.\" GNU General Public License for more details. +-.\" +-.\" You should have received a copy of the GNU General Public Licence along +-.\" with this manual; if not, write to the Free Software Foundation, Inc., +-.\" 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +-.\" +-.\" Copyright (C) 2025 Intel Corporation. All rights reserved. +-.\" ++.\" SPDX-License-Identifier: GPL-2.0-or-later ++.\" Copyright (C) 2026 Intel Corporation + .TH intel_lpmd_control "8" "8 Apr 2026" + + .SH NAME +@@ -62,4 +41,4 @@ Turns on low power mode operation in automatic mode. + .B intel_lpmd_config.xml(5), intel_lpmd(8) + + .SH AUTHOR +-Written by Deepak Sundar +\ No newline at end of file ++Written by Deepak Sundar +diff --git a/src/include/lpmd.h b/src/include/lpmd.h +index cab53b0..31e5fd4 100644 +--- a/src/include/lpmd.h ++++ b/src/include/lpmd.h +@@ -1,22 +1,5 @@ +-/* +- * intel_lpmd.h: Intel Low Power Daemon common header file +- * +- * Copyright (C) 2023 Intel Corporation. All rights reserved. +- * +- * This program is free software; you can redistribute it and/or modify +- * it under the terms of the GNU General Public License as published by +- * the Free Software Foundation; either version 2 of the License, or +- * (at your option) any later version. +- * +- * This program is distributed in the hope that it will be useful, +- * but WITHOUT ANY WARRANTY; without even the implied warranty of +- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +- * GNU General Public License for more details. +- * +- * You should have received a copy of the GNU General Public License +- * along with this program; if not, write to the Free Software +- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +- */ ++/* SPDX-License-Identifier: GPL-2.0-or-later */ ++ + #ifndef LPMD_INTEL_LPMD_H + #define LPMD_INTEL_LPMD_H + +@@ -50,6 +33,7 @@ + #include + #include + ++extern gint watcher_id; + + // Log macros + enum log_level { +@@ -73,6 +57,7 @@ static int dummy_printf(const char *__restrict __format, ...) + { + return 0; + } ++ + #define lpmd_log_fatal printf + #define lpmd_log_error printf + #define lpmd_log_warn printf +@@ -101,21 +86,21 @@ enum slider_param_type { + + // Dbus related + /* Well-known name for this service. */ +-#define INTEL_LPMD_SERVICE_NAME "org.freedesktop.intel_lpmd" +-#define INTEL_LPMD_SERVICE_OBJECT_PATH "/org/freedesktop/intel_lpmd" ++#define INTEL_LPMD_SERVICE_NAME "org.freedesktop.intel_lpmd" ++#define INTEL_LPMD_SERVICE_OBJECT_PATH "/org/freedesktop/intel_lpmd" + #define INTEL_LPMD_SERVICE_INTERFACE "org.freedesktop.intel_lpmd" + +-typedef enum { ++enum message_name_t { + TERMINATE, LPM_FORCE_ON, LPM_FORCE_OFF, LPM_AUTO, HFI_EVENT, +-} message_name_t; ++}; + + #define MAX_MSG_SIZE 512 + +-typedef struct { +- message_name_t msg_id; ++struct message_capsul_t { ++ enum message_name_t msg_id; + int msg_size; + unsigned long msg[MAX_MSG_SIZE]; +-} message_capsul_t; ++}; + + #define MAX_STR_LENGTH 256 + #define MAX_FILE_NAME_PATH 128 +@@ -140,14 +125,14 @@ enum lpmd_update_reason { + UPDATE_WLT, + }; + +-typedef struct { ++struct lpmd_data_t { + int util_cpu; /* From Util monitor */ + int util_sys; /* From Util monitor */ + int util_gfx; /* From Util monitor */ + int wlt_hint; /* From WLT monitor */ + int polling_interval; + int need_update; +-}lpmd_data_t; ++}; + + enum default_config_state { + DEFAULT_OFF, /* lpmd force off: state with all default power settings */ +@@ -165,7 +150,7 @@ enum core_type { + L_CORE + }; + +-typedef struct { ++struct lpmd_config_state_t { + int id; + int valid; + char name[MAX_STATE_NAME]; +@@ -204,10 +189,10 @@ typedef struct { + int entry_load_cpu; + int cpumask_idx; + int steady; +-}lpmd_config_state_t; ++}; + + // lpmd config data +-typedef struct { ++struct lpmd_config_t { + int mode; + int performance_def; + int balanced_def; +@@ -250,10 +235,10 @@ typedef struct { + int balance_slider_def_dc; + int slider_offset_def_dc; + +- lpmd_config_state_t config_states[MAX_STATES]; +- lpmd_data_t data; ++ struct lpmd_config_state_t config_states[MAX_STATES]; ++ struct lpmd_data_t data; + unsigned char *core_type_masks[CORE_TYPES_COUNT]; +-} lpmd_config_t; ++}; + + enum lpm_cpu_process_mode { + LPM_CPU_CGROUPV2, +@@ -280,27 +265,31 @@ enum cpumask_idx { + #define UTIL_DELAY_MAX 5000 + #define UTIL_HYST_MAX 10000 + +-#define cpuid(leaf, eax, ebx, ecx, edx) \ +- __cpuid(leaf, eax, ebx, ecx, edx); \ +- lpmd_log_debug("CPUID 0x%08x: eax = 0x%08x ebx = 0x%08x ecx = 0x%08x edx = 0x%08x\n", \ +- leaf, eax, ebx, ecx, edx); ++#define cpuid(leaf, eax, ebx, ecx, edx) \ ++ do { \ ++ __cpuid(leaf, eax, ebx, ecx, edx); \ ++ lpmd_log_debug("CPUID 0x%08x: eax = 0x%08x ebx = 0x%08x ecx = 0x%08x edx = 0x%08x\n", \ ++ leaf, eax, ebx, ecx, edx); \ ++ } while (0) + +-#define cpuid_count(leaf, subleaf, eax, ebx, ecx, edx) \ +- __cpuid_count(leaf, subleaf, eax, ebx, ecx, edx); \ +- lpmd_log_debug("CPUID 0x%08x subleaf 0x%08x: eax = 0x%08x ebx = 0x%08x ecx = 0x%08x" \ +- "edx = 0x%08x\n", leaf, subleaf, eax, ebx, ecx, edx); ++#define cpuid_count(leaf, subleaf, eax, ebx, ecx, edx) \ ++ do { \ ++ __cpuid_count(leaf, subleaf, eax, ebx, ecx, edx); \ ++ lpmd_log_debug("CPUID 0x%08x subleaf 0x%08x: eax = 0x%08x ebx = 0x%08x ecx = 0x%08x" \ ++ "edx = 0x%08x\n", leaf, subleaf, eax, ebx, ecx, edx); \ ++ } while (0) + + #define SETTING_RESTORE -2 + #define SETTING_IGNORE -1 + + /* WLT hints parsing */ +-typedef enum { ++enum wlt_type_t { + WLT_IDLE = 0, + WLT_BATTERY_LIFE = 1, + WLT_SUSTAINED = 2, + WLT_BURSTY = 3, + WLT_INVALID = 4, +-} wlt_type_t; ++}; + + enum power_profile_daemon_mode { + PPD_PERFORMANCE, +@@ -316,7 +305,7 @@ int in_debug_mode(void); + int do_platform_check(void); + + /* lpmd_proc.c: interfaces */ +-lpmd_config_t *get_lpmd_config(void); ++struct lpmd_config_t *get_lpmd_config(void); + + int lpmd_lock(void); + int lpmd_unlock(void); +@@ -340,18 +329,18 @@ int intel_dbus_server_init(gboolean (*exit_handler)(void)); + + /* lpmd_config.c */ + int match_config_file(int family, int model, int tdp, char *save_file_name); +-int lpmd_get_config(lpmd_config_t *lpmd_config); ++int lpmd_get_config(struct lpmd_config_t *lpmd_config); + int is_wildcard(char *str); + + /* lpmd_state_machine.c */ + int update_lpmd_state(int state); + int get_lpmd_state(void); +-int lpmd_init_config_state(lpmd_config_state_t *state); +-int lpmd_build_config_states(lpmd_config_t *config); ++int lpmd_init_config_state(struct lpmd_config_state_t *state); ++int lpmd_build_config_states(struct lpmd_config_t *config); + int lpmd_enter_next_state(void); + + /* lpmd_util.c */ +-int util_update(lpmd_config_t *lpmd_config); ++int util_update(struct lpmd_config_t *lpmd_config); + + /* lpmd_hfi.c */ + int hfi_init(void); +@@ -367,32 +356,32 @@ int wlt_set_notification_delay(int delay); + /* lpmd_misc.c */ + void itmt_init(void); + int get_itmt(void); +-int process_itmt(lpmd_config_state_t *state); ++int process_itmt(struct lpmd_config_state_t *state); + + int epp_epb_init(void); + int get_epp_epb(int *epp, char *epp_str, int size, int *epb); +-int process_epp_epb(lpmd_config_state_t *state); ++int process_epp_epb(struct lpmd_config_state_t *state); + +-void process_balance_slider_default_update(lpmd_config_t *config); +-void process_slider_offset_default_update(lpmd_config_t *config); +-void process_slider(lpmd_config_t *config, lpmd_config_state_t *state); ++void process_balance_slider_default_update(struct lpmd_config_t *config); ++void process_slider_offset_default_update(struct lpmd_config_t *config); ++void process_slider(struct lpmd_config_t *config, struct lpmd_config_state_t *state); + + /* lpmd_irq.c */ + int irq_init(void); +-int process_irq(lpmd_config_state_t *state); ++int process_irq(struct lpmd_config_state_t *state); + + /* lpmd_cgroup.c*/ +-int cgroup_init(lpmd_config_t *config); ++int cgroup_init(struct lpmd_config_t *config); + int cgroup_cleanup(void); +-int process_cgroup(lpmd_config_state_t *state, enum lpm_cpu_process_mode mode); ++int process_cgroup(struct lpmd_config_state_t *state, enum lpm_cpu_process_mode mode); + + /* lpmd_uevent.c */ + int uevent_init(void); + int check_cpu_hotplug(void); + + /* lpmd_cpu.c */ +-int detect_supported_platform(lpmd_config_t *lpmd_config); +-int detect_cpu_topo(lpmd_config_t *lpmd_config); ++int detect_supported_platform(struct lpmd_config_t *lpmd_config); ++int detect_cpu_topo(struct lpmd_config_t *lpmd_config); + int detect_lpm_cpus(char *cmd_cpus); + int get_tdp(void); + +@@ -412,22 +401,22 @@ int cpumask_alloc(void); + int cpumask_free(enum cpumask_idx idx); + int cpumask_reset(enum cpumask_idx idx); + +-void free_cpu_type_masks(lpmd_config_t *lpmd_config); +-int allocate_cpu_type_masks(lpmd_config_t *lpmd_config); ++void free_cpu_type_masks(struct lpmd_config_t *lpmd_config); ++int allocate_cpu_type_masks(struct lpmd_config_t *lpmd_config); + + int cpumask_add_cpu(int cpu, enum cpumask_idx idx); + int cpumask_blacklist(enum cpumask_idx idx); + int cpumask_init_cpus(char *buf, enum cpumask_idx idx); +-int cpumask_init_cpus_type(char * buf, enum cpumask_idx idx, unsigned char **cmasks, enum core_type type); ++int cpumask_init_cpus_type(char *buf, enum cpumask_idx idx, unsigned char **cmasks, enum core_type type); + int cpumask_nr_cpus(enum cpumask_idx idx); + int cpumask_has_cpu(enum cpumask_idx idx); + + int cpumask_equal(enum cpumask_idx idx1, enum cpumask_idx idx2); + void cpumask_copy(enum cpumask_idx source, enum cpumask_idx dest); +-void cpumask_exclude_copy(enum cpumask_idx source, enum cpumask_idx dest, enum cpumask_idx exlude); ++void cpumask_exclude_copy(enum cpumask_idx source, enum cpumask_idx dest, enum cpumask_idx exclude); + +-char* get_cpus_str(enum cpumask_idx idx, bool refresh); +-char* get_cpus_hexstr(enum cpumask_idx idx, bool refresh); ++char *get_cpus_str(enum cpumask_idx idx, bool refresh); ++char *get_cpus_hexstr(enum cpumask_idx idx, bool refresh); + char *get_proc_irq_str(enum cpumask_idx idx); + char *get_irqbalance_str(enum cpumask_idx idx); + char *get_cpu_isolation_str(enum cpumask_idx idx); +@@ -448,8 +437,8 @@ int lpmd_open(const char *name, int print_level); + int lpmd_read_int(const char *name, int *val, int print_level); + int lpmd_read_yn(const char *name, int *val, int print_level); + int lpmd_write_yn(const char *name, int val, int print_level); +-char* get_time(void); ++char *get_time(void); + void time_start(void); +-char* time_delta(void); ++char *time_delta(void); + uint64_t read_msr(int cpu, uint32_t msr); + #endif +diff --git a/src/include/thermal.h b/src/include/thermal.h +index b0b2e98..e2d2eb1 100644 +--- a/src/include/thermal.h ++++ b/src/include/thermal.h +@@ -1,22 +1,5 @@ +-/* +- * thermal.c: thermal netlink event header +- * +- * Copyright (C) 2023 Intel Corporation. All rights reserved. +- * +- * This program is free software; you can redistribute it and/or modify +- * it under the terms of the GNU General Public License as published by +- * the Free Software Foundation; either version 2 of the License, or +- * (at your option) any later version. +- * +- * This program is distributed in the hope that it will be useful, +- * but WITHOUT ANY WARRANTY; without even the implied warranty of +- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +- * GNU General Public License for more details. +- * +- * You should have received a copy of the GNU General Public License +- * along with this program; if not, write to the Free Software +- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +- */ ++/* SPDX-License-Identifier: GPL-2.0 */ ++ + #ifndef _UAPI_LINUX_THERMAL_H + #define _UAPI_LINUX_THERMAL_H + +@@ -65,11 +48,13 @@ enum thermal_genl_attr { + THERMAL_GENL_ATTR_CAPACITY_CPU_EFF, + __THERMAL_GENL_ATTR_MAX, + }; ++ + #define THERMAL_GENL_ATTR_MAX (__THERMAL_GENL_ATTR_MAX - 1) + + enum thermal_genl_sampling { + THERMAL_GENL_SAMPLING_TEMP, __THERMAL_GENL_SAMPLING_MAX, + }; ++ + #define THERMAL_GENL_SAMPLING_MAX (__THERMAL_GENL_SAMPLING_MAX - 1) + + /* Events of thermal_genl_family */ +@@ -90,6 +75,7 @@ enum thermal_genl_event { + THERMAL_GENL_EVENT_CAPACITY_CHANGE, /* CPU capacity changed */ + __THERMAL_GENL_EVENT_MAX, + }; ++ + #define THERMAL_GENL_EVENT_MAX (__THERMAL_GENL_EVENT_MAX - 1) + + /* Commands supported by the thermal_genl_family */ +@@ -102,6 +88,7 @@ enum thermal_genl_cmd { + THERMAL_GENL_CMD_CDEV_GET, /* List of cdev id */ + __THERMAL_GENL_CMD_MAX, + }; ++ + #define THERMAL_GENL_CMD_MAX (__THERMAL_GENL_CMD_MAX - 1) + + #endif /* _UAPI_LINUX_THERMAL_H */ +diff --git a/src/lpmd_cgroup.c b/src/lpmd_cgroup.c +index 1dddce0..0806d0e 100644 +--- a/src/lpmd_cgroup.c ++++ b/src/lpmd_cgroup.c +@@ -1,114 +1,99 @@ +-/* +- * lpmd_cgroup.c: task isolation via cgroup setting +- * +- * Copyright (C) 2025 Intel Corporation. All rights reserved. +- * +- * This program is free software; you can redistribute it and/or modify +- * it under the terms of the GNU General Public License as published by +- * the Free Software Foundation; either version 2 of the License, or +- * (at your option) any later version. +- * +- * This program is distributed in the hope that it will be useful, +- * but WITHOUT ANY WARRANTY; without even the implied warranty of +- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +- * GNU General Public License for more details. +- * +- * You should have received a copy of the GNU General Public License +- * along with this program; if not, write to the Free Software +- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +- */ ++// SPDX-License-Identifier: GPL-2.0-or-later ++/* Copyright (C) 2026 Intel Corporation */ + + #define _GNU_SOURCE + #include + #include "lpmd.h" + + /* Support for LPM_CPU_CGROUPV2 */ +-#define PATH_CGROUP "/sys/fs/cgroup" ++#define PATH_CGROUP "/sys/fs/cgroup" + #define PATH_CG2_SUBTREE_CONTROL PATH_CGROUP "/cgroup.subtree_control" + + static int update_allowed_cpus(const char *unit, uint8_t *vals, int size) + { + sd_bus_error error = SD_BUS_ERROR_NULL; + sd_bus_message *m = NULL; +- sd_bus *bus = NULL; + char buf[MAX_STR_LENGTH]; ++ sd_bus *bus = NULL; + int offset; + int ret; + int i; + +- ret = sd_bus_open_system (&bus); ++ ret = sd_bus_open_system(&bus); + if (ret < 0) { +- fprintf (stderr, "Failed to connect to system bus: %s\n", strerror (-ret)); ++ fprintf(stderr, "Failed to connect to system bus: %s\n", strerror(-ret)); + goto finish; + } + +- ret = sd_bus_message_new_method_call (bus, &m, "org.freedesktop.systemd1", "/org/freedesktop/systemd1", +- "org.freedesktop.systemd1.Manager", "SetUnitProperties"); ++ ret = sd_bus_message_new_method_call(bus, &m, "org.freedesktop.systemd1", "/org/freedesktop/systemd1", ++ "org.freedesktop.systemd1.Manager", "SetUnitProperties"); + if (ret < 0) { +- fprintf (stderr, "Failed to issue method call: %s\n", error.message); ++ fprintf(stderr, "Failed to issue method call: %s\n", error.message); + goto finish; + } + +- ret = sd_bus_message_append (m, "sb", unit, 1); ++ ret = sd_bus_message_append(m, "sb", unit, 1); + if (ret < 0) { +- fprintf (stderr, "Failed to append unit: %s\n", error.message); ++ fprintf(stderr, "Failed to append unit: %s\n", error.message); + goto finish; + } + +- ret = sd_bus_message_open_container (m, SD_BUS_TYPE_ARRAY, "(sv)"); ++ ret = sd_bus_message_open_container(m, SD_BUS_TYPE_ARRAY, "(sv)"); + if (ret < 0) { +- fprintf (stderr, "Failed to append array: %s\n", error.message); ++ fprintf(stderr, "Failed to append array: %s\n", error.message); + goto finish; + } + +- ret = sd_bus_message_open_container (m, SD_BUS_TYPE_STRUCT, "sv"); ++ ret = sd_bus_message_open_container(m, SD_BUS_TYPE_STRUCT, "sv"); + if (ret < 0) { +- fprintf (stderr, "Failed to open container struct: %s\n", error.message); ++ fprintf(stderr, "Failed to open container struct: %s\n", error.message); + goto finish; + } + +- ret = sd_bus_message_append_basic (m, SD_BUS_TYPE_STRING, "AllowedCPUs"); ++ ret = sd_bus_message_append_basic(m, SD_BUS_TYPE_STRING, "AllowedCPUs"); + if (ret < 0) { +- fprintf (stderr, "Failed to append string: %s\n", error.message); ++ fprintf(stderr, "Failed to append string: %s\n", error.message); + goto finish_1; + } + +- ret = sd_bus_message_open_container (m, 'v', "ay"); ++ ret = sd_bus_message_open_container(m, 'v', "ay"); + if (ret < 0) { +- fprintf (stderr, "Failed to open container: %s\n", error.message); ++ fprintf(stderr, "Failed to open container: %s\n", error.message); + goto finish_2; + } + +- ret = sd_bus_message_append_array (m, 'y', vals, size); ++ ret = sd_bus_message_append_array(m, 'y', vals, size); + if (ret < 0) { +- fprintf (stderr, "Failed to append allowed_cpus: %s\n", error.message); ++ fprintf(stderr, "Failed to append allowed_cpus: %s\n", error.message); + goto finish_2; + } + +- offset = snprintf (buf, MAX_STR_LENGTH, "\tSending Dbus message to systemd: %s: ", unit); ++ offset = snprintf(buf, MAX_STR_LENGTH, "\tSending Dbus message to systemd: %s: ", unit); + for (i = 0; i < size; i++) { + if (offset < MAX_STR_LENGTH) +- offset += snprintf (buf + offset, MAX_STR_LENGTH - offset, "0x%02x ", vals[i]); ++ offset += snprintf(buf + offset, MAX_STR_LENGTH - offset, "0x%02x ", vals[i]); + } + buf[MAX_STR_LENGTH - 1] = '\0'; +- lpmd_log_info ("%s\n", buf); ++ lpmd_log_info("%s\n", buf); + +- sd_bus_message_close_container (m); ++ sd_bus_message_close_container(m); + +-finish_2: sd_bus_message_close_container (m); ++finish_2: ++ sd_bus_message_close_container(m); + +-finish_1: sd_bus_message_close_container (m); ++finish_1: ++ sd_bus_message_close_container(m); + +-finish: if (ret >= 0) { +- ret = sd_bus_call (bus, m, 0, &error, NULL); +- if (ret < 0) { +- fprintf (stderr, "Failed to call: %s\n", error.message); +- } ++finish: ++ if (ret >= 0) { ++ ret = sd_bus_call(bus, m, 0, &error, NULL); ++ if (ret < 0) ++ fprintf(stderr, "Failed to call: %s\n", error.message); + } + +- sd_bus_error_free (&error); +- sd_bus_message_unref (m); +- sd_bus_unref (bus); ++ sd_bus_error_free(&error); ++ sd_bus_message_unref(m); ++ sd_bus_unref(bus); + + return ret < 0 ? -1 : 0; + } +@@ -122,14 +107,14 @@ static int restore_systemd_cgroup(void) + if (!vals) + return -1; + +- update_allowed_cpus ("system.slice", vals, size); +- update_allowed_cpus ("user.slice", vals, size); +- update_allowed_cpus ("machine.slice", vals, size); ++ update_allowed_cpus("system.slice", vals, size); ++ update_allowed_cpus("user.slice", vals, size); ++ update_allowed_cpus("machine.slice", vals, size); + + return 0; + } + +-static int update_systemd_cgroup(lpmd_config_state_t *state) ++static int update_systemd_cgroup(struct lpmd_config_state_t *state) + { + int size = get_max_cpus() / 8; + uint8_t *vals; +@@ -139,54 +124,54 @@ static int update_systemd_cgroup(lpmd_config_state_t *state) + if (!vals) + return -1; + +- ret = update_allowed_cpus ("system.slice", vals, size); ++ ret = update_allowed_cpus("system.slice", vals, size); + if (ret) + goto restore; + +- ret = update_allowed_cpus ("user.slice", vals, size); ++ ret = update_allowed_cpus("user.slice", vals, size); + if (ret) + goto restore; + +- ret = update_allowed_cpus ("machine.slice", vals, size); ++ ret = update_allowed_cpus("machine.slice", vals, size); + if (ret) + goto restore; + + return 0; + + restore: +- restore_systemd_cgroup (); ++ restore_systemd_cgroup(); + return ret; + } + +-static int process_cpu_cgroupv2(lpmd_config_state_t *state) ++static int process_cpu_cgroupv2(struct lpmd_config_state_t *state) + { + if (cpumask_equal(state->cpumask_idx, CPUMASK_ONLINE)) { +- restore_systemd_cgroup (); +- return lpmd_write_str (PATH_CG2_SUBTREE_CONTROL, "-cpuset", LPMD_LOG_DEBUG); +- } else { +- if (lpmd_write_str (PATH_CG2_SUBTREE_CONTROL, "+cpuset", LPMD_LOG_DEBUG)) +- return 1; +- return update_systemd_cgroup(state); ++ restore_systemd_cgroup(); ++ return lpmd_write_str(PATH_CG2_SUBTREE_CONTROL, "-cpuset", LPMD_LOG_DEBUG); + } ++ ++ if (lpmd_write_str(PATH_CG2_SUBTREE_CONTROL, "+cpuset", LPMD_LOG_DEBUG)) ++ return 1; ++ return update_systemd_cgroup(state); + } + + static enum cpumask_idx last_applied_cpumask = CPUMASK_NONE; + + /* Support for cgroup based cpu isolation */ +-static int process_cpu_isolate(lpmd_config_state_t *state) ++static int process_cpu_isolate(struct lpmd_config_state_t *state) + { +- if (lpmd_write_str ("/sys/fs/cgroup/lpm/cpuset.cpus.partition", "member", LPMD_LOG_DEBUG)) ++ if (lpmd_write_str("/sys/fs/cgroup/lpm/cpuset.cpus.partition", "member", LPMD_LOG_DEBUG)) + return 1; + + if (!cpumask_equal(state->cpumask_idx, CPUMASK_ONLINE)) { +- if (lpmd_write_str ("/sys/fs/cgroup/lpm/cpuset.cpus.exclusive", get_cpu_isolation_str(state->cpumask_idx), LPMD_LOG_DEBUG)) ++ if (lpmd_write_str("/sys/fs/cgroup/lpm/cpuset.cpus.exclusive", get_cpu_isolation_str(state->cpumask_idx), LPMD_LOG_DEBUG)) + return 1; +- if (lpmd_write_str ("/sys/fs/cgroup/lpm/cpuset.cpus.partition", "isolated", LPMD_LOG_DEBUG)) ++ if (lpmd_write_str("/sys/fs/cgroup/lpm/cpuset.cpus.partition", "isolated", LPMD_LOG_DEBUG)) + return 1; +- if (lpmd_write_str ("/sys/fs/cgroup/lpm/cpuset.cpus", get_cpu_isolation_str(state->cpumask_idx), LPMD_LOG_DEBUG)) ++ if (lpmd_write_str("/sys/fs/cgroup/lpm/cpuset.cpus", get_cpu_isolation_str(state->cpumask_idx), LPMD_LOG_DEBUG)) + return 1; + } else { +- if (lpmd_write_str ("/sys/fs/cgroup/lpm/cpuset.cpus", get_cpu_isolation_str(CPUMASK_ONLINE), LPMD_LOG_DEBUG)) ++ if (lpmd_write_str("/sys/fs/cgroup/lpm/cpuset.cpus", get_cpu_isolation_str(CPUMASK_ONLINE), LPMD_LOG_DEBUG)) + return 1; + } + +@@ -207,21 +192,21 @@ int cgroup_cleanup(void) + return 0; + } + +-int cgroup_init(lpmd_config_t *config) ++int cgroup_init(struct lpmd_config_t *config) + { +- if (lpmd_write_str (PATH_CG2_SUBTREE_CONTROL, "+cpuset", LPMD_LOG_DEBUG)) ++ if (lpmd_write_str(PATH_CG2_SUBTREE_CONTROL, "+cpuset", LPMD_LOG_DEBUG)) + return 1; + if (config->mode == LPM_CPU_ISOLATE) +- return mkdir ("/sys/fs/cgroup/lpm", 0744); ++ return mkdir("/sys/fs/cgroup/lpm", 0744); + return 0; + } + +-int process_cgroup(lpmd_config_state_t *state, enum lpm_cpu_process_mode mode) ++int process_cgroup(struct lpmd_config_state_t *state, enum lpm_cpu_process_mode mode) + { + int ret; + + if (state->cpumask_idx == CPUMASK_NONE) { +- lpmd_log_debug ("Ignore cgroup processing\n"); ++ lpmd_log_debug("Ignore cgroup processing\n"); + return 0; + } + +diff --git a/src/lpmd_config.c b/src/lpmd_config.c +index cfeb910..b6ae995 100644 +--- a/src/lpmd_config.c ++++ b/src/lpmd_config.c +@@ -1,22 +1,5 @@ +-/* +- * lpmd_config.c: xml config file parser +- * +- * Copyright (C) 2023 Intel Corporation. All rights reserved. +- * +- * This program is free software; you can redistribute it and/or modify +- * it under the terms of the GNU General Public License as published by +- * the Free Software Foundation; either version 2 of the License, or +- * (at your option) any later version. +- * +- * This program is distributed in the hope that it will be useful, +- * but WITHOUT ANY WARRANTY; without even the implied warranty of +- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +- * GNU General Public License for more details. +- * +- * You should have received a copy of the GNU General Public License +- * along with this program; if not, write to the Free Software +- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +- */ ++// SPDX-License-Identifier: GPL-2.0-or-later ++/* Copyright (C) 2026 Intel Corporation */ + + #include "lpmd.h" + #include +@@ -25,7 +8,7 @@ + #define CONFIG_FILE_NAME "intel_lpmd_config.xml" + + static int validate_slider_value(int value, const char *param_name, int state_id, +- int min_val, int max_val) ++ int min_val, int max_val) + { + /* -1 is a special value meaning "ignore/disable" */ + if (value == -1) +@@ -68,13 +51,12 @@ static int read_slider_and_validate(int *dest_ptr, const char *src_value, + + /* Check for parsing errors */ + if (errno == ERANGE || endptr == src_value) { +- if (state_id >= 0) { ++ if (state_id >= 0) + lpmd_log_error("Failed to parse %s value: '%s' is not a valid integer in state ID %d\n", + param_name, src_value, state_id); +- } else { ++ else + lpmd_log_error("Failed to parse %s value: '%s' is not a valid integer\n", + param_name, src_value); +- } + return LPMD_ERROR; + } + +@@ -82,12 +64,12 @@ static int read_slider_and_validate(int *dest_ptr, const char *src_value, + switch (type) { + case SLIDER_TYPE_OFFSET: + if (validate_slider_value(value, param_name, state_id, +- SLIDER_OFFSET_MIN, SLIDER_OFFSET_MAX) != LPMD_SUCCESS) ++ SLIDER_OFFSET_MIN, SLIDER_OFFSET_MAX) != LPMD_SUCCESS) + return LPMD_ERROR; + break; + case SLIDER_TYPE_BALANCE: + if (validate_slider_value(value, param_name, state_id, +- SLIDER_BALANCE_MIN, SLIDER_BALANCE_MAX) != LPMD_SUCCESS) ++ SLIDER_BALANCE_MIN, SLIDER_BALANCE_MAX) != LPMD_SUCCESS) + return LPMD_ERROR; + break; + default: +@@ -100,90 +82,90 @@ static int read_slider_and_validate(int *dest_ptr, const char *src_value, + return LPMD_SUCCESS; + } + +-static void save_string_or_zero(char * tmp_value, char * dst_string, int dest_size) ++static void save_string_or_zero(char *tmp_value, char *dst_string, int dest_size) + { +- if (!strncmp (tmp_value, "-1", strlen ("-1"))) ++ if (!strncmp(tmp_value, "-1", strlen("-1"))) + dst_string[0] = '\0'; + else + copy_user_string(tmp_value, dst_string, dest_size); + } + +-static void lpmd_parse_state(xmlDoc *doc, xmlNode *a_node, lpmd_config_t *config, int idx) ++static void lpmd_parse_state(xmlDoc *doc, xmlNode *a_node, struct lpmd_config_t *config, int idx) + { ++ struct lpmd_config_state_t *state = &config->config_states[idx]; + xmlNode *cur_node = NULL; + char *tmp_value; +- char *pos; + int ret = 0; +- lpmd_config_state_t *state = &config->config_states[idx]; ++ char *pos; + + if (!doc || !a_node || !state) + return; + +- lpmd_log_debug("lpmd_parse_state: %d\n", idx); ++ lpmd_log_debug("%s: %d\n", __func__, idx); + lpmd_init_config_state(state); + + for (cur_node = a_node; cur_node; cur_node = cur_node->next) { + if (cur_node->type != XML_ELEMENT_NODE) + continue; + +- tmp_value = (char*) xmlNodeListGetString (doc, cur_node->xmlChildrenNode, 1); ++ tmp_value = (char *)xmlNodeListGetString(doc, cur_node->xmlChildrenNode, 1); + + if (!tmp_value) + continue; + +- if (!strncmp((const char*)cur_node->name, "ID", strlen("ID"))) +- state->id = strtol (tmp_value, &pos, 10); +- if (!strncmp((const char*)cur_node->name, "Name", strlen("Name"))) { ++ if (!strncmp((const char *)cur_node->name, "ID", strlen("ID"))) ++ state->id = strtol(tmp_value, &pos, 10); ++ if (!strncmp((const char *)cur_node->name, "Name", strlen("Name"))) { + snprintf(state->name, MAX_STATE_NAME - 1, "%s", tmp_value); + state->name[MAX_STATE_NAME - 1] = '\0'; + } +- if (!strncmp((const char*)cur_node->name, "WLTTypeMask", strlen("WLTTypeMask"))) +- state->wlt_type_mask = strtol (tmp_value, &pos, 10); +- else if (!strncmp((const char*)cur_node->name, "WLTType", strlen("WLTType"))) +- state->wlt_type = strtol (tmp_value, &pos, 10); +- if (!strncmp((const char*)cur_node->name, "EntrySystemLoadThres", strlen("EntrySystemLoadThres"))) +- state->entry_system_load_thres = strtol (tmp_value, &pos, 10); +- if (!strncmp((const char*)cur_node->name, "ExitSystemLoadThres", strlen("ExitSystemLoadThres"))) +- state->exit_system_load_thres = strtol (tmp_value, &pos, 10); +- if (!strncmp((const char*)cur_node->name, "ExitSystemLoadhysteresis", strlen("ExitSystemLoadhysteresis"))) +- state->exit_system_load_hyst = strtol (tmp_value, &pos, 10); +- if (!strncmp((const char*)cur_node->name, "EnterCPULoadThres", strlen("EnterCPULoadThres"))) +- state->enter_cpu_load_thres = strtol (tmp_value, &pos, 10); +- if (!strncmp((const char*)cur_node->name, "ExitCPULoadThres", strlen("ExitCPULoadThres"))) +- state->exit_cpu_load_thres = strtol (tmp_value, &pos, 10); +- if (!strncmp((const char*)cur_node->name, "EnterGFXLoadThres", strlen("EnterGFXLoadThres"))) +- state->enter_gfx_load_thres = strtol (tmp_value, &pos, 10); +- if (!strncmp((const char*)cur_node->name, "ExitGFXLoadThres", strlen("ExitGFXLoadThres"))) +- state->exit_gfx_load_thres = strtol (tmp_value, &pos, 10); +- if (!strncmp((const char*)cur_node->name, "MinPollInterval", strlen("MinPollInterval"))) +- state->min_poll_interval = strtol (tmp_value, &pos, 10); +- if (!strncmp((const char*)cur_node->name, "MaxPollInterval", strlen("MaxPollInterval"))) +- state->max_poll_interval = strtol (tmp_value, &pos, 10); +- if (!strncmp((const char*)cur_node->name, "PollIntervalIncrement", strlen("PollIntervalIncrement"))) +- state->poll_interval_increment = strtol (tmp_value, &pos, 10); +- if (!strncmp((const char*)cur_node->name, "EPP", strlen("EPP"))) +- state->epp = strtol (tmp_value, &pos, 10); +- if (!strncmp((const char*)cur_node->name, "EPB", strlen("EPB"))) +- state->epb = strtol (tmp_value, &pos, 10); +- if (!strncmp((const char*)cur_node->name, "ITMTState", strlen("ITMTState"))) +- state->itmt_state = strtol (tmp_value, &pos, 10); +- if (!strncmp((const char*)cur_node->name, "IRQMigrate", strlen("IRQMigrate"))) +- state->irq_migrate = strtol (tmp_value, &pos, 10); +- if (!strncmp((const char*)cur_node->name, "ActivePcores", strlen("ActivePcores"))) ++ if (!strncmp((const char *)cur_node->name, "WLTTypeMask", strlen("WLTTypeMask"))) ++ state->wlt_type_mask = strtol(tmp_value, &pos, 10); ++ else if (!strncmp((const char *)cur_node->name, "WLTType", strlen("WLTType"))) ++ state->wlt_type = strtol(tmp_value, &pos, 10); ++ if (!strncmp((const char *)cur_node->name, "EntrySystemLoadThres", strlen("EntrySystemLoadThres"))) ++ state->entry_system_load_thres = strtol(tmp_value, &pos, 10); ++ if (!strncmp((const char *)cur_node->name, "ExitSystemLoadThres", strlen("ExitSystemLoadThres"))) ++ state->exit_system_load_thres = strtol(tmp_value, &pos, 10); ++ if (!strncmp((const char *)cur_node->name, "ExitSystemLoadhysteresis", strlen("ExitSystemLoadhysteresis"))) ++ state->exit_system_load_hyst = strtol(tmp_value, &pos, 10); ++ if (!strncmp((const char *)cur_node->name, "EnterCPULoadThres", strlen("EnterCPULoadThres"))) ++ state->enter_cpu_load_thres = strtol(tmp_value, &pos, 10); ++ if (!strncmp((const char *)cur_node->name, "ExitCPULoadThres", strlen("ExitCPULoadThres"))) ++ state->exit_cpu_load_thres = strtol(tmp_value, &pos, 10); ++ if (!strncmp((const char *)cur_node->name, "EnterGFXLoadThres", strlen("EnterGFXLoadThres"))) ++ state->enter_gfx_load_thres = strtol(tmp_value, &pos, 10); ++ if (!strncmp((const char *)cur_node->name, "ExitGFXLoadThres", strlen("ExitGFXLoadThres"))) ++ state->exit_gfx_load_thres = strtol(tmp_value, &pos, 10); ++ if (!strncmp((const char *)cur_node->name, "MinPollInterval", strlen("MinPollInterval"))) ++ state->min_poll_interval = strtol(tmp_value, &pos, 10); ++ if (!strncmp((const char *)cur_node->name, "MaxPollInterval", strlen("MaxPollInterval"))) ++ state->max_poll_interval = strtol(tmp_value, &pos, 10); ++ if (!strncmp((const char *)cur_node->name, "PollIntervalIncrement", strlen("PollIntervalIncrement"))) ++ state->poll_interval_increment = strtol(tmp_value, &pos, 10); ++ if (!strncmp((const char *)cur_node->name, "EPP", strlen("EPP"))) ++ state->epp = strtol(tmp_value, &pos, 10); ++ if (!strncmp((const char *)cur_node->name, "EPB", strlen("EPB"))) ++ state->epb = strtol(tmp_value, &pos, 10); ++ if (!strncmp((const char *)cur_node->name, "ITMTState", strlen("ITMTState"))) ++ state->itmt_state = strtol(tmp_value, &pos, 10); ++ if (!strncmp((const char *)cur_node->name, "IRQMigrate", strlen("IRQMigrate"))) ++ state->irq_migrate = strtol(tmp_value, &pos, 10); ++ if (!strncmp((const char *)cur_node->name, "ActivePcores", strlen("ActivePcores"))) + save_string_or_zero(tmp_value, state->active_p_cores, sizeof(state->active_p_cores)); +- if (!strncmp((const char*)cur_node->name, "ActiveEcores", strlen("ActiveEcores"))) ++ if (!strncmp((const char *)cur_node->name, "ActiveEcores", strlen("ActiveEcores"))) + save_string_or_zero(tmp_value, state->active_e_cores, sizeof(state->active_e_cores)); +- if (!strncmp((const char*)cur_node->name, "ActiveLcores", strlen("ActiveLcores"))) ++ if (!strncmp((const char *)cur_node->name, "ActiveLcores", strlen("ActiveLcores"))) + save_string_or_zero(tmp_value, state->active_l_cores, sizeof(state->active_l_cores)); +- if (!strncmp((const char*)cur_node->name, "ActiveCPUs", strlen("ActiveCPUs"))) ++ if (!strncmp((const char *)cur_node->name, "ActiveCPUs", strlen("ActiveCPUs"))) + save_string_or_zero(tmp_value, state->active_cpus, sizeof(state->active_cpus)); +- if (!strncmp((const char*)cur_node->name, "BalanceSliderAC", strlen("BalanceSliderAC"))) ++ if (!strncmp((const char *)cur_node->name, "BalanceSliderAC", strlen("BalanceSliderAC"))) + ret = read_slider_and_validate(&state->balance_slider_ac, tmp_value, "BalanceSliderAC", state->id, SLIDER_TYPE_BALANCE); +- if (!strncmp((const char*)cur_node->name, "SliderOffsetAC", strlen("SliderOffsetAC"))) ++ if (!strncmp((const char *)cur_node->name, "SliderOffsetAC", strlen("SliderOffsetAC"))) + ret = read_slider_and_validate(&state->slider_offset_ac, tmp_value, "SliderOffsetAC", state->id, SLIDER_TYPE_OFFSET); +- if (!strncmp((const char*)cur_node->name, "BalanceSliderDC", strlen("BalanceSliderDC"))) ++ if (!strncmp((const char *)cur_node->name, "BalanceSliderDC", strlen("BalanceSliderDC"))) + ret = read_slider_and_validate(&state->balance_slider_dc, tmp_value, "BalanceSliderDC", state->id, SLIDER_TYPE_BALANCE); +- if (!strncmp((const char*)cur_node->name, "SliderOffsetDC", strlen("SliderOffsetDC"))) ++ if (!strncmp((const char *)cur_node->name, "SliderOffsetDC", strlen("SliderOffsetDC"))) + ret = read_slider_and_validate(&state->slider_offset_dc, tmp_value, "SliderOffsetDC", state->id, SLIDER_TYPE_OFFSET); + + xmlFree(tmp_value); +@@ -204,14 +186,13 @@ int is_wildcard(char *str) + return 0; + } + +-static void lpmd_parse_states(xmlDoc *doc, xmlNode *a_node, lpmd_config_t *lpmd_config) ++static void lpmd_parse_states(xmlDoc *doc, xmlNode *a_node, struct lpmd_config_t *lpmd_config) + { ++ int cpu_family = -1, cpu_model = -1, config_state_count = 0; ++ char cpu_config[MAX_CONFIG_LEN]; + xmlNode *cur_node = NULL; + char *tmp_value; + char *pos; +- int config_state_count = 0; +- int cpu_family = -1, cpu_model = -1; +- char cpu_config[MAX_CONFIG_LEN]; + + if (!doc || !a_node || !lpmd_config) + return; +@@ -223,59 +204,66 @@ static void lpmd_parse_states(xmlDoc *doc, xmlNode *a_node, lpmd_config_t *lpmd_ + cpu_config[0] = '\0'; + + for (cur_node = a_node; cur_node; cur_node = cur_node->next) { +- if (cur_node->type == XML_ELEMENT_NODE) { +- if (cur_node->name) { +- +- tmp_value = (char*) xmlNodeListGetString (doc, cur_node->xmlChildrenNode, 1); +- if (!strncmp ((const char*) cur_node->name, "CPUFamily", strlen ("CPUFamily"))) { +- if (is_wildcard(tmp_value)) +- cpu_family = lpmd_config->cpu_family; +- else +- cpu_family = strtol (tmp_value, &pos, 10); +- } +- +- if (!strncmp ((const char*) cur_node->name, "CPUModel", strlen ("CPUModel"))) { +- if (is_wildcard(tmp_value)) +- cpu_model = lpmd_config->cpu_model; +- else +- cpu_model = strtol (tmp_value, &pos, 10); +- } +- +- if (!strncmp ((const char*) cur_node->name, "CPUConfig", strlen ("CPUConfig"))) { +- if (is_wildcard(tmp_value)) { +- strncpy(cpu_config, lpmd_config->cpu_config, MAX_CONFIG_LEN); +- } else { +- snprintf (cpu_config, MAX_CONFIG_LEN - 1, "%s", tmp_value); +- } +- cpu_config[MAX_CONFIG_LEN - 1] = '\0'; +- } +- +- if (tmp_value) +- xmlFree (tmp_value); +- +- if (strncmp ((const char*) cur_node->name, "State", strlen ("State"))) +- continue; +- +- /* Must check cpu family/model/config first to make sure the states applies */ +- if (cpu_family != lpmd_config->cpu_family || cpu_model != lpmd_config->cpu_model || strncmp(cpu_config, lpmd_config->cpu_config, MAX_CONFIG_LEN)) { +- lpmd_log_info("Ignore unsupported states for CPU family:%d,model%d,config:%s\n", cpu_family, cpu_model, cpu_config); +- return; +- } +- +- if (lpmd_config->config_state_count >= MAX_CONFIG_STATES) +- break; +- lpmd_parse_state (doc, cur_node->children, lpmd_config, CONFIG_STATE_BASE + config_state_count); +- config_state_count ++; +- } ++ if (cur_node->type != XML_ELEMENT_NODE) ++ continue; ++ ++ if (!cur_node->name) ++ continue; ++ ++ tmp_value = (char *)xmlNodeListGetString(doc, cur_node->xmlChildrenNode, 1); ++ if (!strncmp((const char *)cur_node->name, "CPUFamily", strlen("CPUFamily"))) { ++ if (is_wildcard(tmp_value)) ++ cpu_family = lpmd_config->cpu_family; ++ else ++ cpu_family = strtol(tmp_value, &pos, 10); ++ } ++ ++ if (!strncmp((const char *)cur_node->name, "CPUModel", strlen("CPUModel"))) { ++ if (is_wildcard(tmp_value)) ++ cpu_model = lpmd_config->cpu_model; ++ else ++ cpu_model = strtol(tmp_value, &pos, 10); ++ } ++ ++ if (!strncmp((const char *)cur_node->name, "CPUConfig", strlen("CPUConfig"))) { ++ if (is_wildcard(tmp_value)) ++ strncpy(cpu_config, lpmd_config->cpu_config, MAX_CONFIG_LEN); ++ else ++ snprintf(cpu_config, MAX_CONFIG_LEN - 1, "%s", tmp_value); ++ cpu_config[MAX_CONFIG_LEN - 1] = '\0'; ++ } ++ ++ if (tmp_value) ++ xmlFree(tmp_value); ++ ++ if (strncmp((const char *)cur_node->name, "State", strlen("State"))) ++ continue; ++ ++ /* Must check cpu family/model/config first to make sure the states applies */ ++ if (cpu_family != lpmd_config->cpu_family || ++ cpu_model != lpmd_config->cpu_model || ++ strncmp(cpu_config, lpmd_config->cpu_config, ++ MAX_CONFIG_LEN)) { ++ lpmd_log_info("Ignore unsupported states for CPU family:%d,model%d,config:%s\n", ++ cpu_family, cpu_model, cpu_config); ++ return; + } ++ ++ if (lpmd_config->config_state_count >= MAX_CONFIG_STATES) ++ break; ++ lpmd_parse_state(doc, cur_node->children, lpmd_config, ++ CONFIG_STATE_BASE + config_state_count); ++ config_state_count++; + } + lpmd_log_debug("Found %d config states\n", config_state_count); + lpmd_config->config_state_count = config_state_count; + } + +-static void lpmd_init_config(lpmd_config_t *config) ++static void lpmd_init_config(struct lpmd_config_t *config) + { +- config->performance_def = config->balanced_def = config->powersaver_def = LPM_FORCE_OFF; ++ config->performance_def = LPM_FORCE_OFF; ++ config->balanced_def = LPM_FORCE_OFF; ++ config->powersaver_def = LPM_FORCE_OFF; + config->lp_mode_epp = -1; + config->data.util_sys = -1; + config->data.util_cpu = -1; +@@ -289,7 +277,7 @@ static void lpmd_init_config(lpmd_config_t *config) + config->wlt_notification_delay = -1; + } + +-static int lpmd_fill_config(xmlDoc *doc, xmlNode *a_node, lpmd_config_t *lpmd_config) ++static int lpmd_fill_config(xmlDoc *doc, xmlNode *a_node, struct lpmd_config_t *lpmd_config) + { + xmlNode *cur_node = NULL; + char *tmp_value; +@@ -302,210 +290,212 @@ static int lpmd_fill_config(xmlDoc *doc, xmlNode *a_node, lpmd_config_t *lpmd_co + lpmd_init_config(lpmd_config); + + for (cur_node = a_node; cur_node; cur_node = cur_node->next) { +- if (cur_node->type == XML_ELEMENT_NODE) { +- tmp_value = (char*) xmlNodeListGetString (doc, cur_node->xmlChildrenNode, 1); +- if (tmp_value) { +- if (!strncmp((const char*)cur_node->name, "Mode", strlen("Mode"))) { +- errno = 0; +- lpmd_config->mode = strtol (tmp_value, &pos, 10); +- if (errno || *pos != '\0' || lpmd_config->mode > LPM_CPU_MODE_MAX +- || lpmd_config->mode < 0) +- goto err; +- } +- else if (!strncmp((const char*)cur_node->name, "HfiLpmEnable", strlen("HfiLpmEnable"))) { +- errno = 0; +- lpmd_config->hfi_lpm_enable = strtol (tmp_value, &pos, 10); +- if (errno || *pos != '\0' +- || (lpmd_config->hfi_lpm_enable != 1 && lpmd_config->hfi_lpm_enable != 0)) +- goto err; +- } +- else if (!strncmp((const char*)cur_node->name, "WLTHintEnable", strlen("WLtHintEnable"))) { +- errno = 0; +- lpmd_config->wlt_hint_enable = strtol (tmp_value, &pos, 10); +- if (errno || *pos != '\0' +- || (lpmd_config->wlt_hint_enable != 1 && lpmd_config->wlt_hint_enable != 0)) +- goto err; +- } +- else if (!strncmp((const char*)cur_node->name, "WLTHintNotificationDelay", strlen("WLTHintNotificationDelay"))) { +- errno = 0; +- lpmd_config->wlt_notification_delay = strtol (tmp_value, &pos, 10); +- if (errno || *pos != '\0' || lpmd_config->wlt_notification_delay < 0) +- goto err; +- } +- else if (!strncmp((const char*)cur_node->name, "WLTHintMask", strlen("WLTHintMask"))) { +- errno = 0; +- lpmd_config->wlt_hint_mask = strtol (tmp_value, &pos, 10); +- } +- else if (!strncmp((const char*)cur_node->name, "WLTHintPollEnable", strlen("WLtHintPollEnable"))) { +- errno = 0; +- lpmd_config->wlt_hint_poll_enable = strtol (tmp_value, &pos, 10); +- if (errno || *pos != '\0' +- || (lpmd_config->wlt_hint_poll_enable != 1 && lpmd_config->wlt_hint_poll_enable != 0)) +- goto err; +- } +- else if (!strncmp((const char*)cur_node->name, "WLTProxyEnable", strlen("WLTProxyEnable"))) { +- errno = 0; +- lpmd_config->wlt_proxy_enable = strtol (tmp_value, &pos, 10); +- if (errno || *pos != '\0' +- || (lpmd_config->wlt_proxy_enable != 1 && lpmd_config->wlt_proxy_enable != 0)) +- goto err; +- } +- else if (!strncmp((const char*)cur_node->name, "EntryDelayMS", strlen ("EntryDelayMS"))) { +- errno = 0; +- lpmd_config->util_entry_delay = strtol (tmp_value, &pos, 10); +- if (errno +- || *pos +- != '\0'|| lpmd_config->util_entry_delay < 0 || lpmd_config->util_entry_delay > UTIL_DELAY_MAX) +- goto err; +- } +- else if (!strncmp((const char*)cur_node->name, "ExitDelayMS", strlen ("ExitDelayMS"))) { +- errno = 0; +- lpmd_config->util_exit_delay = strtol (tmp_value, &pos, 10); +- if (errno +- || *pos +- != '\0'|| lpmd_config->util_exit_delay < 0 || lpmd_config->util_exit_delay > UTIL_DELAY_MAX) +- goto err; +- } +- else if (!strncmp((const char*)cur_node->name, "util_entry_threshold", +- strlen ("util_entry_threshold"))) { +- errno = 0; +- lpmd_config->util_entry_threshold = strtol (tmp_value, &pos, 10); +- if (errno || *pos != '\0' || lpmd_config->util_entry_threshold < 0 +- || lpmd_config->util_entry_threshold > 100) +- goto err; +- } +- else if (!strncmp((const char*)cur_node->name, "util_exit_threshold", +- strlen ("util_exit_threshold"))) { +- errno = 0; +- lpmd_config->util_exit_threshold = strtol (tmp_value, &pos, 10); +- if (errno || *pos != '\0' || lpmd_config->util_exit_threshold < 0 +- || lpmd_config->util_exit_threshold > 100) +- goto err; +- } +- else if (!strncmp((const char*)cur_node->name, "EntryHystMS", strlen ("EntryHystMS"))) { +- errno = 0; +- lpmd_config->util_entry_hyst = strtol (tmp_value, &pos, 10); +- if (errno +- || *pos +- != '\0'|| lpmd_config->util_entry_hyst < 0 || lpmd_config->util_entry_hyst > UTIL_HYST_MAX) +- goto err; +- } +- else if (!strncmp((const char*)cur_node->name, "ExitHystMS", strlen ("ExitHystMS"))) { +- errno = 0; +- lpmd_config->util_exit_hyst = strtol (tmp_value, &pos, 10); +- if (errno +- || *pos +- != '\0'|| lpmd_config->util_exit_hyst < 0 || lpmd_config->util_exit_hyst > UTIL_HYST_MAX) +- goto err; +- } +- else if (!strncmp((const char*)cur_node->name, "lp_mode_epp", strlen ("lp_mode_epp"))) { +- errno = 0; +- lpmd_config->lp_mode_epp = strtol (tmp_value, &pos, 10); +- if (errno +- || *pos +- != '\0'|| lpmd_config->lp_mode_epp > 255 || lpmd_config->lp_mode_epp < -1) +- goto err; +- if (lpmd_config->lp_mode_epp < 0) +- lpmd_config->lp_mode_epp = -1; +- } +- else if (!strncmp((const char*)cur_node->name, "IgnoreITMT", strlen ("IgnoreITMT"))) { +- errno = 0; +- lpmd_config->ignore_itmt = strtol (tmp_value, &pos, 10); +- if (errno +- || *pos +- != '\0'|| lpmd_config->ignore_itmt < 0 || lpmd_config->ignore_itmt > 1) +- goto err; +- } +- else if (!strncmp((const char*)cur_node->name, "lp_mode_cpus", strlen ("lp_mode_cpus"))) { +- if (!strncmp (tmp_value, "-1", strlen ("-1"))) +- lpmd_config->lp_mode_cpus[0] = '\0'; +- else +- copy_user_string(tmp_value, lpmd_config->lp_mode_cpus, sizeof(lpmd_config->lp_mode_cpus)); +- } +- else if (!strncmp((const char*)cur_node->name, "PerformanceDef", strlen ("PerformanceDef"))) { +- errno = 0; +- lpmd_config->performance_def = strtol (tmp_value, &pos, 10); +- if (errno || *pos != '\0') +- goto err; +- if (lpmd_config->performance_def == -1) +- lpmd_config->performance_def = LPM_FORCE_OFF; +- else if (lpmd_config->performance_def == 1) +- lpmd_config->performance_def = LPM_FORCE_ON; +- else if (!lpmd_config->performance_def) +- lpmd_config->performance_def = LPM_AUTO; +- else +- goto err; +- } +- else if (!strncmp((const char*)cur_node->name, "BalancedDef", strlen ("BalancedDef"))) { +- errno = 0; +- lpmd_config->balanced_def = strtol (tmp_value, &pos, 10); +- if (errno || *pos != '\0') +- goto err; +- if (lpmd_config->balanced_def == -1) +- lpmd_config->balanced_def = LPM_FORCE_OFF; +- else if (lpmd_config->balanced_def == 1) +- lpmd_config->balanced_def = LPM_FORCE_ON; +- else if (!lpmd_config->balanced_def) +- lpmd_config->balanced_def = LPM_AUTO; +- else +- goto err; +- } +- else if (!strncmp((const char*)cur_node->name, "PowersaverDef", strlen ("PowersaverDef"))) { +- errno = 0; +- lpmd_config->powersaver_def = strtol (tmp_value, &pos, 10); +- if (errno || *pos != '\0') +- goto err; +- if (lpmd_config->powersaver_def == -1) +- lpmd_config->powersaver_def = LPM_FORCE_OFF; +- else if (lpmd_config->powersaver_def == 1) +- lpmd_config->powersaver_def = LPM_FORCE_ON; +- else if (!lpmd_config->powersaver_def) +- lpmd_config->powersaver_def = LPM_AUTO; +- else +- goto err; +- } +- else if (!strncmp((const char*)cur_node->name, "States", strlen ("States"))) { +- errno = 0; +- lpmd_parse_states(doc, cur_node->children, lpmd_config); +- } +- else if (!strncmp((const char*)cur_node->name, "BalancedSliderAC", strlen ("BalancedSliderAC"))) { +- if (read_slider_and_validate(&lpmd_config->balance_slider_def_ac, tmp_value, "BalancedSliderAC", -1, SLIDER_TYPE_BALANCE) != 0) { +- goto err; +- } +- } +- else if (!strncmp((const char*)cur_node->name, "BalancedSliderDC", strlen ("BalancedSliderDC"))) { +- if (read_slider_and_validate(&lpmd_config->balance_slider_def_dc, tmp_value, "BalancedSliderDC", -1, SLIDER_TYPE_BALANCE) != 0) { +- goto err; +- } +- } +- else if (!strncmp((const char*)cur_node->name, "SliderOffsetAC", strlen ("SliderOffsetAC"))) { +- if (read_slider_and_validate(&lpmd_config->slider_offset_def_ac, tmp_value, "SliderOffsetAC", -1, SLIDER_TYPE_OFFSET) != 0) { +- goto err; +- } +- } +- else if (!strncmp((const char*)cur_node->name, "SliderOffsetDC", strlen ("SliderOffsetDC"))) { +- if (read_slider_and_validate(&lpmd_config->slider_offset_def_dc, tmp_value, "SliderOffsetDC", -1, SLIDER_TYPE_OFFSET) != 0) { +- goto err; +- } +- } +- else { +- if (!strncmp((const char*)cur_node->name, "HfiSuvEnable", strlen("HfiSuvEnable"))) { +- lpmd_log_debug("Ignore deprecated HfiSuvEnable setting\n"); +- } else { +- lpmd_log_info ("Invalid configuration data\n"); +- goto err; +- } +- } +- xmlFree (tmp_value); +- continue; +-err: +- lpmd_log_error("node type: Element, name: %s value: %s\n", cur_node->name, +- tmp_value); +- xmlFree(tmp_value); +- config_error = 1; /* Mark that a parsing error occurred */ +- break; /* Exit loop and validate before returning error */ ++ if (cur_node->type != XML_ELEMENT_NODE) ++ continue; ++ ++ tmp_value = (char *)xmlNodeListGetString(doc, cur_node->xmlChildrenNode, 1); ++ if (!tmp_value) ++ continue; ++ ++ if (!strncmp((const char *)cur_node->name, "Mode", strlen("Mode"))) { ++ errno = 0; ++ lpmd_config->mode = strtol(tmp_value, &pos, 10); ++ if (errno || *pos != '\0' || ++ lpmd_config->mode > LPM_CPU_MODE_MAX || ++ lpmd_config->mode < 0) ++ goto err; ++ } else if (!strncmp((const char *)cur_node->name, ++ "HfiLpmEnable", strlen("HfiLpmEnable"))) { ++ errno = 0; ++ lpmd_config->hfi_lpm_enable = strtol(tmp_value, &pos, 10); ++ if (errno || *pos != '\0' || ++ (lpmd_config->hfi_lpm_enable != 1 && ++ lpmd_config->hfi_lpm_enable != 0)) ++ goto err; ++ } else if (!strncmp((const char *)cur_node->name, ++ "WLTHintEnable", strlen("WLtHintEnable"))) { ++ errno = 0; ++ lpmd_config->wlt_hint_enable = strtol(tmp_value, &pos, 10); ++ if (errno || *pos != '\0' || ++ (lpmd_config->wlt_hint_enable != 1 && ++ lpmd_config->wlt_hint_enable != 0)) ++ goto err; ++ } else if (!strncmp((const char *)cur_node->name, "WLTHintMask", ++ strlen("WLTHintMask"))) { ++ errno = 0; ++ lpmd_config->wlt_hint_mask = strtol(tmp_value, &pos, 10); ++ } else if (!strncmp((const char *)cur_node->name, ++ "WLTHintPollEnable", ++ strlen("WLtHintPollEnable"))) { ++ errno = 0; ++ lpmd_config->wlt_hint_poll_enable = strtol(tmp_value, &pos, 10); ++ if (errno || *pos != '\0' || ++ (lpmd_config->wlt_hint_poll_enable != 1 && ++ lpmd_config->wlt_hint_poll_enable != 0)) ++ goto err; ++ } else if (!strncmp((const char *)cur_node->name, ++ "WLTProxyEnable", ++ strlen("WLTProxyEnable"))) { ++ errno = 0; ++ lpmd_config->wlt_proxy_enable = strtol(tmp_value, &pos, 10); ++ if (errno || *pos != '\0' || ++ (lpmd_config->wlt_proxy_enable != 1 && ++ lpmd_config->wlt_proxy_enable != 0)) ++ goto err; ++ } else if (!strncmp((const char *)cur_node->name, ++ "EntryDelayMS", strlen("EntryDelayMS"))) { ++ errno = 0; ++ lpmd_config->util_entry_delay = strtol(tmp_value, &pos, 10); ++ if (errno || *pos != '\0' || ++ lpmd_config->util_entry_delay < 0 || ++ lpmd_config->util_entry_delay > UTIL_DELAY_MAX) ++ goto err; ++ } else if (!strncmp((const char *)cur_node->name, "ExitDelayMS", ++ strlen("ExitDelayMS"))) { ++ errno = 0; ++ lpmd_config->util_exit_delay = strtol(tmp_value, &pos, 10); ++ if (errno || *pos != '\0' || ++ lpmd_config->util_exit_delay < 0 || ++ lpmd_config->util_exit_delay > UTIL_DELAY_MAX) ++ goto err; ++ } else if (!strncmp((const char *)cur_node->name, ++ "util_entry_threshold", ++ strlen("util_entry_threshold"))) { ++ errno = 0; ++ lpmd_config->util_entry_threshold = strtol(tmp_value, &pos, 10); ++ if (errno || *pos != '\0' || ++ lpmd_config->util_entry_threshold < 0 || ++ lpmd_config->util_entry_threshold > 100) ++ goto err; ++ } else if (!strncmp((const char *)cur_node->name, ++ "util_exit_threshold", ++ strlen("util_exit_threshold"))) { ++ errno = 0; ++ lpmd_config->util_exit_threshold = strtol(tmp_value, &pos, 10); ++ if (errno || *pos != '\0' || ++ lpmd_config->util_exit_threshold < 0 || ++ lpmd_config->util_exit_threshold > 100) ++ goto err; ++ } else if (!strncmp((const char *)cur_node->name, "EntryHystMS", ++ strlen("EntryHystMS"))) { ++ errno = 0; ++ lpmd_config->util_entry_hyst = strtol(tmp_value, &pos, 10); ++ if (errno || *pos != '\0' || ++ lpmd_config->util_entry_hyst < 0 || ++ lpmd_config->util_entry_hyst > UTIL_HYST_MAX) ++ goto err; ++ } else if (!strncmp((const char *)cur_node->name, "ExitHystMS", ++ strlen("ExitHystMS"))) { ++ errno = 0; ++ lpmd_config->util_exit_hyst = strtol(tmp_value, &pos, 10); ++ if (errno || *pos != '\0' || ++ lpmd_config->util_exit_hyst < 0 || ++ lpmd_config->util_exit_hyst > UTIL_HYST_MAX) ++ goto err; ++ } else if (!strncmp((const char *)cur_node->name, "lp_mode_epp", ++ strlen("lp_mode_epp"))) { ++ errno = 0; ++ lpmd_config->lp_mode_epp = strtol(tmp_value, &pos, 10); ++ if (errno || *pos != '\0' || ++ lpmd_config->lp_mode_epp > 255 || ++ lpmd_config->lp_mode_epp < -1) ++ goto err; ++ if (lpmd_config->lp_mode_epp < 0) ++ lpmd_config->lp_mode_epp = -1; ++ } else if (!strncmp((const char *)cur_node->name, "IgnoreITMT", ++ strlen("IgnoreITMT"))) { ++ errno = 0; ++ lpmd_config->ignore_itmt = strtol(tmp_value, &pos, 10); ++ if (errno || *pos != '\0' || ++ lpmd_config->ignore_itmt < 0 || ++ lpmd_config->ignore_itmt > 1) ++ goto err; ++ } else if (!strncmp((const char *)cur_node->name, ++ "lp_mode_cpus", strlen("lp_mode_cpus"))) { ++ if (!strncmp(tmp_value, "-1", strlen("-1"))) ++ lpmd_config->lp_mode_cpus[0] = '\0'; ++ else ++ copy_user_string(tmp_value, lpmd_config->lp_mode_cpus, ++ sizeof(lpmd_config->lp_mode_cpus)); ++ } else if (!strncmp((const char *)cur_node->name, ++ "PerformanceDef", ++ strlen("PerformanceDef"))) { ++ errno = 0; ++ lpmd_config->performance_def = strtol(tmp_value, &pos, 10); ++ if (errno || *pos != '\0') ++ goto err; ++ if (lpmd_config->performance_def == -1) ++ lpmd_config->performance_def = LPM_FORCE_OFF; ++ else if (lpmd_config->performance_def == 1) ++ lpmd_config->performance_def = LPM_FORCE_ON; ++ else if (!lpmd_config->performance_def) ++ lpmd_config->performance_def = LPM_AUTO; ++ else ++ goto err; ++ } else if (!strncmp((const char *)cur_node->name, "BalancedDef", ++ strlen("BalancedDef"))) { ++ errno = 0; ++ lpmd_config->balanced_def = strtol(tmp_value, &pos, 10); ++ if (errno || *pos != '\0') ++ goto err; ++ if (lpmd_config->balanced_def == -1) ++ lpmd_config->balanced_def = LPM_FORCE_OFF; ++ else if (lpmd_config->balanced_def == 1) ++ lpmd_config->balanced_def = LPM_FORCE_ON; ++ else if (!lpmd_config->balanced_def) ++ lpmd_config->balanced_def = LPM_AUTO; ++ else ++ goto err; ++ } else if (!strncmp((const char *)cur_node->name, ++ "PowersaverDef", strlen("PowersaverDef"))) { ++ errno = 0; ++ lpmd_config->powersaver_def = strtol(tmp_value, &pos, 10); ++ if (errno || *pos != '\0') ++ goto err; ++ if (lpmd_config->powersaver_def == -1) ++ lpmd_config->powersaver_def = LPM_FORCE_OFF; ++ else if (lpmd_config->powersaver_def == 1) ++ lpmd_config->powersaver_def = LPM_FORCE_ON; ++ else if (!lpmd_config->powersaver_def) ++ lpmd_config->powersaver_def = LPM_AUTO; ++ else ++ goto err; ++ } else if (!strncmp((const char *)cur_node->name, "States", ++ strlen("States"))) { ++ errno = 0; ++ lpmd_parse_states(doc, cur_node->children, lpmd_config); ++ } else if (!strncmp((const char *)cur_node->name, "BalancedSliderAC", strlen("BalancedSliderAC"))) { ++ if (read_slider_and_validate(&lpmd_config->balance_slider_def_ac, ++ tmp_value, "BalancedSliderAC", -1, SLIDER_TYPE_BALANCE) != 0) ++ goto err; ++ } else if (!strncmp((const char *)cur_node->name, "BalancedSliderDC", strlen("BalancedSliderDC"))) { ++ if (read_slider_and_validate(&lpmd_config->balance_slider_def_dc, ++ tmp_value, "BalancedSliderDC", -1, SLIDER_TYPE_BALANCE) != 0) ++ goto err; ++ } else if (!strncmp((const char *)cur_node->name, "SliderOffsetAC", strlen("SliderOffsetAC"))) { ++ if (read_slider_and_validate(&lpmd_config->slider_offset_def_ac, ++ tmp_value, "SliderOffsetAC", -1, SLIDER_TYPE_OFFSET) != 0) ++ goto err; ++ } else if (!strncmp((const char *)cur_node->name, "SliderOffsetDC", strlen("SliderOffsetDC"))) { ++ if (read_slider_and_validate(&lpmd_config->slider_offset_def_dc, ++ tmp_value, "SliderOffsetDC", -1, SLIDER_TYPE_OFFSET) != 0) ++ goto err; ++ } else { ++ if (!strncmp((const char *)cur_node->name, "HfiSuvEnable", strlen("HfiSuvEnable"))) { ++ lpmd_log_debug("Ignore deprecated HfiSuvEnable setting\n"); ++ } else { ++ lpmd_log_info("Invalid configuration data\n"); ++ goto err; + } + } ++ xmlFree(tmp_value); ++ continue; ++err: ++ lpmd_log_error("node type: Element, name: %s value: %s\n", cur_node->name, ++ tmp_value); ++ xmlFree(tmp_value); ++ config_error = 1; /* Mark that a parsing error occurred */ ++ break; /* Exit loop and validate before returning error */ + } + + /* If a parsing error occurred, return error */ +@@ -525,8 +515,8 @@ int match_config_file(int family, int model, int tdp, char *save_file_name) + "%s/intel_lpmd_config_F%d_M%d_T%d.xml", TDCONFDIR, family, + model, tdp); + +- lpmd_log_msg ("Looking for config file %s\n", file_name); +- ret = stat (file_name, &s); ++ lpmd_log_msg("Looking for config file %s\n", file_name); ++ ret = stat(file_name, &s); + if (!ret) { + strncpy(save_file_name, file_name, MAX_FILE_NAME_PATH); + return ret; +@@ -546,7 +536,7 @@ int match_config_file(int family, int model, int tdp, char *save_file_name) + return ret; + } + +-int lpmd_get_config(lpmd_config_t *lpmd_config) ++int lpmd_get_config(struct lpmd_config_t *lpmd_config) + { + char file_name_str[MAX_FILE_NAME_PATH]; + xmlNode *root_element; +@@ -567,51 +557,51 @@ int lpmd_get_config(lpmd_config_t *lpmd_config) + goto process_xml; + } + +- file_name = file_name_str; +- + /* + * If a model specific config file was not found use the generic + * config file. + */ +- snprintf (file_name, MAX_FILE_NAME_PATH, "%s/%s", TDCONFDIR, CONFIG_FILE_NAME); ++ file_name = file_name_str; ++ snprintf(file_name, MAX_FILE_NAME_PATH, "%s/%s", TDCONFDIR, CONFIG_FILE_NAME); + +- lpmd_log_msg ("Reading configuration file %s\n", file_name); ++ lpmd_log_msg("Reading configuration file %s\n", file_name); + +- if (stat (file_name, &s)) { +- lpmd_log_msg ("error: could not find file %s\n", file_name); ++ if (stat(file_name, &s)) { ++ lpmd_log_msg("error: could not find file %s\n", file_name); + return LPMD_ERROR; + } + + strncpy(lpmd_config->file_name, file_name, MAX_FILE_NAME_PATH - 1); + + process_xml: +- doc = xmlReadFile (file_name, NULL, 0); +- if (doc == NULL) { +- lpmd_log_msg ("error: could not parse file %s\n", file_name); ++ doc = xmlReadFile(file_name, NULL, 0); ++ if (!doc) { ++ lpmd_log_msg("error: could not parse file %s\n", file_name); + return LPMD_ERROR; + } + +- root_element = xmlDocGetRootElement (doc); +- if (root_element == NULL) { +- lpmd_log_warn ("error: could not get root element\n"); ++ root_element = xmlDocGetRootElement(doc); ++ if (!root_element) { ++ lpmd_log_warn("error: could not get root element\n"); + return LPMD_ERROR; + } + + cur_node = NULL; + + for (cur_node = root_element; cur_node; cur_node = cur_node->next) { +- if (cur_node->type == XML_ELEMENT_NODE) { +- if (!strncmp ((const char*) cur_node->name, "Configuration", +- strlen ("Configuration"))) { +- if (lpmd_fill_config (doc, cur_node->children, lpmd_config) != LPMD_SUCCESS) { +- xmlFreeDoc (doc); +- return LPMD_ERROR; +- } +- } ++ if (cur_node->type != XML_ELEMENT_NODE) ++ continue; ++ ++ if (strncmp((const char *)cur_node->name, "Configuration", strlen("Configuration"))) ++ continue; ++ ++ if (lpmd_fill_config(doc, cur_node->children, lpmd_config) != LPMD_SUCCESS) { ++ xmlFreeDoc(doc); ++ return LPMD_ERROR; + } + } + +- xmlFreeDoc (doc); ++ xmlFreeDoc(doc); + + return LPMD_SUCCESS; + } +diff --git a/src/lpmd_cpu.c b/src/lpmd_cpu.c +index aa7c1da..f4c9cbd 100644 +--- a/src/lpmd_cpu.c ++++ b/src/lpmd_cpu.c +@@ -1,22 +1,5 @@ +-/* +- * lpmd_cpu.c: CPU related processing +- * +- * Copyright (C) 2025 Intel Corporation. All rights reserved. +- * +- * This program is free software; you can redistribute it and/or modify +- * it under the terms of the GNU General Public License as published by +- * the Free Software Foundation; either version 2 of the License, or +- * (at your option) any later version. +- * +- * This program is distributed in the hope that it will be useful, +- * but WITHOUT ANY WARRANTY; without even the implied warranty of +- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +- * GNU General Public License for more details. +- * +- * You should have received a copy of the GNU General Public License +- * along with this program; if not, write to the Free Software +- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +- */ ++// SPDX-License-Identifier: GPL-2.0-or-later ++/* Copyright (C) 2026 Intel Corporation */ + + #define _GNU_SOURCE + #include +@@ -46,17 +29,17 @@ static struct cpu_model_entry id_table[] = { + { 0, 0 } // Last Invalid entry + }; + +-int detect_supported_platform(lpmd_config_t *lpmd_config) ++int detect_supported_platform(struct lpmd_config_t *lpmd_config) + { +- unsigned int eax, ebx, ecx, edx; + unsigned int max_level, family, model, stepping, tdp; + char file_name[MAX_FILE_NAME_PATH] = "\0"; ++ unsigned int eax, ebx, ecx, edx; + int val; + + cpuid(0, eax, ebx, ecx, edx); + + /* Unsupported vendor */ +- if (ebx != 0x756e6547 || edx != 0x49656e69 || ecx != 0x6c65746e) { ++ if (ebx != 0x756e6547 || edx != 0x49656e69 || ecx != 0x6c65746e) { + lpmd_log_info("Unsupported vendor\n"); + return -1; + } +@@ -73,7 +56,7 @@ int detect_supported_platform(lpmd_config_t *lpmd_config) + tdp = get_tdp(); + + lpmd_log_info("%u CPUID levels; family:model:stepping 0x%x:%x:%x (%u:%u:%u)\n", +- max_level, family, model, stepping, family, model, stepping); ++ max_level, family, model, stepping, family, model, stepping); + + if (!match_config_file(family, model, tdp, file_name)) { + lpmd_log_info("Found a config file matching the platform model - skipping platform check\n"); +@@ -86,10 +69,10 @@ int detect_supported_platform(lpmd_config_t *lpmd_config) + } + + /* Need CPUID.1A to detect CPU core type */ +- if (max_level < 0x1a) { ++ if (max_level < 0x1a) { + lpmd_log_info("CPUID leaf 0x1a not supported, unable to detect CPU type\n"); + return -1; +- } ++ } + + cpuid_count(7, 0, eax, ebx, ecx, edx); + +@@ -106,7 +89,8 @@ int detect_supported_platform(lpmd_config_t *lpmd_config) + } + + if (val != 2 && val != 8) { +- lpmd_log_info("Non-Mobile PM profile detected. %s returns %d\n", PATH_PM_PROFILE, val); ++ lpmd_log_info("Non-Mobile PM profile detected. %s returns %d\n", ++ PATH_PM_PROFILE, val); + return -1; + } + +@@ -116,7 +100,7 @@ int detect_supported_platform(lpmd_config_t *lpmd_config) + if (id_table[val].family == family && id_table[val].model == model) + break; + val++; +- } ++ } + + /* Unsupported model */ + if (!id_table[val].family) { +@@ -124,7 +108,9 @@ int detect_supported_platform(lpmd_config_t *lpmd_config) + lpmd_log_debug("Supported platforms (with optimized configs):\n"); + val = 0; + while (id_table[val].family) { +- lpmd_log_debug("\tfamily %d model %d\n", id_table[val].family, id_table[val].model); ++ lpmd_log_debug("\tfamily %d model %d\n", ++ id_table[val].family, ++ id_table[val].model); + val++; + } + } +@@ -174,7 +160,7 @@ static int is_cpu_in_l3(int cpu) + return -1; + } + +- for(subleaf = 0;; subleaf++) { ++ for (subleaf = 0; ; subleaf++) { + unsigned int type, level; + + cpuid_count(4, subleaf, eax, ebx, ecx, edx); +@@ -186,7 +172,7 @@ static int is_cpu_in_l3(int cpu) + if (!type) + break; + /* Unified Cache */ +- if (type !=3 ) ++ if (type != 3) + continue; + /* L3 */ + if (level != 3) +@@ -222,34 +208,34 @@ int is_cpu_lcore(int cpu) + #define PATH_RAPL "/sys/class/powercap" + int get_tdp(void) + { +- FILE *filep; +- DIR *dir; +- struct dirent *entry; +- int ret; + char path[MAX_STR_LENGTH * 2]; + char str[MAX_STR_LENGTH]; ++ struct dirent *entry; ++ int ret, tdp = 0; ++ FILE *filep; + char *pos; +- int tdp = 0; ++ DIR *dir; + +- if ((dir = opendir (PATH_RAPL)) == NULL) { +- perror ("opendir() error"); ++ dir = opendir(PATH_RAPL); ++ if (!dir) { ++ perror("opendir() error"); + return 1; + } + +- while ((entry = readdir (dir)) != NULL) { +- if (strlen (entry->d_name) > 100) ++ while ((entry = readdir(dir)) != NULL) { ++ if (strlen(entry->d_name) > 100) + continue; + + if (strncmp(entry->d_name, "intel-rapl", strlen("intel-rapl"))) + continue; + +- snprintf (path, MAX_STR_LENGTH * 2, "%s/%s/name", PATH_RAPL, entry->d_name); +- filep = fopen (path, "r"); ++ snprintf(path, MAX_STR_LENGTH * 2, "%s/%s/name", PATH_RAPL, entry->d_name); ++ filep = fopen(path, "r"); + if (!filep) + continue; + +- ret = fread (str, 1, MAX_STR_LENGTH, filep); +- fclose (filep); ++ ret = fread(str, 1, MAX_STR_LENGTH, filep); ++ fclose(filep); + + if (ret <= 0) + continue; +@@ -257,13 +243,15 @@ int get_tdp(void) + if (strncmp(str, "package", strlen("package"))) + continue; + +- snprintf (path, MAX_STR_LENGTH * 2, "%s/%s/constraint_0_max_power_uw", PATH_RAPL, entry->d_name); +- filep = fopen (path, "r"); ++ snprintf(path, MAX_STR_LENGTH * 2, ++ "%s/%s/constraint_0_max_power_uw", PATH_RAPL, ++ entry->d_name); ++ filep = fopen(path, "r"); + if (!filep) + continue; + +- ret = fread (str, 1, MAX_STR_LENGTH, filep); +- fclose (filep); ++ ret = fread(str, 1, MAX_STR_LENGTH, filep); ++ fclose(filep); + + if (ret <= 0) + continue; +@@ -275,54 +263,52 @@ int get_tdp(void) + tdp = strtol(str, &pos, 10); + break; + } +- closedir (dir); ++ closedir(dir); + + return tdp / 1000000; + } + +- + #define BITMASK_SIZE 32 + int detect_max_cpus(void) + { +- FILE *filep; + unsigned long dummy; +- int max_cpus; +- int i; ++ int max_cpus, i; ++ FILE *filep; + + max_cpus = 0; + for (i = 0; i < 256; ++i) { + char path[MAX_STR_LENGTH]; + +- snprintf (path, sizeof(path), "/sys/devices/system/cpu/cpu%d/topology/thread_siblings", i); ++ snprintf(path, sizeof(path), ++ "/sys/devices/system/cpu/cpu%d/topology/thread_siblings", i); + +- filep = fopen (path, "r"); ++ filep = fopen(path, "r"); + if (filep) + break; + } + + if (!filep) { +- lpmd_log_error ("Can't get max cpu number\n"); ++ lpmd_log_error("Can't get max cpu number\n"); + return -1; + } + +- while (fscanf (filep, "%lx,", &dummy) == 1) ++ while (fscanf(filep, "%lx,", &dummy) == 1) + max_cpus += BITMASK_SIZE; +- fclose (filep); ++ fclose(filep); ++ ++ lpmd_log_debug("\t%d CPUs supported in maximum\n", max_cpus); + +- lpmd_log_debug ("\t%d CPUs supported in maximum\n", max_cpus); +- + set_max_cpus(max_cpus); + return 0; + } + +-int detect_cpu_topo(lpmd_config_t *lpmd_config) ++int detect_cpu_topo(struct lpmd_config_t *lpmd_config) + { + FILE *filep; + int i; + char path[MAX_STR_LENGTH]; + int ret; + int pcores, ecores, lcores; +- int tdp; + + ret = detect_max_cpus(); + if (ret) +@@ -334,22 +320,24 @@ int detect_cpu_topo(lpmd_config_t *lpmd_config) + return ret; + + cpumask_reset(CPUMASK_ONLINE); +- pcores = ecores = lcores = 0; ++ pcores = 0; ++ ecores = 0; ++ lcores = 0; + + for (i = 0; i < get_max_cpus(); i++) { + unsigned int online = 0; + +- snprintf (path, sizeof(path), "/sys/devices/system/cpu/cpu%d/online", i); +- filep = fopen (path, "r"); ++ snprintf(path, sizeof(path), "/sys/devices/system/cpu/cpu%d/online", i); ++ filep = fopen(path, "r"); + if (filep) { +- if (fscanf (filep, "%u", &online) != 1) +- lpmd_log_warn ("fread failed for %s\n", path); +- fclose (filep); +- } +- else if (!i) ++ if (fscanf(filep, "%u", &online) != 1) ++ lpmd_log_warn("fread failed for %s\n", path); ++ fclose(filep); ++ } else if (!i) { + online = 1; +- else ++ } else { + break; ++ } + + if (!online) + continue; +@@ -361,9 +349,8 @@ int detect_cpu_topo(lpmd_config_t *lpmd_config) + /* Here it is the first time we migrate CPUs, must clear the previous cgroup settings */ + cgroup_cleanup(); + +- for (i = 0 ; i < CORE_TYPES_COUNT ; i++) { ++ for (i = 0 ; i < CORE_TYPES_COUNT ; i++) + memset(lpmd_config->core_type_masks[i], 0, get_max_cpus() / 8); +- } + + for (i = 0; i < get_max_cpus(); i++) { + if (!is_cpu_online(i)) +@@ -371,12 +358,10 @@ int detect_cpu_topo(lpmd_config_t *lpmd_config) + if (is_cpu_pcore(i) > 0) { + pcores++; + lpmd_config->core_type_masks[P_CORE][i / 8] |= 1 << (i % 8); +- } +- else if (is_cpu_ecore(i) > 0) { ++ } else if (is_cpu_ecore(i) > 0) { + ecores++; + lpmd_config->core_type_masks[E_CORE][i / 8] |= 1 << (i % 8); +- } +- else if (is_cpu_lcore(i) > 0) { ++ } else if (is_cpu_lcore(i) > 0) { + lcores++; + lpmd_config->core_type_masks[L_CORE][i / 8] |= 1 << (i % 8); + } +@@ -398,7 +383,7 @@ static int detect_lpm_cpus_cmd(char *cmd) + { + int ret; + +- ret = cpumask_init_cpus (cmd, CPUMASK_LPM_DEFAULT); ++ ret = cpumask_init_cpus(cmd, CPUMASK_LPM_DEFAULT); + if (ret <= 0) + cpumask_reset(CPUMASK_LPM_DEFAULT); + +@@ -407,32 +392,32 @@ static int detect_lpm_cpus_cmd(char *cmd) + + static int detect_lpm_cpus_cluster(void) + { +- FILE *filep; + char path[MAX_STR_LENGTH]; + char str[MAX_STR_LENGTH]; ++ FILE *filep; + int i, ret; + + for (i = get_max_cpus(); i >= 0; i--) { +- if (!is_cpu_online (i)) ++ if (!is_cpu_online(i)) + continue; + +- snprintf (path, sizeof(path), "/sys/devices/system/cpu/cpu%d/topology/cluster_cpus_list", +- i); ++ snprintf(path, sizeof(path), ++ "/sys/devices/system/cpu/cpu%d/topology/cluster_cpus_list", i); + path[MAX_STR_LENGTH - 1] = '\0'; + +- filep = fopen (path, "r"); ++ filep = fopen(path, "r"); + if (!filep) + continue; + +- ret = fread (str, 1, MAX_STR_LENGTH - 1, filep); +- fclose (filep); ++ ret = fread(str, 1, MAX_STR_LENGTH - 1, filep); ++ fclose(filep); + + if (ret <= 0) + continue; + + str[ret] = '\0'; + +- if (cpumask_init_cpus (str, CPUMASK_LPM_DEFAULT) <= 0) ++ if (cpumask_init_cpus(str, CPUMASK_LPM_DEFAULT) <= 0) + continue; + + /* An Ecore module contains 4 Atom cores */ +@@ -464,7 +449,7 @@ static int detect_lpm_cpus_lcore(void) + int i; + + for (i = 0; i < get_max_cpus(); i++) { +- if (!is_cpu_online (i)) ++ if (!is_cpu_online(i)) + continue; + if (detect_cpu_lcore(i) < 0) + return -1; +@@ -491,16 +476,16 @@ int detect_lpm_cpus(char *cmd_cpus) + char *str = NULL; + + if (cmd_cpus && cmd_cpus[0] != '\0') { +- ret = detect_lpm_cpus_cmd (cmd_cpus); ++ ret = detect_lpm_cpus_cmd(cmd_cpus); + if (ret <= 0) { +- lpmd_log_error ("\tInvalid -c parameter: %s\n", cmd_cpus); +- exit (-1); ++ lpmd_log_error("\tInvalid -c parameter: %s\n", cmd_cpus); ++ exit(-1); + } + str = "CommandLine"; + goto end; + } + +- ret = detect_lpm_cpus_lcore (); ++ ret = detect_lpm_cpus_lcore(); + if (ret < 0) + return ret; + +@@ -509,14 +494,15 @@ int detect_lpm_cpus(char *cmd_cpus) + goto end; + } + +- if (detect_lpm_cpus_cluster ()) { ++ if (detect_lpm_cpus_cluster()) { + str = "Ecores"; + goto end; + } + +-end: if (cpumask_has_cpu(CPUMASK_LPM_DEFAULT)) +- lpmd_log_info ("\tUse CPU %s as Default Low Power CPUs (%s)\n", +- get_cpus_str (CPUMASK_LPM_DEFAULT, false), str); ++end: ++ if (cpumask_has_cpu(CPUMASK_LPM_DEFAULT)) ++ lpmd_log_info("\tUse CPU %s as Default Low Power CPUs (%s)\n", ++ get_cpus_str(CPUMASK_LPM_DEFAULT, false), str); + + return 0; + } +diff --git a/src/lpmd_cpumask.c b/src/lpmd_cpumask.c +index 3d6a22b..fc87371 100644 +--- a/src/lpmd_cpumask.c ++++ b/src/lpmd_cpumask.c +@@ -1,22 +1,5 @@ +-/* +- * lpmd_cpumask.c: helper functions for cpumask handlingf +- * +- * Copyright (C) 2025 Intel Corporation. All rights reserved. +- * +- * This program is free software; you can redistribute it and/or modify +- * it under the terms of the GNU General Public License as published by +- * the Free Software Foundation; either version 2 of the License, or +- * (at your option) any later version. +- * +- * This program is distributed in the hope that it will be useful, +- * but WITHOUT ANY WARRANTY; without even the implied warranty of +- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +- * GNU General Public License for more details. +- * +- * You should have received a copy of the GNU General Public License +- * along with this program; if not, write to the Free Software +- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +- */ ++// SPDX-License-Identifier: GPL-2.0-or-later ++/* Copyright (C) 2026 Intel Corporation */ + + #define _GNU_SOURCE + #include +@@ -83,8 +66,8 @@ static size_t alloc_cpu_set(cpu_set_t **cpu_set) + size_t size; + + _cpu_set = CPU_ALLOC((topo_max_cpus + 1)); +- if (_cpu_set == NULL) +- err (3, "CPU_ALLOC"); ++ if (!_cpu_set) ++ err(3, "CPU_ALLOC"); + size = CPU_ALLOC_SIZE((topo_max_cpus + 1)); + CPU_ZERO_S(size, _cpu_set); + +@@ -94,8 +77,8 @@ static size_t alloc_cpu_set(cpu_set_t **cpu_set) + size_cpumask = size; + + if (size_cpumask && size_cpumask != size) { +- lpmd_log_error ("Conflict cpumask size %zu vs. %zu\n", size, size_cpumask); +- exit (-1); ++ lpmd_log_error("Conflict cpumask size %zu vs. %zu\n", size, size_cpumask); ++ exit(-1); + } + return size; + } +@@ -105,7 +88,7 @@ int cpu_migrate(int cpu) + cpu_set_t *mask; + int ret; + +- alloc_cpu_set (&mask); ++ alloc_cpu_set(&mask); + CPU_SET_S(cpu, size_cpumask, mask); + ret = sched_setaffinity(0, size_cpumask, mask); + CPU_FREE(mask); +@@ -138,7 +121,7 @@ int cpumask_free(enum cpumask_idx idx) + { + if (!cpumasks[idx].mask) + return 0; +- ++ + cpumask_reset(idx); + free(cpumasks[idx].mask); + cpumasks[idx].mask = NULL; +@@ -152,11 +135,11 @@ int cpumask_reset(enum cpumask_idx idx) + else + CPU_ZERO_S(size_cpumask, cpumasks[idx].mask); + +- free (cpumasks[idx].str); +- free (cpumasks[idx].str_reverse); +- free (cpumasks[idx].hexstr); +- free (cpumasks[idx].hexstr_reverse); +- free (cpumasks[idx].hexvals); ++ free(cpumasks[idx].str); ++ free(cpumasks[idx].str_reverse); ++ free(cpumasks[idx].hexstr); ++ free(cpumasks[idx].hexstr_reverse); ++ free(cpumasks[idx].hexvals); + cpumasks[idx].str = NULL; + cpumasks[idx].str_reverse = NULL; + cpumasks[idx].hexstr = NULL; +@@ -167,27 +150,29 @@ int cpumask_reset(enum cpumask_idx idx) + + int cpumask_add_cpu(int cpu, enum cpumask_idx idx) + { +- if (idx != CPUMASK_ONLINE && !is_cpu_online (cpu)) ++ if (idx != CPUMASK_ONLINE && !is_cpu_online(cpu)) + return 0; + + if (!cpumasks[idx].mask) +- alloc_cpu_set (&cpumasks[idx].mask); ++ alloc_cpu_set(&cpumasks[idx].mask); + + CPU_SET_S(cpu, size_cpumask, cpumasks[idx].mask); + + return LPMD_SUCCESS; + } + +-void free_cpu_type_masks(lpmd_config_t *lpmd_config) ++void free_cpu_type_masks(struct lpmd_config_t *lpmd_config) + { + int i; ++ + for (i = 0 ; i < CORE_TYPES_COUNT ; i++) + free(lpmd_config->core_type_masks[i]); + } + +-int allocate_cpu_type_masks(lpmd_config_t *lpmd_config) ++int allocate_cpu_type_masks(struct lpmd_config_t *lpmd_config) + { + int i; ++ + for (i = 0 ; i < CORE_TYPES_COUNT ; i++) { + lpmd_config->core_type_masks[i] = malloc(get_max_cpus() / 8); + if (!lpmd_config->core_type_masks[i]) { +@@ -198,7 +183,7 @@ int allocate_cpu_type_masks(lpmd_config_t *lpmd_config) + return 0; + } + +-static unsigned int count_cpu_type_cores(unsigned char * bitmask) ++static unsigned int count_cpu_type_cores(unsigned char *bitmask) + { + unsigned int count = 0; + int i; +@@ -223,15 +208,15 @@ static unsigned int get_next_cpu_cmask(unsigned int id, enum core_type type, uns + return id; + } + +-int cpumask_init_cpus_type(char * buf, enum cpumask_idx idx, unsigned char **cmasks, enum core_type type) ++int cpumask_init_cpus_type(char *buf, enum cpumask_idx idx, unsigned char **cmasks, enum core_type type) + { + unsigned int current, next, count; + int nr_cpus = 0; +- char * end; ++ char *end; + +- if (!strncmp(buf, "ALL", strlen("ALL")) || !strncmp(buf, "all", strlen("all")) || is_wildcard(buf)) ++ if (!strncmp(buf, "ALL", strlen("ALL")) || !strncmp(buf, "all", strlen("all")) || is_wildcard(buf)) { + count = count_cpu_type_cores(cmasks[type]); +- else { ++ } else { + errno = 0; + count = strtol(buf, &end, 10); + if (errno || *end != '\0' || !count) +@@ -239,7 +224,7 @@ int cpumask_init_cpus_type(char * buf, enum cpumask_idx idx, unsigned char **cma + } + + current = get_next_cpu_cmask(0, type, cmasks[type]); +- while(nr_cpus != count) { ++ while (nr_cpus != count) { + cpumask_add_cpu(current, idx); + next = get_next_cpu_cmask(current + 1, type, cmasks[type]); + if(next == current) /* Couldn't find next core of the provided type */ +@@ -278,9 +263,9 @@ int cpumask_init_cpus(char *buf, enum cpumask_idx idx) + if (*next == '-') /* no negative cpu numbers */ + goto error; + +- start = strtoul (next, &next, 10); ++ start = strtoul(next, &next, 10); + +- cpumask_add_cpu (start, idx); ++ cpumask_add_cpu(start, idx); + + if (*next == '\0') + break; +@@ -292,8 +277,7 @@ int cpumask_init_cpus(char *buf, enum cpumask_idx idx) + + if (*next == '-') { + next += 1; /* start range */ +- } +- else if (*next == '.') { ++ } else if (*next == '.') { + next += 1; + if (*next == '.') + next += 1; /* start range */ +@@ -301,12 +285,12 @@ int cpumask_init_cpus(char *buf, enum cpumask_idx idx) + goto error; + } + +- end = strtoul (next, &next, 10); ++ end = strtoul(next, &next, 10); + if (end <= start) + goto error; + + while (++start <= end) +- cpumask_add_cpu (start, idx); ++ cpumask_add_cpu(start, idx); + + if (*next == ',') + next += 1; +@@ -318,7 +302,7 @@ int cpumask_init_cpus(char *buf, enum cpumask_idx idx) + + return CPU_COUNT_S(size_cpumask, cpumasks[idx].mask); + error: +- lpmd_log_error ("CPU string malformed: %s\n", buf); ++ lpmd_log_error("CPU string malformed: %s\n", buf); + return -1; + } + +@@ -362,7 +346,7 @@ void cpumask_copy(enum cpumask_idx source, enum cpumask_idx dest) + } + } + +-void cpumask_exclude_copy(enum cpumask_idx source, enum cpumask_idx dest, enum cpumask_idx exlude) ++void cpumask_exclude_copy(enum cpumask_idx source, enum cpumask_idx dest, enum cpumask_idx exclude) + { + int i; + +@@ -371,9 +355,8 @@ void cpumask_exclude_copy(enum cpumask_idx source, enum cpumask_idx dest, enum c + if (!CPU_ISSET_S(i, size_cpumask, cpumasks[source].mask)) + continue; + +- if (CPU_ISSET_S(i, size_cpumask, cpumasks[exlude].mask)) ++ if (CPU_ISSET_S(i, size_cpumask, cpumasks[exclude].mask)) + continue; +- + } + } + +@@ -387,10 +370,10 @@ static int cpumask_to_str(cpu_set_t *mask, char *buf, int length) + if (!CPU_ISSET_S(i, size_cpumask, mask)) + continue; + if (length - 1 < offset) { +- lpmd_log_debug ("cpumask_to_str: Too many cpus\n"); ++ lpmd_log_debug("%s: Too many cpus\n", __func__); + return 1; + } +- offset += snprintf (buf + offset, length - 1 - offset, "%d,", i); ++ offset += snprintf(buf + offset, length - 1 - offset, "%d,", i); + } + if (offset) + buf[offset - 1] = '\0'; +@@ -442,7 +425,7 @@ static int cpumask_to_hexstr(cpu_set_t *mask, char *str, int size) + } + + int get_cached_value_init(enum cpumask_idx idx, bool refresh, +- char **cached_str, const char *cached_name) ++ char **cached_str, const char *cached_name) + { + if (!cpumasks[idx].mask) + return LPMD_ERROR; +@@ -454,36 +437,38 @@ int get_cached_value_init(enum cpumask_idx idx, bool refresh, + if (!refresh) + return LPMD_SUCCESS; + } else { +- *cached_str = calloc (MAX_STR_LENGTH, 1); ++ *cached_str = calloc(MAX_STR_LENGTH, 1); + } + + if (!(*cached_str)) +- err (3, "%s_ALLOC", cached_name); ++ err(3, "%s_ALLOC", cached_name); + + return LPMD_SUCCESS; + } + +-char* get_cpus_str(enum cpumask_idx idx, bool refresh) ++char *get_cpus_str(enum cpumask_idx idx, bool refresh) + { + int ret = get_cached_value_init(idx, refresh, &cpumasks[idx].str, "STR"); ++ + if (ret) + return NULL; + +- cpumask_to_str (cpumasks[idx].mask, cpumasks[idx].str, MAX_STR_LENGTH); ++ cpumask_to_str(cpumasks[idx].mask, cpumasks[idx].str, MAX_STR_LENGTH); + return cpumasks[idx].str; + } + +-char* get_cpus_hexstr(enum cpumask_idx idx, bool refresh) ++char *get_cpus_hexstr(enum cpumask_idx idx, bool refresh) + { + int ret = get_cached_value_init(idx, refresh, &cpumasks[idx].hexstr, "HEXSTR"); ++ + if (ret) + return NULL; + +- cpumask_to_hexstr (cpumasks[idx].mask, cpumasks[idx].hexstr, MAX_STR_LENGTH); ++ cpumask_to_hexstr(cpumasks[idx].mask, cpumasks[idx].hexstr, MAX_STR_LENGTH); + return cpumasks[idx].hexstr; + } + +-static char* get_cpus_str_reverse(enum cpumask_idx idx, bool refresh) ++static char *get_cpus_str_reverse(enum cpumask_idx idx, bool refresh) + { + cpu_set_t *mask; + int ret; +@@ -492,9 +477,9 @@ static char* get_cpus_str_reverse(enum cpumask_idx idx, bool refresh) + if (ret) + return NULL; + +- alloc_cpu_set (&mask); ++ alloc_cpu_set(&mask); + CPU_XOR_S(size_cpumask, mask, cpumasks[idx].mask, cpumasks[CPUMASK_ONLINE].mask); +- cpumask_to_str (mask, cpumasks[idx].str_reverse, MAX_STR_LENGTH); ++ cpumask_to_str(mask, cpumasks[idx].str_reverse, MAX_STR_LENGTH); + CPU_FREE(mask); + + return cpumasks[idx].str_reverse; +@@ -517,7 +502,7 @@ static uint8_t *get_cpus_hexvals(enum cpumask_idx idx, bool refresh) + if (!refresh) + return cpumasks[idx].hexvals; + +- vals = calloc (size, 1); ++ vals = calloc(size, 1); + if (!vals) + return NULL; + +@@ -526,7 +511,7 @@ static uint8_t *get_cpus_hexvals(enum cpumask_idx idx, bool refresh) + k = i / 8; + + if (k >= size) { +- lpmd_log_error ("size too big\n"); ++ lpmd_log_error("size too big\n"); + free(vals); + return NULL; + } +@@ -535,7 +520,8 @@ static uint8_t *get_cpus_hexvals(enum cpumask_idx idx, bool refresh) + goto set_val; + + v |= 1 << j; +-set_val: if (j == 7) { ++set_val: ++ if (j == 7) { + vals[k] = v; + v = 0; + } +@@ -547,12 +533,14 @@ set_val: if (j == 7) { + + int cpumask_blacklist(enum cpumask_idx idx) + { ++ char *state_name; ++ + if (!cpumasks[idx].mask) +- alloc_cpu_set (&cpumasks[idx].mask); ++ alloc_cpu_set(&cpumasks[idx].mask); + + /* Return due to blacklist not getting initialized yet. */ + if (!cpumasks[CPUMASK_BLACKLIST].mask) { +- alloc_cpu_set (&cpumasks[CPUMASK_BLACKLIST].mask); ++ alloc_cpu_set(&cpumasks[CPUMASK_BLACKLIST].mask); + return LPMD_ERROR; + } + +@@ -572,7 +560,7 @@ int cpumask_blacklist(enum cpumask_idx idx) + cpumasks[idx].hexvals = get_cpus_hexvals(idx, true); + + if (!CPU_COUNT_S(size_cpumask, cpumasks[idx].mask)) { +- char *state_name = user_cpumask_idx_to_state_name(idx); ++ state_name = user_cpumask_idx_to_state_name(idx); + lpmd_log_error("%s: cpumask[%d] is empty after blacklisting due to unavailable cpus\n", state_name, idx); + lpmd_log_error("It's possible another cgroup claimed all cores required by cpumask[%d]\n", idx); + } +@@ -580,7 +568,6 @@ int cpumask_blacklist(enum cpumask_idx idx) + return LPMD_SUCCESS; + } + +- + char *get_proc_irq_str(enum cpumask_idx idx) + { + return get_cpus_hexstr(idx, false); +diff --git a/src/lpmd_dbus_server.c b/src/lpmd_dbus_server.c +index 0b2960b..1c08aec 100644 +--- a/src/lpmd_dbus_server.c ++++ b/src/lpmd_dbus_server.c +@@ -1,25 +1,5 @@ +-/* +- * lpmd_dbus_server.c: Dbus server for intel_lpmd +- * +- * Copyright (C) 2023 Intel Corporation. All rights reserved. +- * +- * This program is free software; you can redistribute it and/or modify +- * it under the terms of the GNU General Public License as published by +- * the Free Software Foundation; either version 2 of the License, or +- * (at your option) any later version. +- * +- * This program is distributed in the hope that it will be useful, +- * but WITHOUT ANY WARRANTY; without even the implied warranty of +- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +- * GNU General Public License for more details. +- * +- * You should have received a copy of the GNU General Public License +- * along with this program; if not, write to the Free Software +- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +- * +- * This file contains function to start dbus server and provide callbacks for +- * dbus messages. +- */ ++// SPDX-License-Identifier: GPL-2.0-or-later ++/* Copyright (C) 2026 Intel Corporation */ + + #include + #include +@@ -56,51 +36,50 @@ static gboolean + // Dbus object initialization + static void pref_object_init(PrefObject *obj) + { +- g_assert (obj != NULL); ++ g_assert(obj); + } + + // Dbus object class initialization + static void pref_object_class_init(PrefObjectClass *_class) + { +- g_assert (_class != NULL); ++ g_assert(_class); + } + + static gboolean dbus_interface_terminate(PrefObject *obj, GError **error) + { +- lpmd_log_debug ("intel_lpmd_dbus_interface_terminate\n"); +- lpmd_terminate (); ++ lpmd_log_debug("intel_lpmd_dbus_interface_terminate\n"); ++ lpmd_terminate(); + if (intel_lpmd_dbus_exit_callback) +- intel_lpmd_dbus_exit_callback (); ++ intel_lpmd_dbus_exit_callback(); + + return TRUE; + } + + static gboolean dbus_interface_l_pm__fo_rc_e__on(PrefObject *obj, GError **error) + { +- lpmd_log_debug ("intel_lpmd_dbus_interface_lpm_enter\n"); +- lpmd_force_on (); ++ lpmd_log_debug("intel_lpmd_dbus_interface_lpm_enter\n"); ++ lpmd_force_on(); + + return TRUE; + } + + static gboolean dbus_interface_l_pm__fo_rc_e__of_f(PrefObject *obj, GError **error) + { +- lpmd_log_debug ("intel_lpmd_dbus_interface_lpm_exit\n"); +- lpmd_force_off (); ++ lpmd_log_debug("intel_lpmd_dbus_interface_lpm_exit\n"); ++ lpmd_force_off(); + + return TRUE; + } + + static gboolean dbus_interface_l_pm__au_to(PrefObject *obj, GError **error) + { +- lpmd_set_auto (); ++ lpmd_set_auto(); + return TRUE; + } + + #pragma GCC diagnostic push + + static GDBusInterfaceVTable interface_vtable; +-extern gint watcher_id; + + static GDBusNodeInfo * + lpmd_dbus_load_introspection(const gchar *filename, GError **error) +@@ -110,22 +89,21 @@ lpmd_dbus_load_introspection(const gchar *filename, GError **error) + + path = g_build_filename("/org/freedesktop/intel_lpmd", filename, NULL); + data = g_resources_lookup_data(path, G_RESOURCE_LOOKUP_FLAGS_NONE, error); +- if (data == NULL) ++ if (!data) + return NULL; + + return g_dbus_node_info_new_for_xml((gchar *)g_bytes_get_data(data, NULL), error); + } + +- + static void + lpmd_dbus_handle_method_call(GDBusConnection *connection, +- const gchar *sender, +- const gchar *object_path, +- const gchar *interface_name, +- const gchar *method_name, +- GVariant *parameters, +- GDBusMethodInvocation *invocation, +- gpointer user_data) ++ const gchar *sender, ++ const gchar *object_path, ++ const gchar *interface_name, ++ const gchar *method_name, ++ GVariant *parameters, ++ GDBusMethodInvocation *invocation, ++ gpointer user_data) + { + PrefObject *obj = PREF_OBJECT(user_data); + g_autoptr(GError) error = NULL; +@@ -156,7 +134,7 @@ lpmd_dbus_handle_method_call(GDBusConnection *connection, + } + + if (g_strcmp0(method_name, "GetState") == 0) { +- const char *state_names[] = { ++ static const char * const state_names[] = { + [LPMD_OFF] = "OFF", + [LPMD_ON] = "ON", + [LPMD_AUTO] = "AUTO", +@@ -168,7 +146,7 @@ lpmd_dbus_handle_method_call(GDBusConnection *connection, + const char *name = (state >= 0 && state <= LPMD_TERMINATE) ? state_names[state] : "UNKNOWN"; + + g_dbus_method_invocation_return_value(invocation, +- g_variant_new("(s)", name)); ++ g_variant_new("(s)", name)); + return; + } + +@@ -182,48 +160,49 @@ lpmd_dbus_handle_method_call(GDBusConnection *connection, + + static GVariant * + lpmd_dbus_handle_get_property(GDBusConnection *connection, +- const gchar *sender, +- const gchar *object_path, +- const gchar *interface_name, +- const gchar *property_name, +- GError **error, +- gpointer user_data) ++ const gchar *sender, ++ const gchar *object_path, ++ const gchar *interface_name, ++ const gchar *property_name, ++ GError **error, ++ gpointer user_data) + { + return NULL; + } + + static gboolean + lpmd_dbus_handle_set_property(GDBusConnection *connection, +- const gchar *sender, +- const gchar *object_path, +- const gchar *interface_name, +- const gchar *property_name, +- GVariant *value, +- GError **error, +- gpointer user_data) { ++ const gchar *sender, ++ const gchar *object_path, ++ const gchar *interface_name, ++ const gchar *property_name, ++ GVariant *value, ++ GError **error, ++ gpointer user_data) ++{ + return TRUE; + } + +- + static void + lpmd_dbus_on_bus_acquired(GDBusConnection *connection, +- const gchar *name, +- gpointer user_data) { +- guint registration_id; ++ const gchar *name, ++ gpointer user_data) ++{ ++ GDBusNodeInfo *introspection_data = NULL; + GDBusProxy *proxy_id = NULL; ++ guint registration_id; + GError *error = NULL; +- GDBusNodeInfo *introspection_data = NULL; + +- if (user_data == NULL) { ++ if (!user_data) { + lpmd_log_error("user_data is NULL\n"); + return; + } + + introspection_data = lpmd_dbus_load_introspection("src/intel_lpmd_dbus_interface.xml", +- &error); +- if (introspection_data == NULL || error != NULL) { ++ &error); ++ if (!introspection_data || error) { + lpmd_log_error("Couldn't create introspection data: %s:\n", +- error->message); ++ error->message); + return; + } + +@@ -244,33 +223,34 @@ lpmd_dbus_on_bus_acquired(GDBusConnection *connection, + NULL, + &error); + g_assert(registration_id > 0); +- g_assert(proxy_id != NULL); ++ g_assert(proxy_id); + } + + static void + lpmd_dbus_on_name_acquired(GDBusConnection *connection, +- const gchar *name, +- gpointer user_data) { ++ const gchar *name, ++ gpointer user_data) ++{ + } + + static void + lpmd_dbus_on_name_lost(GDBusConnection *connection, +- const gchar *name, +- gpointer user_data) ++ const gchar *name, ++ gpointer user_data) + { + g_warning("Lost the name %s\n", name); + exit(1); + } + +- + // Set up Dbus server with GDBus +-int intel_dbus_server_init(gboolean (*exit_handler)(void)) { ++int intel_dbus_server_init(gboolean (*exit_handler)(void)) ++{ + PrefObject *value_obj; + + intel_lpmd_dbus_exit_callback = exit_handler; + + value_obj = PREF_OBJECT(g_object_new(PREF_TYPE_OBJECT, NULL)); +- if (value_obj == NULL) { ++ if (!value_obj) { + lpmd_log_error("Failed to create one Value instance:\n"); + return LPMD_FATAL_ERROR; + } +@@ -290,4 +270,5 @@ int intel_dbus_server_init(gboolean (*exit_handler)(void)) { + + return LPMD_SUCCESS; + } ++ + #pragma GCC diagnostic pop +diff --git a/src/lpmd_helpers.c b/src/lpmd_helpers.c +index 2e27369..3bcd55a 100644 +--- a/src/lpmd_helpers.c ++++ b/src/lpmd_helpers.c +@@ -1,22 +1,6 @@ +-/* +- * lpmd_helper.c: helper functions +- * +- * Copyright (C) 2023 Intel Corporation. All rights reserved. +- * +- * This program is free software; you can redistribute it and/or modify +- * it under the terms of the GNU General Public License as published by +- * the Free Software Foundation; either version 2 of the License, or +- * (at your option) any later version. +- * +- * This program is distributed in the hope that it will be useful, +- * but WITHOUT ANY WARRANTY; without even the implied warranty of +- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +- * GNU General Public License for more details. +- * +- * You should have received a copy of the GNU General Public License +- * along with this program; if not, write to the Free Software +- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +- */ ++// SPDX-License-Identifier: GPL-2.0-or-later ++/* Copyright (C) 2026 Intel Corporation */ ++ + #define _GNU_SOURCE + #include + #include +@@ -52,14 +36,14 @@ int lpmd_read_str(char *path, char *str, int size) + FILE *filep; + int ret; + +- filep = fopen (path, "r"); ++ filep = fopen(path, "r"); + if (!filep) { + lpmd_log_error("Cannot open %s\n", path); + return 1; + } + +- ret = fread (str, 1, size, filep); +- fclose (filep); ++ ret = fread(str, 1, size, filep); ++ fclose(filep); + + if (ret <= 0) + return 1; +@@ -68,14 +52,14 @@ int lpmd_read_str(char *path, char *str, int size) + ret = size - 1; + str[ret - 1] = '\0'; + +- lpmd_log_debug ("Read \"%s\" from %s\n", str, path); ++ lpmd_log_debug("Read \"%s\" from %s\n", str, path); + return 0; + } + + static int _write_str(const char *name, char *str, int print_level, int log_level, const char *mode) + { +- FILE *filep; + char prefix[16]; ++ FILE *filep; + int i, ret; + + if (print_level >= 15) +@@ -83,42 +67,41 @@ static int _write_str(const char *name, char *str, int print_level, int log_leve + + if (print_level <= 0) { + prefix[0] = '\0'; +- } +- else { ++ } else { + for (i = 0; i < print_level; i++) + prefix[i] = '\t'; + prefix[i] = '\0'; + } + +- filep = fopen (name, mode); ++ filep = fopen(name, mode); + if (!filep) { +- lpmd_log_error ("%sOpen %s failed\n", prefix, name); ++ lpmd_log_error("%sOpen %s failed\n", prefix, name); + return 1; + } + +- ret = fprintf (filep, "%s", str); ++ ret = fprintf(filep, "%s", str); + if (ret <= 0) { +- lpmd_log_error ("%sWrite \"%s\" to %s failed, strlen %zu, ret %d\n", prefix, str, name, +- strlen (str), ret); +- fclose (filep); ++ lpmd_log_error("%sWrite \"%s\" to %s failed, strlen %zu, ret %d\n", ++ prefix, str, name, strlen(str), ret); ++ fclose(filep); + return 1; + } + + switch (print_level) { +- case LPMD_LOG_INFO: +- lpmd_log_info ("%sWrite \"%s\" to %s\n", prefix, str, name); +- break; +- case LPMD_LOG_DEBUG: +- lpmd_log_debug ("%sWrite \"%s\" to %s\n", prefix, str, name); +- break; +- case LPMD_LOG_MSG: +- lpmd_log_msg ("%sWrite \"%s\" to %s\n", prefix, str, name); +- break; +- default: +- break; ++ case LPMD_LOG_INFO: ++ lpmd_log_info("%sWrite \"%s\" to %s\n", prefix, str, name); ++ break; ++ case LPMD_LOG_DEBUG: ++ lpmd_log_debug("%sWrite \"%s\" to %s\n", prefix, str, name); ++ break; ++ case LPMD_LOG_MSG: ++ lpmd_log_msg("%sWrite \"%s\" to %s\n", prefix, str, name); ++ break; ++ default: ++ break; + } + +- fclose (filep); ++ fclose(filep); + return 0; + } + +@@ -127,7 +110,7 @@ int lpmd_write_str(const char *name, char *str, int print_level) + if (!name || !str) + return 0; + +- return _write_str (name, str, print_level, 2, "r+"); ++ return _write_str(name, str, print_level, 2, "r+"); + } + + int lpmd_write_str_append(const char *name, char *str, int print_level) +@@ -135,7 +118,7 @@ int lpmd_write_str_append(const char *name, char *str, int print_level) + if (!name || !str) + return 0; + +- return _write_str (name, str, print_level, 2, "a+"); ++ return _write_str(name, str, print_level, 2, "a+"); + } + + int lpmd_write_str_verbose(const char *name, char *str, int print_level) +@@ -143,7 +126,7 @@ int lpmd_write_str_verbose(const char *name, char *str, int print_level) + if (!name || !str) + return 0; + +- return _write_str (name, str, print_level, 3, "r+"); ++ return _write_str(name, str, print_level, 3, "r+"); + } + + int lpmd_write_int(const char *name, int val, int print_level) +@@ -156,62 +139,60 @@ int lpmd_write_int(const char *name, int val, int print_level) + if (!name) + return 1; + +- clock_gettime (CLOCK_MONOTONIC, &tp1); ++ clock_gettime(CLOCK_MONOTONIC, &tp1); + + if (print_level >= 15) + return 1; + + if (print_level < 0) { + prefix[0] = '\0'; +- } +- else { ++ } else { + for (i = 0; i < print_level; i++) + prefix[i] = '\t'; + prefix[i] = '\0'; + } + +- filep = fopen (name, "r+"); ++ filep = fopen(name, "r+"); + if (!filep) { +- lpmd_log_error ("%sOpen %s failed\n", prefix, name); ++ lpmd_log_error("%sOpen %s failed\n", prefix, name); + return 1; + } + +- ret = fprintf (filep, "%d", val); ++ ret = fprintf(filep, "%d", val); + if (ret <= 0) { +- lpmd_log_error ("%sWrite \"%d\" to %s failed, ret %d\n", prefix, val, name, ret); +- fclose (filep); ++ lpmd_log_error("%sWrite \"%d\" to %s failed, ret %d\n", prefix, val, name, ret); ++ fclose(filep); + return 1; + } + +- clock_gettime (CLOCK_MONOTONIC, &tp2); ++ clock_gettime(CLOCK_MONOTONIC, &tp2); + + switch (print_level) { +- case LPMD_LOG_INFO: +- lpmd_log_info ("%sWrite \"%d\" to %s (%lu ns)\n", prefix, val, name, +- 1000000000 * (tp2.tv_sec - tp1.tv_sec) + tp2.tv_nsec - tp1.tv_nsec); +- break; +- case LPMD_LOG_DEBUG: +- lpmd_log_debug ("%sWrite \"%d\" to %s (%lu ns)\n", prefix, val, name, +- 1000000000 * (tp2.tv_sec - tp1.tv_sec) + tp2.tv_nsec - tp1.tv_nsec); +- break; +- case LPMD_LOG_MSG: +- lpmd_log_msg ("%sWrite \"%d\" to %s (%lu ns)\n", prefix, val, name, +- 1000000000 * (tp2.tv_sec - tp1.tv_sec) + tp2.tv_nsec - tp1.tv_nsec); +- break; +- default: +- break; ++ case LPMD_LOG_INFO: ++ lpmd_log_info("%sWrite \"%d\" to %s (%lu ns)\n", prefix, val, name, ++ 1000000000 * (tp2.tv_sec - tp1.tv_sec) + tp2.tv_nsec - tp1.tv_nsec); ++ break; ++ case LPMD_LOG_DEBUG: ++ lpmd_log_debug("%sWrite \"%d\" to %s (%lu ns)\n", prefix, val, name, ++ 1000000000 * (tp2.tv_sec - tp1.tv_sec) + tp2.tv_nsec - tp1.tv_nsec); ++ break; ++ case LPMD_LOG_MSG: ++ lpmd_log_msg("%sWrite \"%d\" to %s (%lu ns)\n", prefix, val, name, ++ 1000000000 * (tp2.tv_sec - tp1.tv_sec) + tp2.tv_nsec - tp1.tv_nsec); ++ break; ++ default: ++ break; + } + +- fclose (filep); ++ fclose(filep); + return 0; +- + } + + int lpmd_read_int(const char *name, int *val, int print_level) + { +- FILE *filep; + char prefix[16]; + int i, t, ret; ++ FILE *filep; + + if (!name || !val) + return 1; +@@ -221,35 +202,33 @@ int lpmd_read_int(const char *name, int *val, int print_level) + + if (print_level < 0) { + prefix[0] = '\0'; +- } +- else { ++ } else { + for (i = 0; i < print_level; i++) + prefix[i] = '\t'; + prefix[i] = '\0'; + } + +- filep = fopen (name, "r"); ++ filep = fopen(name, "r"); + if (!filep) { +- lpmd_log_error ("%sOpen %s failed\n", prefix, name); ++ lpmd_log_error("%sOpen %s failed\n", prefix, name); + return 1; + } + +- ret = fscanf (filep, "%d", &t); ++ ret = fscanf(filep, "%d", &t); + if (ret != 1) { +- lpmd_log_error ("%sRead %s failed, ret %d\n", prefix, name, ret); +- fclose (filep); ++ lpmd_log_error("%sRead %s failed, ret %d\n", prefix, name, ret); ++ fclose(filep); + return 1; + } + +- fclose (filep); ++ fclose(filep); + + *val = t; + + if (print_level >= 0) +- lpmd_log_debug ("%sRead \"%d\" from %s\n", prefix, *val, name); ++ lpmd_log_debug("%sRead \"%d\" from %s\n", prefix, *val, name); + + return 0; +- + } + + int lpmd_write_yn(const char *name, int val, int print_level) +@@ -264,7 +243,7 @@ int lpmd_write_yn(const char *name, int val, int print_level) + if (ret < 0) + return 1; + +- return _write_str (name, str, print_level, 2, "r+"); ++ return _write_str(name, str, print_level, 2, "r+"); + } + + int lpmd_read_yn(const char *name, int *val, int print_level) +@@ -281,49 +260,47 @@ int lpmd_read_yn(const char *name, int *val, int print_level) + + if (print_level < 0) { + prefix[0] = '\0'; +- } +- else { ++ } else { + for (i = 0; i < print_level; i++) + prefix[i] = '\t'; + prefix[i] = '\0'; + } + +- filep = fopen (name, "r"); ++ filep = fopen(name, "r"); + if (!filep) { +- lpmd_log_error ("%sOpen %s failed\n", prefix, name); ++ lpmd_log_error("%sOpen %s failed\n", prefix, name); + return 1; + } + + ret = fgetc(filep); + if (ret == EOF) { +- if (feof(filep)) { +- lpmd_log_error ("%sRead %s failed due to EOF\n", prefix, name); +- } else if (ferror(filep)) { +- lpmd_log_error ("%sRead %s failed, error %s\n", prefix, name, strerror(errno)); +- } +- fclose (filep); ++ if (feof(filep)) ++ lpmd_log_error("%sRead %s failed due to EOF\n", prefix, ++ name); ++ else if (ferror(filep)) ++ lpmd_log_error("%sRead %s failed, error %s\n", prefix, ++ name, strerror(errno)); ++ fclose(filep); + return 1; + } + +- fclose (filep); ++ fclose(filep); + + if (ret == 'Y') { + *val = 1; + } else if (ret == 'N') { + *val = 0; + } else { +- lpmd_log_error ("%sRead %s failed, read %c\n", prefix, name, ret); ++ lpmd_log_error("%sRead %s failed, read %c\n", prefix, name, ret); + return 1; + } + + if (print_level >= 0) +- lpmd_log_debug ("%sRead \"%c\" from %s\n", prefix, *val, name); ++ lpmd_log_debug("%sRead \"%c\" from %s\n", prefix, *val, name); + + return 0; +- + } + +- + /* + * lpmd_open does not require print on success + * print_level: -1: don't print on error +@@ -342,46 +319,46 @@ int lpmd_open(const char *name, int print_level) + + if (print_level < 0) { + prefix[0] = '\0'; +- } +- else { ++ } else { + for (i = 0; i < print_level; i++) + prefix[i] = '\t'; + prefix[i] = '\0'; + } + +- filep = fopen (name, "r"); ++ filep = fopen(name, "r"); + if (!filep) { + if (print_level >= 0) +- lpmd_log_error ("%sOpen %s failed\n", prefix, name); ++ lpmd_log_error("%sOpen %s failed\n", prefix, name); + return 1; + } + +- fclose (filep); ++ fclose(filep); + return 0; + } + +-char* get_time(void) ++char *get_time(void) + { + static time_t time_cur; + +- time_cur = time (NULL); +- return ctime (&time_cur); ++ time_cur = time(NULL); ++ return ctime(&time_cur); + } + + static struct timespec timespec; + static char time_buf[MAX_STR_LENGTH]; + void time_start(void) + { +- clock_gettime (CLOCK_MONOTONIC, ×pec); ++ clock_gettime(CLOCK_MONOTONIC, ×pec); + } + +-char* time_delta(void) ++char *time_delta(void) + { + static struct timespec tp1; +- clock_gettime (CLOCK_MONOTONIC, &tp1); +- snprintf (time_buf, MAX_STR_LENGTH, "%ld ns", +- 1000000000 * (tp1.tv_sec - timespec.tv_sec) + tp1.tv_nsec - timespec.tv_nsec); +- memset (×pec, 0, sizeof(timespec)); ++ ++ clock_gettime(CLOCK_MONOTONIC, &tp1); ++ snprintf(time_buf, MAX_STR_LENGTH, "%ld ns", ++ 1000000000 * (tp1.tv_sec - timespec.tv_sec) + tp1.tv_nsec - timespec.tv_nsec); ++ memset(×pec, 0, sizeof(timespec)); + return time_buf; + } + +diff --git a/src/lpmd_hfi.c b/src/lpmd_hfi.c +index 486b198..db16c00 100644 +--- a/src/lpmd_hfi.c ++++ b/src/lpmd_hfi.c +@@ -1,27 +1,10 @@ +-/* +- * lpmd_hfi.c: intel_lpmd HFI monitor +- * +- * Copyright (C) 2023 Intel Corporation. All rights reserved. +- * +- * This program is free software; you can redistribute it and/or modify +- * it under the terms of the GNU General Public License as published by +- * the Free Software Foundation; either version 2 of the License, or +- * (at your option) any later version. +- * +- * This program is distributed in the hope that it will be useful, +- * but WITHOUT ANY WARRANTY; without even the implied warranty of +- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +- * GNU General Public License for more details. +- * +- * You should have received a copy of the GNU General Public License +- * along with this program; if not, write to the Free Software +- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +- * +- * This file processes HFI messages from the firmware. When the EE column for +- * a CPU is 255, that CPU will be in allowed list to run all thread. +- */ ++// SPDX-License-Identifier: GPL-2.0-or-later ++/* Copyright(c) 2023 Intel Corporation */ + ++#ifndef _GNU_SOURCE + #define _GNU_SOURCE ++#endif ++ + #include + #include + #include +@@ -86,32 +69,33 @@ static int seq_check_handler(struct nl_msg *msg, void *arg) + } + + static int send_and_recv_msgs(struct hfi_event_data *drv, struct nl_msg *msg, +- int (*valid_handler)(struct nl_msg*, void*), void *valid_data) ++ int (*valid_handler)(struct nl_msg*, void*), ++ void *valid_data) + { + struct nl_cb *cb; + int err = -ENOMEM; + +- cb = nl_cb_clone (drv->nl_cb); ++ cb = nl_cb_clone(drv->nl_cb); + if (!cb) + goto out; + +- err = nl_send_auto_complete (drv->nl_handle, msg); ++ err = nl_send_auto_complete(drv->nl_handle, msg); + if (err < 0) + goto out; + + err = 1; + +- nl_cb_err (cb, NL_CB_CUSTOM, error_handler, &err); +- nl_cb_set (cb, NL_CB_FINISH, NL_CB_CUSTOM, finish_handler, &err); +- nl_cb_set (cb, NL_CB_ACK, NL_CB_CUSTOM, ack_handler, &err); ++ nl_cb_err(cb, NL_CB_CUSTOM, error_handler, &err); ++ nl_cb_set(cb, NL_CB_FINISH, NL_CB_CUSTOM, finish_handler, &err); ++ nl_cb_set(cb, NL_CB_ACK, NL_CB_CUSTOM, ack_handler, &err); + + if (valid_handler) +- nl_cb_set (cb, NL_CB_VALID, NL_CB_CUSTOM, valid_handler, valid_data); ++ nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, valid_handler, valid_data); + + while (err > 0) +- err = nl_recvmsgs (drv->nl_handle, cb); +-out: nl_cb_put (cb); +- nlmsg_free (msg); ++ err = nl_recvmsgs(drv->nl_handle, cb); ++out: nl_cb_put(cb); ++ nlmsg_free(msg); + return err; + } + +@@ -124,48 +108,52 @@ static int family_handler(struct nl_msg *msg, void *arg) + { + struct family_data *res = arg; + struct nlattr *tb[CTRL_ATTR_MAX + 1]; +- struct genlmsghdr *gnlh = nlmsg_data (nlmsg_hdr (msg)); ++ struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg)); + struct nlattr *mcgrp; + int i; + +- nla_parse (tb, CTRL_ATTR_MAX, genlmsg_attrdata (gnlh, 0), genlmsg_attrlen (gnlh, 0), NULL); ++ nla_parse(tb, CTRL_ATTR_MAX, genlmsg_attrdata(gnlh, 0), ++ genlmsg_attrlen(gnlh, 0), NULL); + if (!tb[CTRL_ATTR_MCAST_GROUPS]) + return NL_SKIP; + +- nla_for_each_nested (mcgrp, tb[CTRL_ATTR_MCAST_GROUPS], i) +- { ++ nla_for_each_nested(mcgrp, tb[CTRL_ATTR_MCAST_GROUPS], i) { + struct nlattr *tb2[CTRL_ATTR_MCAST_GRP_MAX + 1]; +- nla_parse (tb2, CTRL_ATTR_MCAST_GRP_MAX, nla_data (mcgrp), nla_len (mcgrp), NULL); +- if (!tb2[CTRL_ATTR_MCAST_GRP_NAME] || !tb2[CTRL_ATTR_MCAST_GRP_ID] +- || strncmp (nla_data (tb2[CTRL_ATTR_MCAST_GRP_NAME]), res->group, +- nla_len (tb2[CTRL_ATTR_MCAST_GRP_NAME])) != 0) ++ ++ nla_parse(tb2, CTRL_ATTR_MCAST_GRP_MAX, ++ nla_data(mcgrp), nla_len(mcgrp), NULL); ++ if (!tb2[CTRL_ATTR_MCAST_GRP_NAME] || ++ !tb2[CTRL_ATTR_MCAST_GRP_ID] || ++ strncmp(nla_data(tb2[CTRL_ATTR_MCAST_GRP_NAME]), res->group, ++ nla_len(tb2[CTRL_ATTR_MCAST_GRP_NAME])) != 0) + continue; +- res->id = nla_get_u32 (tb2[CTRL_ATTR_MCAST_GRP_ID]); ++ res->id = nla_get_u32(tb2[CTRL_ATTR_MCAST_GRP_ID]); + break; + }; + + return 0; + } + +-static int nl_get_multicast_id(struct hfi_event_data *drv, const char *family, const char *group) ++static int nl_get_multicast_id(struct hfi_event_data *drv, const char *family, ++ const char *group) + { + struct nl_msg *msg; + int ret = -1; + struct family_data res = { group, -ENOENT }; + +- msg = nlmsg_alloc (); ++ msg = nlmsg_alloc(); + if (!msg) + return -ENOMEM; +- genlmsg_put (msg, 0, 0, genl_ctrl_resolve (drv->nl_handle, "nlctrl"), 0, 0, CTRL_CMD_GETFAMILY, +- 0); +- NLA_PUT_STRING (msg, CTRL_ATTR_FAMILY_NAME, family); ++ genlmsg_put(msg, 0, 0, genl_ctrl_resolve(drv->nl_handle, "nlctrl"), ++ 0, 0, CTRL_CMD_GETFAMILY, 0); ++ NLA_PUT_STRING(msg, CTRL_ATTR_FAMILY_NAME, family); + +- ret = send_and_recv_msgs (drv, msg, family_handler, &res); ++ ret = send_and_recv_msgs(drv, msg, family_handler, &res); + msg = NULL; + if (ret == 0) + ret = res.id; + +-nla_put_failure: nlmsg_free (msg); ++nla_put_failure: nlmsg_free(msg); + return ret; + } + +@@ -206,48 +194,88 @@ static char *update_one_cpu(struct perf_cap *perf_cap) + + static void process_one_event(int first, int last, int nr) + { +- + /* Need to update more CPUs */ +- if (nr == 16 && last != get_max_online_cpu ()) ++ if (nr == 16 && last != get_max_online_cpu()) + return; + + if (cpumask_has_cpu(CPUMASK_HFI)) { + /* Ignore duplicate event */ +- if (cpumask_equal (CPUMASK_HFI_LAST, CPUMASK_HFI )) { +- lpmd_log_debug ("\tDuplicated HFI LPM hints ignored\n\n"); ++ if (cpumask_equal(CPUMASK_HFI_LAST, CPUMASK_HFI)) { ++ lpmd_log_debug("\tDuplicated HFI LPM hints ignored\n\n"); + return; + } +- lpmd_log_debug ("\tDetect HFI LPM event\n"); ++ lpmd_log_debug("\tDetect HFI LPM event\n"); + update_reason(UPDATE_HFI); + cpumask_copy(CPUMASK_HFI, CPUMASK_HFI_LAST); +- } +- else if (cpumask_has_cpu(CPUMASK_HFI_BANNED)) { ++ } else if (cpumask_has_cpu(CPUMASK_HFI_BANNED)) { + cpumask_exclude_copy(CPUMASK_ONLINE, CPUMASK_HFI, CPUMASK_HFI_BANNED); + /* Ignore duplicate event */ +- if (cpumask_equal (CPUMASK_HFI_LAST, CPUMASK_HFI )) { +- lpmd_log_debug ("\tDuplicated HFI BANNED hints ignored\n\n"); ++ if (cpumask_equal(CPUMASK_HFI_LAST, CPUMASK_HFI)) { ++ lpmd_log_debug("\tDuplicated HFI BANNED hints ignored\n\n"); + return; + } +- lpmd_log_debug ("\tDetect HFI LPM event with banned CPUs\n"); ++ lpmd_log_debug("\tDetect HFI LPM event with banned CPUs\n"); + update_reason(UPDATE_HFI); + cpumask_copy(CPUMASK_HFI, CPUMASK_HFI_LAST); +- } +- else if (cpumask_has_cpu(CPUMASK_HFI_LAST)) { +- lpmd_log_debug ("\tHFI LPM recover\n"); ++ } else if (cpumask_has_cpu(CPUMASK_HFI_LAST)) { ++ lpmd_log_debug("\tHFI LPM recover\n"); + // Don't override the DETECT_LPM_CPU_DEFAULT so it is auto recovered + cpumask_copy(CPUMASK_ONLINE, CPUMASK_HFI); + update_reason(UPDATE_HFI); +- cpumask_reset (CPUMASK_HFI_LAST); ++ cpumask_reset(CPUMASK_HFI_LAST); ++ } else { ++ lpmd_log_info("\t\t\tUnsupported HFI event ignored\n"); + } +- else { +- lpmd_log_info ("\t\t\tUnsupported HFI event ignored\n"); ++} ++ ++static void __handle_event(struct nlattr *cap, int *index, ++ int *offset, char *buf, struct perf_cap *perf_cap, ++ int *first_cpu, int *last_cpu, int *nr_cpus) ++{ ++ switch (*index) { ++ case 0: ++ *offset += snprintf(buf + *offset, MAX_STR_LENGTH - ++ *offset, "\tCPU %3d: ", nla_get_u32(cap)); ++ perf_cap->cpu = nla_get_u32(cap); ++ break; ++ case 1: ++ *offset += snprintf(buf + *offset, MAX_STR_LENGTH - ++ *offset, " PERF [%4d] ", nla_get_u32(cap)); ++ perf_cap->perf = nla_get_u32(cap); ++ break; ++ case 2: ++ *offset += snprintf(buf + *offset, MAX_STR_LENGTH - ++ *offset, " EFF [%4d] ", nla_get_u32(cap)); ++ perf_cap->eff = nla_get_u32(cap); ++ break; ++ default: ++ break; ++ } ++ *index += 1; ++ ++ if (*index == 3) { ++ char *str; ++ ++ str = update_one_cpu(perf_cap); ++ *offset += snprintf(buf + *offset, MAX_STR_LENGTH - ++ *offset, " TYPE [%s]", str); ++ buf[MAX_STR_LENGTH - 1] = '\0'; ++ lpmd_log_debug("\t\t\t%s\n", buf); ++ ++ *index = 0; ++ *offset = 0; ++ ++ if (*first_cpu == -1) ++ *first_cpu = perf_cap->cpu; ++ *last_cpu = perf_cap->cpu; ++ *nr_cpus += 1; + } + } + + static int handle_event(struct nl_msg *n, void *arg) + { +- struct nlmsghdr *nlh = nlmsg_hdr (n); +- struct genlmsghdr *genlhdr = genlmsg_hdr (nlh); ++ struct nlmsghdr *nlh = nlmsg_hdr(n); ++ struct genlmsghdr *genlhdr = genlmsg_hdr(nlh); + struct nlattr *attrs[THERMAL_GENL_ATTR_MAX + 1]; + struct nlattr *cap; + struct perf_cap perf_cap; +@@ -258,62 +286,26 @@ static int handle_event(struct nl_msg *n, void *arg) + if (genlhdr->cmd != THERMAL_GENL_EVENT_CAPACITY_CHANGE) + return 0; + +- if (genlmsg_parse (nlh, 0, attrs, THERMAL_GENL_ATTR_MAX, NULL)) ++ if (genlmsg_parse(nlh, 0, attrs, THERMAL_GENL_ATTR_MAX, NULL)) + return -1; + +- perf_cap.cpu = perf_cap.perf = perf_cap.eff = -1; +- +- nla_for_each_nested (cap, attrs[THERMAL_GENL_ATTR_CAPACITY], j) +- { +- +- switch (index) { +- case 0: +- offset += snprintf (buf + offset, MAX_STR_LENGTH - offset, "\tCPU %3d: ", +- nla_get_u32 (cap)); +- perf_cap.cpu = nla_get_u32 (cap); +- break; +- case 1: +- offset += snprintf (buf + offset, MAX_STR_LENGTH - offset, " PERF [%4d] ", +- nla_get_u32 (cap)); +- perf_cap.perf = nla_get_u32 (cap); +- break; +- case 2: +- offset += snprintf (buf + offset, MAX_STR_LENGTH - offset, " EFF [%4d] ", +- nla_get_u32 (cap)); +- perf_cap.eff = nla_get_u32 (cap); +- break; +- default: +- break; +- } +- index++; +- +- if (index == 3) { +- char *str; +- +- str = update_one_cpu (&perf_cap); +- offset += snprintf (buf + offset, MAX_STR_LENGTH - offset, " TYPE [%s]", str); +- buf[MAX_STR_LENGTH - 1] = '\0'; +- lpmd_log_debug ("\t\t\t%s\n", buf); ++ perf_cap.eff = -1; ++ perf_cap.perf = -1; ++ perf_cap.cpu = -1; + +- index = 0; +- offset = 0; +- +- if (first_cpu == -1) +- first_cpu = perf_cap.cpu; +- last_cpu = perf_cap.cpu; +- nr_cpus++; +- } +- } +- process_one_event (first_cpu, last_cpu, nr_cpus); ++ nla_for_each_nested(cap, attrs[THERMAL_GENL_ATTR_CAPACITY], j) ++ __handle_event(cap, &index, &offset, buf, &perf_cap, ++ &first_cpu, &last_cpu, &nr_cpus); ++ process_one_event(first_cpu, last_cpu, nr_cpus); + + return 0; + } + +-static int done = 0; ++static int done; + + int hfi_kill(void) + { +- nl_socket_free (drv.nl_handle); ++ nl_socket_free(drv.nl_handle); + done = 1; + return 0; + } +@@ -323,7 +315,7 @@ int hfi_update(void) + int err = 0; + + while (!err) +- err = nl_recvmsgs (drv.nl_handle, drv.nl_cb); ++ err = nl_recvmsgs(drv.nl_handle, drv.nl_cb); + + return 0; + } +@@ -336,45 +328,46 @@ int hfi_init(void) + + cpumask_reset(CPUMASK_HFI_LAST); + +- signal (SIGPIPE, SIG_IGN); ++ signal(SIGPIPE, SIG_IGN); + +- sock = nl_socket_alloc (); ++ sock = nl_socket_alloc(); + if (!sock) { +- lpmd_log_error ("nl_socket_alloc failed\n"); ++ lpmd_log_error("nl_socket_alloc failed\n"); + goto err_proc; + } + +- if (genl_connect (sock)) { +- lpmd_log_error ("genl_connect(sk_event) failed\n"); ++ if (genl_connect(sock)) { ++ lpmd_log_error("genl_connect(sk_event) failed\n"); + goto err_proc; + } + + drv.nl_handle = sock; +- drv.nl_cb = cb = nl_cb_alloc (NL_CB_DEFAULT); +- if (drv.nl_cb == NULL) { +- lpmd_log_error ("Failed to allocate netlink callbacks"); ++ cb = nl_cb_alloc(NL_CB_DEFAULT); ++ drv.nl_cb = cb; ++ if (!drv.nl_cb) { ++ lpmd_log_error("Failed to allocate netlink callbacks"); + goto err_proc; + } + +- mcast_id = nl_get_multicast_id (&drv, THERMAL_GENL_FAMILY_NAME, +- THERMAL_GENL_EVENT_GROUP_NAME); ++ mcast_id = nl_get_multicast_id(&drv, THERMAL_GENL_FAMILY_NAME, ++ THERMAL_GENL_EVENT_GROUP_NAME); + if (mcast_id < 0) { +- lpmd_log_error ("nl_get_multicast_id failed\n"); ++ lpmd_log_error("nl_get_multicast_id failed\n"); + goto err_proc; + } + +- if (nl_socket_add_membership (sock, mcast_id)) { +- lpmd_log_error ("nl_socket_add_membership failed"); ++ if (nl_socket_add_membership(sock, mcast_id)) { ++ lpmd_log_error("nl_socket_add_membership failed"); + goto err_proc; + } + +- nl_cb_set (cb, NL_CB_SEQ_CHECK, NL_CB_CUSTOM, seq_check_handler, &done); +- nl_cb_set (cb, NL_CB_VALID, NL_CB_CUSTOM, handle_event, NULL); ++ nl_cb_set(cb, NL_CB_SEQ_CHECK, NL_CB_CUSTOM, seq_check_handler, &done); ++ nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, handle_event, NULL); + +- nl_socket_set_nonblocking (sock); ++ nl_socket_set_nonblocking(sock); + + if (drv.nl_handle) +- return nl_socket_get_fd (drv.nl_handle); ++ return nl_socket_get_fd(drv.nl_handle); + + err_proc: return -1; + } +diff --git a/src/lpmd_irq.c b/src/lpmd_irq.c +index 6f390ce..4b1f043 100644 +--- a/src/lpmd_irq.c ++++ b/src/lpmd_irq.c +@@ -1,22 +1,6 @@ +-/* +- * irq.c: irq related processing +- * +- * Copyright (C) 2023 Intel Corporation. All rights reserved. +- * +- * This program is free software; you can redistribute it and/or modify +- * it under the terms of the GNU General Public License as published by +- * the Free Software Foundation; either version 2 of the License, or +- * (at your option) any later version. +- * +- * This program is distributed in the hope that it will be useful, +- * but WITHOUT ANY WARRANTY; without even the implied warranty of +- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +- * GNU General Public License for more details. +- * +- * You should have received a copy of the GNU General Public License +- * along with this program; if not, write to the Free Software +- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +- */ ++// SPDX-License-Identifier: GPL-2.0-or-later ++/* Copyright (C) 2026 Intel Corporation */ ++ + #define _GNU_SOURCE + #include + #include +@@ -63,7 +47,6 @@ struct info_irqs { + struct info_irqs info_irqs; + struct info_irqs *info = &info_irqs; + +- + /* Interrupt Management */ + #define SOCKET_PATH "irqbalance" + #define SOCKET_TMPFS "/run/irqbalance" +@@ -73,15 +56,15 @@ static int irqbalance_ban_cpus(char *irq_str) + char socket_cmd[MAX_STR_LENGTH]; + int offset; + +- lpmd_log_debug ("\tUpdate IRQ affinity (irqbalance)\n"); +- offset = snprintf (socket_cmd, MAX_STR_LENGTH, "settings cpus %s", irq_str); ++ lpmd_log_debug("\tUpdate IRQ affinity (irqbalance)\n"); ++ offset = snprintf(socket_cmd, MAX_STR_LENGTH, "settings cpus %s", irq_str); + if (offset >= MAX_STR_LENGTH) + offset = MAX_STR_LENGTH - 1; + + socket_cmd[offset] = '\0'; +- socket_send_cmd (irq_socket_name, socket_cmd); ++ socket_send_cmd(irq_socket_name, socket_cmd); + +- lpmd_log_debug ("\tSend socket command %s\n", socket_cmd); ++ lpmd_log_debug("\tSend socket command %s\n", socket_cmd); + return 0; + } + +@@ -90,16 +73,16 @@ static int native_restore_irqs(void) + char path[MAX_STR_LENGTH]; + int i; + +- lpmd_log_debug ("\tRestore IRQ affinity (native)\n"); ++ lpmd_log_debug("\tRestore IRQ affinity (native)\n"); + + for (i = 0; i < info->nr_irqs; i++) { + char *str = info->irq[i].affinity; + +- snprintf (path, MAX_STR_LENGTH, "/proc/irq/%i/smp_affinity", info->irq[i].irq); ++ snprintf(path, MAX_STR_LENGTH, "/proc/irq/%i/smp_affinity", info->irq[i].irq); + +- lpmd_write_str (path, str, LPMD_LOG_DEBUG); ++ lpmd_write_str(path, str, LPMD_LOG_DEBUG); + } +- memset (info, 0, sizeof(*info)); ++ memset(info, 0, sizeof(*info)); + return 0; + } + +@@ -107,80 +90,79 @@ static int irq_updated; + + static int update_one_irq(int irq, char *irq_str) + { +- FILE *filep; +- size_t size = 0; + char path[MAX_STR_LENGTH]; + char *str = NULL; ++ size_t size = 0; ++ FILE *filep; + + if (info->nr_irqs >= (MAX_IRQS - 1)) { +- lpmd_log_error ("Too many IRQs\n"); ++ lpmd_log_error("Too many IRQs\n"); + return -1; + } + +- +- snprintf (path, MAX_STR_LENGTH, "/proc/irq/%i/smp_affinity", irq); ++ snprintf(path, MAX_STR_LENGTH, "/proc/irq/%i/smp_affinity", irq); + + if (!irq_updated) { + info->irq[info->nr_irqs].irq = irq; +- filep = fopen (path, "r"); ++ filep = fopen(path, "r"); + if (!filep) + return -1; + +- if (getline (&str, &size, filep) <= 0) { +- lpmd_log_error ("Failed to get IRQ%d smp_affinity\n", irq); +- free (str); +- fclose (filep); ++ if (getline(&str, &size, filep) <= 0) { ++ lpmd_log_error("Failed to get IRQ%d smp_affinity\n", irq); ++ free(str); ++ fclose(filep); + return -1; + } + +- fclose (filep); ++ fclose(filep); + +- snprintf (info->irq[info->nr_irqs].affinity, MAX_STR_LENGTH, "%s", str); ++ snprintf(info->irq[info->nr_irqs].affinity, MAX_STR_LENGTH, "%s", str); + +- free (str); ++ free(str); + + /* Remove the Newline */ +- size = strnlen (info->irq[info->nr_irqs].affinity, MAX_STR_LENGTH); ++ size = strnlen(info->irq[info->nr_irqs].affinity, MAX_STR_LENGTH); + info->irq[info->nr_irqs].affinity[size - 1] = '\0'; + + info->nr_irqs++; + } + +- return lpmd_write_str (path, irq_str, LPMD_LOG_DEBUG); ++ return lpmd_write_str(path, irq_str, LPMD_LOG_DEBUG); + } + + static int native_update_irqs(char *irq_str) + { +- FILE *filep; + char *line = NULL; + size_t size = 0; ++ FILE *filep; + +- lpmd_log_debug ("\tUpdate IRQ affinity (native)\n"); ++ lpmd_log_debug("\tUpdate IRQ affinity (native)\n"); + +- filep = fopen ("/proc/interrupts", "r"); ++ filep = fopen("/proc/interrupts", "r"); + if (!filep) { +- perror ("Error open /proc/interrupts\n"); ++ perror("Error open /proc/interrupts\n"); + return -1; + } + + /* first line is the header we don't need; nuke it */ +- if (getline (&line, &size, filep) <= 0) { +- perror ("Error getline\n"); +- free (line); +- fclose (filep); ++ if (getline(&line, &size, filep) <= 0) { ++ perror("Error getline\n"); ++ free(line); ++ fclose(filep); + return -1; + } +- free (line); ++ free(line); + +- while (!feof (filep)) { ++ while (!feof(filep)) { + int number; + char *c; + + line = NULL; + size = 0; + +- if (getline (&line, &size, filep) <= 0) { +- free (line); ++ if (getline(&line, &size, filep) <= 0) { ++ free(line); + break; + } + +@@ -190,92 +172,91 @@ static int native_update_irqs(char *irq_str) + c++; + + if (!isdigit(*c)) { +- free (line); ++ free(line); + break; + } +- c = strchr (line, ':'); ++ c = strchr(line, ':'); + if (!c) { +- free (line); ++ free(line); + continue; + } + + *c = 0; +- number = strtoul (line, NULL, 10); ++ number = strtoul(line, NULL, 10); + +- update_one_irq (number, irq_str); +- free (line); ++ update_one_irq(number, irq_str); ++ free(line); + } + +- fclose (filep); ++ fclose(filep); + + irq_updated = 1; + return 0; + } + +-int process_irq(lpmd_config_state_t *state) ++int process_irq(struct lpmd_config_state_t *state) + { + switch (state->irq_migrate) { +- case SETTING_IGNORE: +- lpmd_log_info ("Ignore IRQ migration\n"); +- return 0; +- case SETTING_RESTORE: +- if (irqbalance_pid == -1) +- native_restore_irqs(); +- else +- irqbalance_ban_cpus("NULL"); +- return 0; +- default: +- if (state->cpumask_idx == CPUMASK_NONE) +- return 0; +- if (irqbalance_pid == -1) +- native_update_irqs(get_proc_irq_str(state->cpumask_idx)); +- else +- irqbalance_ban_cpus(get_irqbalance_str(state->cpumask_idx)); ++ case SETTING_IGNORE: ++ lpmd_log_info("Ignore IRQ migration\n"); ++ return 0; ++ case SETTING_RESTORE: ++ if (irqbalance_pid == -1) ++ native_restore_irqs(); ++ else ++ irqbalance_ban_cpus("NULL"); ++ return 0; ++ default: ++ if (state->cpumask_idx == CPUMASK_NONE) + return 0; +- } ++ if (irqbalance_pid == -1) ++ native_update_irqs(get_proc_irq_str(state->cpumask_idx)); ++ else ++ irqbalance_ban_cpus(get_irqbalance_str(state->cpumask_idx)); ++ return 0; ++ } + return 0; + } + +-int irq_init (void) ++int irq_init(void) + { + DIR *dir; + int socket_fd; + int ret; + +- lpmd_log_info ("Detecting IRQs ...\n"); ++ lpmd_log_info("Detecting IRQs ...\n"); + +- dir = opendir ("/run/irqbalance"); ++ dir = opendir("/run/irqbalance"); + if (dir) { + struct dirent *entry; + + do { +- entry = readdir (dir); ++ entry = readdir(dir); + if (entry) { +- if (!strncmp (entry->d_name, "irqbalance", 10)) { +- ret = sscanf (entry->d_name, "irqbalance%d.sock", &irqbalance_pid); ++ if (!strncmp(entry->d_name, "irqbalance", 10)) { ++ ret = sscanf(entry->d_name, "irqbalance%d.sock", &irqbalance_pid); + if (!ret) + irqbalance_pid = -1; + } + } +- } +- while ((entry) && (irqbalance_pid == -1)); +- +- closedir (dir); ++ } while ((entry) && (irqbalance_pid == -1)); ++ ++ closedir(dir); + } + + if (irqbalance_pid == -1) { +- lpmd_log_info ("\tirqbalance not running, run in native mode\n"); ++ lpmd_log_info("\tirqbalance not running, run in native mode\n"); + return LPMD_SUCCESS; + } + +- snprintf (irq_socket_name, 64, "%s/%s%d.sock", SOCKET_TMPFS, SOCKET_PATH, irqbalance_pid); +- socket_fd = socket_init_connection (irq_socket_name); ++ snprintf(irq_socket_name, 64, "%s/%s%d.sock", SOCKET_TMPFS, SOCKET_PATH, irqbalance_pid); ++ socket_fd = socket_init_connection(irq_socket_name); + if (socket_fd < 0) { +- lpmd_log_error ("Can not connect to irqbalance socket /run/irqbalance/irqbalance%d.sock\n", +- irqbalance_pid); ++ lpmd_log_error("Can not connect to irqbalance socket /run/irqbalance/irqbalance%d.sock\n", ++ irqbalance_pid); + return LPMD_ERROR; + } +- close (socket_fd); +- lpmd_log_info ("\tFind irqbalance socket %s\n", irq_socket_name); ++ close(socket_fd); ++ lpmd_log_info("\tFind irqbalance socket %s\n", irq_socket_name); + return LPMD_SUCCESS; + } +diff --git a/src/lpmd_main.c b/src/lpmd_main.c +index 4f33f1d..0e31390 100644 +--- a/src/lpmd_main.c ++++ b/src/lpmd_main.c +@@ -1,33 +1,11 @@ +-/* +- * lpmd_main.c: Intel Low Power Daemon main entry point +- * +- * Copyright (C) 2023 Intel Corporation. All rights reserved. +- * +- * This program is free software; you can redistribute it and/or modify +- * it under the terms of the GNU General Public License as published by +- * the Free Software Foundation; either version 2 of the License, or +- * (at your option) any later version. +- * +- * This program is distributed in the hope that it will be useful, +- * but WITHOUT ANY WARRANTY; without even the implied warranty of +- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +- * GNU General Public License for more details. +- * +- * You should have received a copy of the GNU General Public License +- * along with this program; if not, write to the Free Software +- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +- * +- * This source file contains main() function, which parses command line +- * option. Call lpmd init function. Provide logging support. +- * Also allow to daemonize. +- */ ++// SPDX-License-Identifier: GPL-2.0-or-later ++/* Copyright (C) 2026 Intel Corporation */ + + #include + #include + #include + #include + +- + #include "lpmd.h" + + #if !defined(INTEL_LPMD_DIST_VERSION) +@@ -36,15 +14,13 @@ + + #define EXIT_UNSUPPORTED 2 + +-extern int intel_lpmd_dbus_server_init(gboolean (*exit_handler)(void)); +- + // Lock file + static int lock_file_handle = -1; + static const char *lock_file = TDRUNDIR "/intel_lpmd.pid"; + + // Default log level + static int lpmd_log_level = G_LOG_LEVEL_ERROR | G_LOG_LEVEL_CRITICAL | G_LOG_LEVEL_WARNING +- | G_LOG_LEVEL_MESSAGE; ++ | G_LOG_LEVEL_MESSAGE; + + int in_debug_mode(void) + { +@@ -56,9 +32,8 @@ static gboolean intel_lpmd_daemonize; + static gboolean use_syslog; + + // Disable dbus +-static gboolean dbus_enable; +- + static gboolean ignore_platform_check = FALSE; ++static gboolean dbus_enable; + + int do_platform_check(void) + { +@@ -76,73 +51,72 @@ gint watcher_id = 0; + + // g_log handler. All logs will be directed here + static void intel_lpmd_logger(const gchar *log_domain, GLogLevelFlags log_level, +- const gchar *message, gpointer user_data) ++ const gchar *message, gpointer user_data) + { +- if (!(lpmd_log_level & log_level)) +- return; +- + int syslog_priority; + const char *prefix; + time_t seconds; + ++ if (!(lpmd_log_level & log_level)) ++ return; ++ + switch (log_level) { +- case G_LOG_LEVEL_ERROR: +- prefix = "[CRIT]"; +- syslog_priority = LOG_CRIT; +- break; +- case G_LOG_LEVEL_CRITICAL: +- prefix = "[ERR]"; +- syslog_priority = LOG_ERR; +- break; +- case G_LOG_LEVEL_WARNING: +- prefix = "[WARN]"; +- syslog_priority = LOG_WARNING; +- break; +- case G_LOG_LEVEL_MESSAGE: +- prefix = "[MSG]"; +- syslog_priority = LOG_NOTICE; +- break; +- case G_LOG_LEVEL_DEBUG: +- prefix = "[DEBUG]"; +- syslog_priority = LOG_DEBUG; +- break; +- case G_LOG_LEVEL_INFO: +- default: +- prefix = "[INFO]"; +- syslog_priority = LOG_INFO; +- break; ++ case G_LOG_LEVEL_ERROR: ++ prefix = "[CRIT]"; ++ syslog_priority = LOG_CRIT; ++ break; ++ case G_LOG_LEVEL_CRITICAL: ++ prefix = "[ERR]"; ++ syslog_priority = LOG_ERR; ++ break; ++ case G_LOG_LEVEL_WARNING: ++ prefix = "[WARN]"; ++ syslog_priority = LOG_WARNING; ++ break; ++ case G_LOG_LEVEL_MESSAGE: ++ prefix = "[MSG]"; ++ syslog_priority = LOG_NOTICE; ++ break; ++ case G_LOG_LEVEL_DEBUG: ++ prefix = "[DEBUG]"; ++ syslog_priority = LOG_DEBUG; ++ break; ++ case G_LOG_LEVEL_INFO: ++ default: ++ prefix = "[INFO]"; ++ syslog_priority = LOG_INFO; ++ break; + } + +- seconds = time (NULL); ++ seconds = time(NULL); + + if (use_syslog) +- syslog (syslog_priority, "%s", message); ++ syslog(syslog_priority, "%s", message); + else +- g_print ("[%lld]%s%s", (long long) seconds, prefix, message); ++ g_print("[%lld]%s%s", (long long)seconds, prefix, message); + } + + static void clean_up_lockfile(void) + { + if (lock_file_handle != -1) { +- (void) close (lock_file_handle); +- (void) unlink (lock_file); ++ (void)close(lock_file_handle); ++ (void)unlink(lock_file); + } + } + + static bool check_intel_lpmd_running(void) + { +- +- lock_file_handle = open (lock_file, O_RDWR | O_CREAT, 0600); ++ lock_file_handle = open(lock_file, O_RDWR | O_CREAT, 0600); + if (lock_file_handle == -1) { + // Couldn't open lock file +- lpmd_log_error ("Could not open PID lock file %s, exiting\n", lock_file); ++ lpmd_log_error("Could not open PID lock file %s, exiting\n", lock_file); + return false; + } + // Try to lock file +- if (lockf (lock_file_handle, F_TLOCK, 0) == -1) { ++ if (lockf(lock_file_handle, F_TLOCK, 0) == -1) { + // Couldn't get lock on lock file +- lpmd_log_error ("Couldn't get lock file %d\n", getpid ()); +- close (lock_file_handle); ++ lpmd_log_error("Couldn't get lock file %d\n", getpid()); ++ close(lock_file_handle); + return true; + } + +@@ -153,17 +127,17 @@ static bool check_intel_lpmd_running(void) + static gboolean sig_int_handler(void) + { + // Call terminate function +- lpmd_terminate (); ++ lpmd_terminate(); + +- sleep (1); ++ sleep(1); + + if (g_main_loop) +- g_main_loop_quit (g_main_loop); ++ g_main_loop_quit(g_main_loop); + + // Clean up if any +- clean_up_lockfile (); ++ clean_up_lockfile(); + +- exit (EXIT_SUCCESS); ++ exit(EXIT_SUCCESS); + + return FALSE; + } +@@ -171,161 +145,153 @@ static gboolean sig_int_handler(void) + int main(int argc, char *argv[]) + { + gboolean show_version = FALSE; +- gboolean log_info = FALSE; + gboolean log_debug = FALSE; + gboolean no_daemon = FALSE; ++ gboolean log_info = FALSE; + gboolean systemd = FALSE; +- gboolean success; + GOptionContext *opt_ctx; ++ gboolean success; + int ret; + + intel_lpmd_daemonize = TRUE; +- use_syslog = TRUE; + dbus_enable = FALSE; ++ use_syslog = TRUE; + +- GOptionEntry options[] = +- { { "version", 0, 0, G_OPTION_ARG_NONE, &show_version, N_ ("Print intel_lpmd version and exit"), NULL }, +- { "no-daemon", 0, 0, G_OPTION_ARG_NONE, &no_daemon, N_ ("Don't become a daemon: Default is daemon mode"), NULL }, +- { "systemd", 0, 0, G_OPTION_ARG_NONE, &systemd, N_ ("Assume daemon is started by systemd, always run in non-daemon mode when using this parameter"), NULL }, +- { "loglevel=info", 0, 0, G_OPTION_ARG_NONE, &log_info, N_ ("Log severity: info level and up"), NULL }, +- { "loglevel=debug", 0, 0, G_OPTION_ARG_NONE, &log_debug, N_ ("Log severity: debug level and up: Max logging"), NULL }, +- { "dbus-enable", 0, 0, G_OPTION_ARG_NONE, &dbus_enable, N_ ( "Enable Dbus"), NULL }, +- { "ignore-platform-check", 0, 0, G_OPTION_ARG_NONE, &ignore_platform_check, N_ ( "Ignore platform check"), NULL }, +- { NULL, 0, 0, G_OPTION_ARG_NONE, NULL, NULL, NULL } }; +- +- if (!g_module_supported ()) { +- fprintf (stderr, "GModules are not supported on your platform!\n"); +- exit (EXIT_FAILURE); ++ GOptionEntry options[] = { ++ { "version", 0, 0, G_OPTION_ARG_NONE, &show_version, N_("Print intel_lpmd version and exit"), NULL }, ++ { "no-daemon", 0, 0, G_OPTION_ARG_NONE, &no_daemon, N_("Don't become a daemon: Default is daemon mode"), NULL }, ++ { "systemd", 0, 0, G_OPTION_ARG_NONE, &systemd, N_("Assume daemon is started by systemd, always run in non-daemon mode when using this parameter"), NULL }, ++ { "loglevel=info", 0, 0, G_OPTION_ARG_NONE, &log_info, N_("Log severity: info level and up"), NULL }, ++ { "loglevel=debug", 0, 0, G_OPTION_ARG_NONE, &log_debug, N_("Log severity: debug level and up: Max logging"), NULL }, ++ { "dbus-enable", 0, 0, G_OPTION_ARG_NONE, &dbus_enable, N_("Enable Dbus"), NULL }, ++ { "ignore-platform-check", 0, 0, G_OPTION_ARG_NONE, &ignore_platform_check, N_("Ignore platform check"), NULL }, ++ { NULL, 0, 0, G_OPTION_ARG_NONE, NULL, NULL, NULL } ++ }; ++ ++ if (!g_module_supported()) { ++ fprintf(stderr, "GModules are not supported on your platform!\n"); ++ exit(EXIT_FAILURE); + } + + // Set locale to be able to use environment variables +- setlocale (LC_ALL, ""); ++ setlocale(LC_ALL, ""); + +- bindtextdomain (GETTEXT_PACKAGE, TDLOCALEDIR); +- bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8"); +- textdomain (GETTEXT_PACKAGE); ++ bindtextdomain(GETTEXT_PACKAGE, TDLOCALEDIR); ++ bind_textdomain_codeset(GETTEXT_PACKAGE, "UTF-8"); ++ textdomain(GETTEXT_PACKAGE); + + // Parse options +- opt_ctx = g_option_context_new (NULL); +- g_option_context_set_translation_domain (opt_ctx, GETTEXT_PACKAGE); +- g_option_context_set_ignore_unknown_options (opt_ctx, FALSE); +- g_option_context_set_help_enabled (opt_ctx, TRUE); +- g_option_context_add_main_entries (opt_ctx, options, NULL); +- +- g_option_context_set_summary (opt_ctx, +- "Intel Energy Optimizer (LPMD) Daemon based on system usage takes action " +- "to improve energy efficiency the system.\n\n" +- "Copyright (c) 2024, Intel Corporation\n" +- "This program comes with ABSOLUTELY NO WARRANTY.\n" +- "This work is licensed under GPL v2.\n\n" +- "Use \"man intel_lpmd\" to get more details."); +- +- success = g_option_context_parse (opt_ctx, &argc, &argv, NULL); +- g_option_context_free (opt_ctx); ++ opt_ctx = g_option_context_new(NULL); ++ g_option_context_set_translation_domain(opt_ctx, GETTEXT_PACKAGE); ++ g_option_context_set_ignore_unknown_options(opt_ctx, FALSE); ++ g_option_context_set_help_enabled(opt_ctx, TRUE); ++ g_option_context_add_main_entries(opt_ctx, options, NULL); ++ ++ g_option_context_set_summary(opt_ctx, ++ "Intel Energy Optimizer (LPMD) Daemon based on system usage takes action " ++ "to improve energy efficiency the system.\n\n" ++ "Copyright (c) 2024, Intel Corporation\n" ++ "This program comes with ABSOLUTELY NO WARRANTY.\n" ++ "This work is licensed under GPL v2.\n\n" ++ "Use \"man intel_lpmd\" to get more details."); ++ ++ success = g_option_context_parse(opt_ctx, &argc, &argv, NULL); ++ g_option_context_free(opt_ctx); + + if (!success) { +- fprintf (stderr, "Invalid option. Please use --help to see a list of valid options.\n"); +- exit (EXIT_FAILURE); ++ fprintf(stderr, ++ "Invalid option. Please use --help to see a list of valid options.\n"); ++ exit(EXIT_FAILURE); + } + + if (show_version) { +- fprintf (stdout, INTEL_LPMD_DIST_VERSION "\n"); +- exit (EXIT_SUCCESS); ++ fprintf(stdout, INTEL_LPMD_DIST_VERSION "\n"); ++ exit(EXIT_SUCCESS); + } + +- if (getuid () != 0) { +- fprintf (stderr, "You must be root to run intel_lpmd!\n"); +- exit (EXIT_FAILURE); ++ if (getuid() != 0) { ++ fprintf(stderr, "You must be root to run intel_lpmd!\n"); ++ exit(EXIT_FAILURE); + } + +- if (g_mkdir_with_parents (TDRUNDIR, 0755) != 0) { +- fprintf (stderr, "Cannot create '%s': %s", TDRUNDIR, strerror (errno)); +- exit (EXIT_FAILURE); ++ if (g_mkdir_with_parents(TDRUNDIR, 0755) != 0) { ++ fprintf(stderr, "Cannot create '%s': %s", TDRUNDIR, strerror(errno)); ++ exit(EXIT_FAILURE); + } + +- if (g_mkdir_with_parents (TDCONFDIR, 0755) != 0) { +- fprintf (stderr, "Cannot create '%s': %s", TDCONFDIR, strerror (errno)); +- exit (EXIT_FAILURE); ++ if (g_mkdir_with_parents(TDCONFDIR, 0755) != 0) { ++ fprintf(stderr, "Cannot create '%s': %s", TDCONFDIR, strerror(errno)); ++ exit(EXIT_FAILURE); + } + +- if (log_info) { ++ if (log_info) + lpmd_log_level |= G_LOG_LEVEL_INFO; +- } + +- if (log_debug) { ++ if (log_debug) + lpmd_log_level |= G_LOG_LEVEL_INFO | G_LOG_LEVEL_DEBUG; +- } + +- openlog ("intel_lpmd", LOG_PID, LOG_USER | LOG_DAEMON | LOG_SYSLOG); ++ openlog("intel_lpmd", LOG_PID, LOG_USER | LOG_DAEMON | LOG_SYSLOG); + // Don't care return val + + intel_lpmd_daemonize = !no_daemon && !systemd; + use_syslog = !no_daemon || systemd; +- g_log_set_handler (NULL, G_LOG_LEVEL_MASK, intel_lpmd_logger, NULL); ++ g_log_set_handler(NULL, G_LOG_LEVEL_MASK, intel_lpmd_logger, NULL); + +- if (check_intel_lpmd_running ()) { +- lpmd_log_error ("An instance of intel_lpmd is already running, exiting ...\n"); +- exit (EXIT_FAILURE); ++ if (check_intel_lpmd_running()) { ++ lpmd_log_error("An instance of intel_lpmd is already running, exiting ...\n"); ++ exit(EXIT_FAILURE); + } + + if (!intel_lpmd_daemonize) { +- g_unix_signal_add (SIGINT, G_SOURCE_FUNC (sig_int_handler), NULL); +- g_unix_signal_add (SIGTERM, G_SOURCE_FUNC (sig_int_handler), NULL); ++ g_unix_signal_add(SIGINT, G_SOURCE_FUNC(sig_int_handler), NULL); ++ g_unix_signal_add(SIGTERM, G_SOURCE_FUNC(sig_int_handler), NULL); + } + +- /* +- * Initialize the GType/GObject system +- * Since GLib 2.36, the type system is initialised automatically and this function +- * does nothing. Deprecated since: 2.36 +- */ +- +- g_type_init (); +- + // Create a main loop that will dispatch callbacks +- g_main_loop = g_main_loop_new (NULL, FALSE); +- if (g_main_loop == NULL) { +- clean_up_lockfile (); +- lpmd_log_error ("Couldn't create GMainLoop:\n"); ++ g_main_loop = g_main_loop_new(NULL, FALSE); ++ if (!g_main_loop) { ++ clean_up_lockfile(); ++ lpmd_log_error("Couldn't create GMainLoop:\n"); + return LPMD_FATAL_ERROR; + } + + if (intel_lpmd_daemonize) { +- printf ("Ready to serve requests: Daemonizing..\n"); +- lpmd_log_info ("intel_lpmd ver %s: Ready to serve requests: Daemonizing..\n", +- INTEL_LPMD_DIST_VERSION); ++ printf("Ready to serve requests: Daemonizing..\n"); ++ lpmd_log_info("intel_lpmd ver %s: Ready to serve requests: Daemonizing..\n", ++ INTEL_LPMD_DIST_VERSION); + +- if (daemon (0, 0) != 0) { +- clean_up_lockfile (); +- lpmd_log_error ("Failed to daemonize.\n"); ++ if (daemon(0, 0) != 0) { ++ clean_up_lockfile(); ++ lpmd_log_error("Failed to daemonize.\n"); + return LPMD_FATAL_ERROR; + } + } + + if (dbus_enable) +- intel_dbus_server_init (sig_int_handler); ++ intel_dbus_server_init(sig_int_handler); + +- ret = lpmd_main (); ++ ret = lpmd_main(); + + if (ret != LPMD_SUCCESS) { +- clean_up_lockfile (); +- closelog (); ++ clean_up_lockfile(); ++ closelog(); + + if (ret == LPMD_ERROR) +- exit (EXIT_UNSUPPORTED); ++ exit(EXIT_UNSUPPORTED); + else +- exit (EXIT_FAILURE); ++ exit(EXIT_FAILURE); + } + + // Start service requests on the D-Bus +- lpmd_log_debug ("Start main loop\n"); +- g_main_loop_run (g_main_loop); +- lpmd_log_warn ("Oops g main loop exit..\n"); ++ lpmd_log_debug("Start main loop\n"); ++ g_main_loop_run(g_main_loop); ++ lpmd_log_warn("Oops g main loop exit..\n"); + + #ifdef GDBUS +- g_bus_unwatch_name (watcher_id); ++ g_bus_unwatch_name(watcher_id); + #endif + +- fprintf (stdout, "Exiting ..\n"); +- clean_up_lockfile (); +- closelog (); ++ fprintf(stdout, "Exiting ..\n"); ++ clean_up_lockfile(); ++ closelog(); + } +diff --git a/src/lpmd_misc.c b/src/lpmd_misc.c +index b0def2b..ead26f3 100644 +--- a/src/lpmd_misc.c ++++ b/src/lpmd_misc.c +@@ -1,22 +1,6 @@ +-/* +- * lpmd_misc.c: processing misc PowerManagement features +- * +- * Copyright (C) 2025 Intel Corporation. All rights reserved. +- * +- * This program is free software; you can redistribute it and/or modify +- * it under the terms of the GNU General Public License as published by +- * the Free Software Foundation; either version 2 of the License, or +- * (at your option) any later version. +- * +- * This program is distributed in the hope that it will be useful, +- * but WITHOUT ANY WARRANTY; without even the implied warranty of +- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +- * GNU General Public License for more details. +- * +- * You should have received a copy of the GNU General Public License +- * along with this program; if not, write to the Free Software +- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +- */ ++// SPDX-License-Identifier: GPL-2.0-or-later ++/* Copyright (C) 2026 Intel Corporation */ ++ + #define _GNU_SOURCE + #include "lpmd.h" + +@@ -34,7 +18,7 @@ int get_itmt(void) + if (!has_itmt) + return -1; + +- ret = lpmd_read_yn(PATH_ITMT_CONTROL_DEBUGFS, &val, -1); ++ ret = lpmd_read_yn(PATH_ITMT_CONTROL_DEBUGFS, &val, -1); + if (!ret) + return val; + +@@ -50,7 +34,6 @@ int get_itmt(void) + + void itmt_init(void) + { +- + if (lpmd_read_yn(PATH_ITMT_CONTROL_DEBUGFS, &saved_itmt, -1)) { + lpmd_log_debug("ITMT debugfs not detected\n"); + } else { +@@ -64,7 +47,7 @@ void itmt_init(void) + has_itmt = 1; + } + +-int process_itmt(lpmd_config_state_t *state) ++int process_itmt(struct lpmd_config_state_t *state) + { + int ret; + +@@ -72,20 +55,20 @@ int process_itmt(lpmd_config_state_t *state) + return 0; + + switch (state->itmt_state) { +- case SETTING_IGNORE: +- lpmd_log_debug("Ignore ITMT\n"); +- return 0; +- case SETTING_RESTORE: +- ret = lpmd_write_yn(PATH_ITMT_CONTROL_DEBUGFS, saved_itmt, -1); +- if (ret) +- return lpmd_write_int(PATH_ITMT_CONTROL, saved_itmt, -1); +- return ret; +- default: +- lpmd_log_debug ("%s ITMT\n", state->itmt_state ? "Enable" : "Disable"); +- ret = lpmd_write_yn(PATH_ITMT_CONTROL_DEBUGFS, state->itmt_state, -1); +- if (ret) +- return lpmd_write_int(PATH_ITMT_CONTROL, state->itmt_state, -1); +- return ret; ++ case SETTING_IGNORE: ++ lpmd_log_debug("Ignore ITMT\n"); ++ return 0; ++ case SETTING_RESTORE: ++ ret = lpmd_write_yn(PATH_ITMT_CONTROL_DEBUGFS, saved_itmt, -1); ++ if (ret) ++ return lpmd_write_int(PATH_ITMT_CONTROL, saved_itmt, -1); ++ return ret; ++ default: ++ lpmd_log_debug("%s ITMT\n", state->itmt_state ? "Enable" : "Disable"); ++ ret = lpmd_write_yn(PATH_ITMT_CONTROL_DEBUGFS, state->itmt_state, -1); ++ if (ret) ++ return lpmd_write_int(PATH_ITMT_CONTROL, state->itmt_state, -1); ++ return ret; + } + } + +@@ -102,14 +85,16 @@ static int slider_unavailable; + #define PATH_SOC_BALANCE_SLIDER "/sys/module/processor_thermal_soc_slider/parameters/slider_balance" + #define PATH_SOC_OFFSET "/sys/module/processor_thermal_soc_slider/parameters/slider_offset" + +-static void init_slider_path() ++static void init_slider_path(void) + { +- DIR *dir; + struct dirent *entry; ++ DIR *dir; + int ret; + + snprintf(soc_sld_path, MAX_STR_LENGTH, "%s", PATH_PLATFORM_PROFILE); +- if ((dir = opendir(soc_sld_path)) == NULL) { ++ ++ dir = opendir(soc_sld_path); ++ if (!dir) { + lpmd_log_debug("Cannot find %s\n", soc_sld_path); + goto slider_failed; + } +@@ -118,11 +103,11 @@ static void init_slider_path() + if (strlen(entry->d_name) > 100) + continue; + if (strncmp(entry->d_name, "platform-profile", +- strlen("platform-profile"))) ++ strlen("platform-profile"))) + continue; + + snprintf(soc_sld_path, MAX_STR_LENGTH, "%s/%s/name", +- PATH_PLATFORM_PROFILE, entry->d_name); ++ PATH_PLATFORM_PROFILE, entry->d_name); + + ret = lpmd_read_str(soc_sld_path, soc_sld_profile, MAX_STR_LENGTH); + if (ret) +@@ -130,7 +115,7 @@ static void init_slider_path() + + if (!strncmp(soc_sld_profile, NAME_SOC_SLD, strlen(NAME_SOC_SLD))) { + snprintf(soc_sld_path, MAX_STR_LENGTH, "%s/%s/profile", +- PATH_PLATFORM_PROFILE, entry->d_name); ++ PATH_PLATFORM_PROFILE, entry->d_name); + slider_available = 1; + break; + } +@@ -144,7 +129,7 @@ static void init_slider_path() + } + + lpmd_log_info("\tAvailable at %s/%s, use profile [%s]\n", +- PATH_PLATFORM_PROFILE, entry->d_name, soc_sld_profile); ++ PATH_PLATFORM_PROFILE, entry->d_name, soc_sld_profile); + + return; + +@@ -158,7 +143,7 @@ static int update_balance_slider(int slider) + int ret; + static int current_slider = -1; + +- lpmd_log_debug("update_balance_slider\n"); ++ lpmd_log_debug("%s\n", __func__); + + if (slider < 0) + return 0; +@@ -231,9 +216,9 @@ static int update_slider_offset(int offset) + return 0; + } + +-void process_balance_slider_default_update(lpmd_config_t *config) ++void process_balance_slider_default_update(struct lpmd_config_t *config) + { +- lpmd_log_debug("process_balance_slider_default_update\n"); ++ lpmd_log_debug("%s\n", __func__); + + if (is_on_battery()) { + if (config->balance_slider_def_dc >= 0) +@@ -244,9 +229,9 @@ void process_balance_slider_default_update(lpmd_config_t *config) + } + } + +-void process_slider_offset_default_update(lpmd_config_t *config) ++void process_slider_offset_default_update(struct lpmd_config_t *config) + { +- lpmd_log_debug("process_slider_offset_default_update\n"); ++ lpmd_log_debug("%s\n", __func__); + + if (is_on_battery()) { + if (config->slider_offset_def_dc >= 0) +@@ -257,9 +242,9 @@ void process_slider_offset_default_update(lpmd_config_t *config) + } + } + +-static int process_balance_slider(lpmd_config_state_t *state) ++static int process_balance_slider(struct lpmd_config_state_t *state) + { +- lpmd_log_debug("process_balance_slider\n"); ++ lpmd_log_debug("%s\n", __func__); + + if (is_on_battery()) + return update_balance_slider(state->balance_slider_dc); +@@ -267,9 +252,9 @@ static int process_balance_slider(lpmd_config_state_t *state) + return update_balance_slider(state->balance_slider_ac); + } + +-static int process_slider_offset(lpmd_config_state_t *state) ++static int process_slider_offset(struct lpmd_config_state_t *state) + { +- lpmd_log_debug("process_slider_offset\n"); ++ lpmd_log_debug("%s\n", __func__); + + if (is_on_battery()) + return update_slider_offset(state->slider_offset_dc); +@@ -277,7 +262,7 @@ static int process_slider_offset(lpmd_config_state_t *state) + return update_slider_offset(state->slider_offset_ac); + } + +-void process_slider(lpmd_config_t *config, lpmd_config_state_t *state) ++void process_slider(struct lpmd_config_t *config, struct lpmd_config_state_t *state) + { + int ret; + +@@ -297,6 +282,7 @@ struct cpu_info { + int epp; + int epb; + }; ++ + static struct cpu_info *saved_cpu_info; + + static int get_epp(char *path, int *val, char *str, int size) +@@ -305,28 +291,28 @@ static int get_epp(char *path, int *val, char *str, int size) + int epp; + int ret; + +- filep = fopen (path, "r"); ++ filep = fopen(path, "r"); + if (!filep) + return 1; + +- ret = fscanf (filep, "%d", &epp); ++ ret = fscanf(filep, "%d", &epp); + if (ret == 1) { + *val = epp; + ret = 0; + goto end; + } + +- ret = fread (str, 1, size, filep); +- if (ret <= 0) ++ ret = fread(str, 1, size, filep); ++ if (ret <= 0) { + ret = 1; +- else { ++ } else { + if (ret >= size) + ret = size - 1; + str[ret - 1] = '\0'; + ret = 0; + } + end: +- fclose (filep); ++ fclose(filep); + return ret; + } + +@@ -335,26 +321,26 @@ static int set_epp(char *path, int val, char *str) + FILE *filep; + int ret; + +- filep = fopen (path, "r+"); ++ filep = fopen(path, "r+"); + if (!filep) + return 1; + +- if (val >= 0) +- ret = fprintf (filep, "%d", val); +- else if (str && str[0] != '\0') +- ret = fprintf (filep, "%s", str); +- else { +- fclose (filep); ++ if (val >= 0) { ++ ret = fprintf(filep, "%d", val); ++ } else if (str && str[0] != '\0') { ++ ret = fprintf(filep, "%s", str); ++ } else { ++ fclose(filep); + return 1; + } + +- fclose (filep); ++ fclose(filep); + + if (ret <= 0) { + if (val >= 0) +- lpmd_log_error ("Write \"%d\" to %s failed, ret %d\n", val, path, ret); ++ lpmd_log_error("Write \"%d\" to %s failed, ret %d\n", val, path, ret); + else +- lpmd_log_error ("Write \"%s\" to %s failed, ret %d\n", str, path, ret); ++ lpmd_log_error("Write \"%s\" to %s failed, ret %d\n", str, path, ret); + } + return !(ret > 0); + } +@@ -386,8 +372,9 @@ int get_epp_epb(int *epp, char *epp_str, int size, int *epb) + *epp = -1; + epp_str[0] = '\0'; + /* CPU0 is always online */ +- snprintf (path, sizeof(path), "/sys/devices/system/cpu/cpu%d/cpufreq/energy_performance_preference", 0); +- get_epp (path, epp, epp_str, size); ++ snprintf(path, sizeof(path), ++ "/sys/devices/system/cpu/cpu%d/cpufreq/energy_performance_preference", 0); ++ get_epp(path, epp, epp_str, size); + epp_str[size - 1] = '\0'; + + *epb = -1; +@@ -396,17 +383,17 @@ int get_epp_epb(int *epp, char *epp_str, int size, int *epb) + return ret; + } + +-int process_epp_epb(lpmd_config_state_t *state) ++int process_epp_epb(struct lpmd_config_state_t *state) + { +- int max_cpus = get_max_cpus (); +- int c; +- int ret; ++ int max_cpus = get_max_cpus(); + char path[MAX_STR_LENGTH]; ++ int ret; ++ int c; + + if (state->epp == SETTING_IGNORE) +- lpmd_log_info ("Ignore EPP\n"); ++ lpmd_log_info("Ignore EPP\n"); + if (state->epb == SETTING_IGNORE) +- lpmd_log_info ("Ignore EPB\n"); ++ lpmd_log_info("Ignore EPB\n"); + if (state->epp == SETTING_IGNORE && state->epb == SETTING_IGNORE) + return 0; + +@@ -414,7 +401,7 @@ int process_epp_epb(lpmd_config_state_t *state) + int val; + char *str = NULL; + +- if (!is_cpu_online (c)) ++ if (!is_cpu_online(c)) + continue; + + if (state->epp != SETTING_IGNORE) { +@@ -430,13 +417,16 @@ int process_epp_epb(lpmd_config_state_t *state) + val = state->epp; + } + +- snprintf(path, sizeof(path), "/sys/devices/system/cpu/cpu%d/cpufreq/energy_performance_preference", c); +- ret = set_epp (path, val, str); ++ snprintf(path, sizeof(path), ++ "/sys/devices/system/cpu/cpu%d/cpufreq/energy_performance_preference", c); ++ ret = set_epp(path, val, str); + if (!ret) { + if (val != -1) +- lpmd_log_debug ("Set CPU%d EPP to 0x%x\n", c, val); ++ lpmd_log_debug("Set CPU%d EPP to 0x%x\n", ++ c, val); + else +- lpmd_log_debug ("Set CPU%d EPP to %s\n", c, saved_cpu_info[c].epp_str); ++ lpmd_log_debug("Set CPU%d EPP to %s\n", ++ c, saved_cpu_info[c].epp_str); + } + } + +@@ -446,10 +436,11 @@ int process_epp_epb(lpmd_config_state_t *state) + else + val = state->epb; + +- snprintf (path, MAX_STR_LENGTH, "/sys/devices/system/cpu/cpu%d/power/energy_perf_bias", c); ++ snprintf(path, MAX_STR_LENGTH, ++ "/sys/devices/system/cpu/cpu%d/power/energy_perf_bias", c); + ret = lpmd_write_int(path, val, -1); + if (!ret) +- lpmd_log_debug ("Set CPU%d EPB to 0x%x\n", c, val); ++ lpmd_log_debug("Set CPU%d EPB to 0x%x\n", c, val); + } + } + return 0; +@@ -457,36 +448,39 @@ int process_epp_epb(lpmd_config_state_t *state) + + int epp_epb_init(void) + { +- int max_cpus = get_max_cpus (); +- int c; +- int ret; ++ int max_cpus = get_max_cpus(); + char path[MAX_STR_LENGTH]; ++ int ret; ++ int c; + +- saved_cpu_info = calloc (max_cpus, sizeof(struct cpu_info)); ++ saved_cpu_info = calloc(max_cpus, sizeof(struct cpu_info)); + + for (c = 0; c < max_cpus; c++) { + saved_cpu_info[c].epp_str[0] = '\0'; + saved_cpu_info[c].epp = -1; + +- if (!is_cpu_online (c)) ++ if (!is_cpu_online(c)) + continue; + +- snprintf (path, sizeof(path), "/sys/devices/system/cpu/cpu%d/cpufreq/energy_performance_preference", c); +- ret = get_epp (path, &saved_cpu_info[c].epp, saved_cpu_info[c].epp_str, MAX_EPP_STRING_LENGTH); ++ snprintf(path, sizeof(path), ++ "/sys/devices/system/cpu/cpu%d/cpufreq/energy_performance_preference", c); ++ ret = get_epp(path, &saved_cpu_info[c].epp, ++ saved_cpu_info[c].epp_str, MAX_EPP_STRING_LENGTH); + if (!ret) { + if (saved_cpu_info[c].epp != -1) +- lpmd_log_debug ("CPU%d EPP: 0x%x\n", c, saved_cpu_info[c].epp); ++ lpmd_log_debug("CPU%d EPP: 0x%x\n", c, saved_cpu_info[c].epp); + else +- lpmd_log_debug ("CPU%d EPP: %s\n", c, saved_cpu_info[c].epp_str); ++ lpmd_log_debug("CPU%d EPP: %s\n", c, saved_cpu_info[c].epp_str); + } + +- snprintf(path, MAX_STR_LENGTH, "/sys/devices/system/cpu/cpu%d/power/energy_perf_bias", c); ++ snprintf(path, MAX_STR_LENGTH, ++ "/sys/devices/system/cpu/cpu%d/power/energy_perf_bias", c); + ret = lpmd_read_int(path, &saved_cpu_info[c].epb, -1); + if (ret) { + saved_cpu_info[c].epb = -1; + continue; + } +- lpmd_log_debug ("CPU%d EPB: 0x%x\n", c, saved_cpu_info[c].epb); ++ lpmd_log_debug("CPU%d EPB: 0x%x\n", c, saved_cpu_info[c].epb); + } + return 0; + } +diff --git a/src/lpmd_proc.c b/src/lpmd_proc.c +index 3c3fafb..a459fda 100644 +--- a/src/lpmd_proc.c ++++ b/src/lpmd_proc.c +@@ -1,33 +1,13 @@ +-/* +- * lpmd_proc.c: Intel Low Power Daemon core processing +- * +- * Copyright (C) 2023 Intel Corporation. All rights reserved. +- * +- * This program is free software; you can redistribute it and/or modify +- * it under the terms of the GNU General Public License as published by +- * the Free Software Foundation; either version 2 of the License, or +- * (at your option) any later version. +- * +- * This program is distributed in the hope that it will be useful, +- * but WITHOUT ANY WARRANTY; without even the implied warranty of +- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +- * GNU General Public License for more details. +- * +- * You should have received a copy of the GNU General Public License +- * along with this program; if not, write to the Free Software +- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +- * +- * This file contains the main LPMD thread and poll loop. Call correct +- * processing function on receiving user or system command. +- */ ++// SPDX-License-Identifier: GPL-2.0-or-later ++/* Copyright (C) 2026 Intel Corporation */ + + #include "lpmd.h" + #include + #include "wlt_proxy.h" + +-static lpmd_config_t lpmd_config; ++static struct lpmd_config_t lpmd_config; + +-lpmd_config_t *get_lpmd_config(void) ++struct lpmd_config_t *get_lpmd_config(void) + { + return &lpmd_config; + } +@@ -38,12 +18,12 @@ static pthread_mutex_t lpmd_mutex; + + int lpmd_lock(void) + { +- return pthread_mutex_lock (&lpmd_mutex); ++ return pthread_mutex_lock(&lpmd_mutex); + } + + int lpmd_unlock(void) + { +- return pthread_mutex_unlock (&lpmd_mutex); ++ return pthread_mutex_unlock(&lpmd_mutex); + } + + static int has_hfi_capability(void) +@@ -62,44 +42,44 @@ static int has_hfi_capability(void) + + static int write_pipe_fd; + +-static void lpmd_send_message(message_name_t msg_id, int size, unsigned char *msg) ++static void lpmd_send_message(enum message_name_t msg_id, int size, unsigned char *msg) + { +- message_capsul_t msg_cap; ++ struct message_capsul_t msg_cap; + int result; + +- memset (&msg_cap, 0, sizeof(message_capsul_t)); ++ memset(&msg_cap, 0, sizeof(struct message_capsul_t)); + + msg_cap.msg_id = msg_id; + msg_cap.msg_size = (size > MAX_MSG_SIZE) ? MAX_MSG_SIZE : size; + if (msg) +- memcpy (msg_cap.msg, msg, msg_cap.msg_size); ++ memcpy(msg_cap.msg, msg, msg_cap.msg_size); + +- result = write (write_pipe_fd, &msg_cap, sizeof(message_capsul_t)); ++ result = write(write_pipe_fd, &msg_cap, sizeof(struct message_capsul_t)); + if (result < 0) +- lpmd_log_warn ("Write to pipe failed\n"); ++ lpmd_log_warn("Write to pipe failed\n"); + } + + void lpmd_terminate(void) + { +- lpmd_send_message (TERMINATE, 0, NULL); +- sleep (1); ++ lpmd_send_message(TERMINATE, 0, NULL); ++ sleep(1); + if (upower_client) + g_clear_object(&upower_client); + } + + void lpmd_force_on(void) + { +- lpmd_send_message (LPM_FORCE_ON, 0, NULL); ++ lpmd_send_message(LPM_FORCE_ON, 0, NULL); + } + + void lpmd_force_off(void) + { +- lpmd_send_message (LPM_FORCE_OFF, 0, NULL); ++ lpmd_send_message(LPM_FORCE_OFF, 0, NULL); + } + + void lpmd_set_auto(void) + { +- lpmd_send_message (LPM_AUTO, 0, NULL); ++ lpmd_send_message(LPM_AUTO, 0, NULL); + } + + #define LPMD_NUM_OF_POLL_FDS 5 +@@ -128,25 +108,26 @@ int get_ppd_mode(void) + + static void power_profiles_changed_cb(void) + { +- g_autoptr (GVariant) ++ g_autoptr(GVariant) + active_profile_v = NULL; + +- active_profile_v = g_dbus_proxy_get_cached_property (power_profiles_daemon, "ActiveProfile"); ++ active_profile_v = g_dbus_proxy_get_cached_property(power_profiles_daemon, ++ "ActiveProfile"); + +- if (active_profile_v && g_variant_is_of_type (active_profile_v, G_VARIANT_TYPE_STRING)) { +- const char *active_profile = g_variant_get_string (active_profile_v, NULL); ++ if (active_profile_v && g_variant_is_of_type(active_profile_v, G_VARIANT_TYPE_STRING)) { ++ const char *active_profile = g_variant_get_string(active_profile_v, NULL); + +- lpmd_log_debug ("power_profiles_changed_cb: %s\n", active_profile); ++ lpmd_log_debug("%s: %s\n", __func__, active_profile); + +- if (strcmp (active_profile, "power-saver") == 0) { ++ if (strcmp(active_profile, "power-saver") == 0) { + ppd_mode = PPD_POWERSAVER; +- lpmd_send_message (lpmd_config.powersaver_def, 0, NULL); +- } else if (strcmp (active_profile, "performance") == 0) { ++ lpmd_send_message(lpmd_config.powersaver_def, 0, NULL); ++ } else if (strcmp(active_profile, "performance") == 0) { + ppd_mode = PPD_PERFORMANCE; +- lpmd_send_message (lpmd_config.performance_def, 0, NULL); +- } else if (strcmp (active_profile, "balanced") == 0) { ++ lpmd_send_message(lpmd_config.performance_def, 0, NULL); ++ } else if (strcmp(active_profile, "balanced") == 0) { + ppd_mode = PPD_BALANCED; +- lpmd_send_message (lpmd_config.balanced_def, 0, NULL); ++ lpmd_send_message(lpmd_config.balanced_def, 0, NULL); + } else { + lpmd_log_warn("Ignore unsupported power profile: %s\n", active_profile); + } +@@ -158,29 +139,26 @@ static void power_profiles_changed_cb(void) + + static int connect_to_power_profile_daemon(void) + { +- g_autoptr (GDBusConnection) ++ g_autoptr(GDBusConnection) + bus = NULL; + +- bus = g_bus_get_sync (G_BUS_TYPE_SYSTEM, NULL, NULL); ++ bus = g_bus_get_sync(G_BUS_TYPE_SYSTEM, NULL, NULL); + if (bus) { +- power_profiles_daemon = g_dbus_proxy_new_sync (bus, G_DBUS_PROXY_FLAGS_DO_NOT_AUTO_START, +- NULL, +- "net.hadess.PowerProfiles", +- "/net/hadess/PowerProfiles", +- "net.hadess.PowerProfiles", +- NULL, +- NULL); ++ power_profiles_daemon = ++ g_dbus_proxy_new_sync(bus, G_DBUS_PROXY_FLAGS_DO_NOT_AUTO_START, ++ NULL, "net.hadess.PowerProfiles", ++ "/net/hadess/PowerProfiles", ++ "net.hadess.PowerProfiles", NULL, NULL); + + if (power_profiles_daemon) { +- g_signal_connect_swapped (power_profiles_daemon, "g-properties-changed", +- (GCallback) power_profiles_changed_cb, +- NULL); +- power_profiles_changed_cb (); ++ g_signal_connect_swapped(power_profiles_daemon, ++ "g-properties-changed", ++ (GCallback)power_profiles_changed_cb, ++ NULL); ++ power_profiles_changed_cb(); + return 0; + } +- else { +- lpmd_log_info ("Could not setup DBus watch for power-profiles-daemon"); +- } ++ lpmd_log_info("Could not setup DBus watch for power-profiles-daemon"); + } + return 1; + } +@@ -195,12 +173,12 @@ int is_on_battery(void) + return battery_mode; + } + +-static void upower_daemon_cb (UpClient *client, GParamSpec *pspec, gpointer user_data) ++static void upower_daemon_cb(UpClient *client, GParamSpec *pspec, gpointer user_data) + { + static int mode = -1; + + battery_mode = up_client_get_on_battery(upower_client); +- if (mode != battery_mode){ ++ if (mode != battery_mode) { + process_balance_slider_default_update(&lpmd_config); + process_slider_offset_default_update(&lpmd_config); + } +@@ -212,23 +190,23 @@ static void connect_to_upower_daemon(void) + { + GError *error = NULL; + GPtrArray *devices; ++ UpDevice *device; + int i; + +- upower_client = up_client_new_full (NULL, &error); +- if (upower_client == NULL) { +- g_warning ("Cannot connect to upowerd: %s", error->message); +- g_error_free (error); ++ upower_client = up_client_new_full(NULL, &error); ++ if (!upower_client) { ++ g_warning("Cannot connect to upowerd: %s", error->message); ++ g_error_free(error); + return; + } + + lpmd_log_info("connected to upower daemon\n"); +- g_signal_connect (upower_client, "notify", G_CALLBACK (upower_daemon_cb), NULL); ++ g_signal_connect(upower_client, "notify", G_CALLBACK(upower_daemon_cb), NULL); + +- devices = up_client_get_devices2 (upower_client); +- for (i=0; i < devices->len; i++) { +- UpDevice *device; +- device = g_ptr_array_index (devices, i); +- g_signal_connect (device, "notify", G_CALLBACK (upower_daemon_cb), NULL); ++ devices = up_client_get_devices2(upower_client); ++ for (i = 0; i < devices->len; i++) { ++ device = g_ptr_array_index(devices, i); ++ g_signal_connect(device, "notify", G_CALLBACK(upower_daemon_cb), NULL); + } + } + +@@ -236,28 +214,28 @@ static void connect_to_upower_daemon(void) + #define POLL_TIMEOUT_DEFAULT_SECONDS 1 + + // called from LPMD main thread to process user and system messages +-static int proc_message(message_capsul_t *msg) ++static int proc_message(struct message_capsul_t *msg) + { +- lpmd_log_debug ("Received message %d\n", msg->msg_id); ++ lpmd_log_debug("Received message %d\n", msg->msg_id); + switch (msg->msg_id) { +- case TERMINATE: +- lpmd_log_msg ("Terminating ...\n"); +- update_lpmd_state(LPMD_TERMINATE); +- break; +- case LPM_FORCE_ON: +- // Always stay in LPM mode +- update_lpmd_state(LPMD_ON); +- break; +- case LPM_FORCE_OFF: +- // Never enter LPM mode +- update_lpmd_state(LPMD_OFF); +- break; +- case LPM_AUTO: +- // Enable oppotunistic LPM +- update_lpmd_state(LPMD_AUTO); +- break; +- default: +- break; ++ case TERMINATE: ++ lpmd_log_msg("Terminating ...\n"); ++ update_lpmd_state(LPMD_TERMINATE); ++ break; ++ case LPM_FORCE_ON: ++ // Always stay in LPM mode ++ update_lpmd_state(LPMD_ON); ++ break; ++ case LPM_FORCE_OFF: ++ // Never enter LPM mode ++ update_lpmd_state(LPMD_OFF); ++ break; ++ case LPM_AUTO: ++ // Enable oppotunistic LPM ++ update_lpmd_state(LPMD_AUTO); ++ break; ++ default: ++ break; + } + + return 0; +@@ -267,28 +245,31 @@ static void dump_poll_results(int ret) + { + int i = 0; + +- + // if (!in_debug_mode()) + if (1) + return; + + if (idx_pipe_fd != -1) { +- lpmd_log_debug("poll_fds[%s]: event %d, revent %d\n", " Pipe", poll_fds[i].events, poll_fds[i].revents); ++ lpmd_log_debug("poll_fds[%s]: event %d, revent %d\n", " Pipe", ++ poll_fds[i].events, poll_fds[i].revents); + i++; + } + + if (idx_uevent_fd != -1) { +- lpmd_log_debug("poll_fds[%s]: event %d, revent %d\n", "Uevent", poll_fds[i].events, poll_fds[i].revents); ++ lpmd_log_debug("poll_fds[%s]: event %d, revent %d\n", "Uevent", ++ poll_fds[i].events, poll_fds[i].revents); + i++; + } + + if (idx_hfi_fd != -1) { +- lpmd_log_debug("poll_fds[%s]: event %d, revent %d\n", " HFI", poll_fds[i].events, poll_fds[i].revents); ++ lpmd_log_debug("poll_fds[%s]: event %d, revent %d\n", " HFI", ++ poll_fds[i].events, poll_fds[i].revents); + i++; + } + + if (idx_wlt_fd != -1) { +- lpmd_log_debug("poll_fds[%s]: event %d, revent %d\n", " WLT", poll_fds[i].events, poll_fds[i].revents); ++ lpmd_log_debug("poll_fds[%s]: event %d, revent %d\n", " WLT", ++ poll_fds[i].events, poll_fds[i].revents); + i++; + } + } +@@ -304,8 +285,8 @@ void update_reason(int reason) + * their cpumasks with other states and therefore can't be uniquely identified + * by their cpumask idx. + */ +-char *user_cpumask_idx_to_state_name(enum cpumask_idx idx) { +- ++char *user_cpumask_idx_to_state_name(enum cpumask_idx idx) ++{ + for (int i = 0 ; i < MAX_STATES ; i++) { + if (lpmd_config.config_states[i].cpumask_idx == idx) + return lpmd_config.config_states[i].name; +@@ -314,20 +295,20 @@ char *user_cpumask_idx_to_state_name(enum cpumask_idx idx) { + } + + // LPMD processing thread. This is callback to pthread lpmd_core_main +-static void* lpmd_core_main_loop(void *arg) ++static void *lpmd_core_main_loop(void *arg) + { +- int n; ++ struct message_capsul_t msg; ++ int wlt_hint, result, n; + + lpmd_config.data.polling_interval = DEF_POLLING_INTERVAL; + + for (;;) { +- + if (get_lpmd_state() == LPMD_TERMINATE) + break; + +- n = poll (poll_fds, poll_fd_cnt, lpmd_config.data.polling_interval); ++ n = poll(poll_fds, poll_fd_cnt, lpmd_config.data.polling_interval); + if (n < 0) { +- lpmd_log_warn ("Write to pipe failed\n"); ++ lpmd_log_warn("Write to pipe failed\n"); + continue; + } + dump_poll_results(n); +@@ -338,22 +319,21 @@ static void* lpmd_core_main_loop(void *arg) + util_update(&lpmd_config); + + if (lpmd_config.wlt_proxy_enable) +- lpmd_config.data.wlt_hint = read_wlt_proxy(&lpmd_config.data.polling_interval); ++ lpmd_config.data.wlt_hint = ++ read_wlt_proxy(&lpmd_config.data.polling_interval); + } + + /* Check CPU hotplug. Maybe need to freeze lpmd */ +- if (idx_uevent_fd >= 0 && (poll_fds[idx_uevent_fd].revents & POLLIN)) { +- check_cpu_hotplug (); +- } ++ if (idx_uevent_fd >= 0 && (poll_fds[idx_uevent_fd].revents & POLLIN)) ++ check_cpu_hotplug(); + + /* Update CPUMASK_HFI */ +- if (idx_hfi_fd >= 0 && (poll_fds[idx_hfi_fd].revents & POLLIN)) { ++ if (idx_hfi_fd >= 0 && (poll_fds[idx_hfi_fd].revents & POLLIN)) + hfi_update(); +- } + + /* Update WLT hint */ + if (idx_wlt_fd >= 0 && (poll_fds[idx_wlt_fd].revents & POLLPRI)) { +- int wlt_hint = wlt_update(poll_fds[idx_wlt_fd].fd); ++ wlt_hint = wlt_update(poll_fds[idx_wlt_fd].fd); + if (wlt_hint != lpmd_config.data.wlt_hint) { + lpmd_config.data.wlt_hint = wlt_hint; + update_reason(UPDATE_WLT); +@@ -364,17 +344,15 @@ static void* lpmd_core_main_loop(void *arg) + if (idx_pipe_fd >= 0 && (poll_fds[idx_pipe_fd].revents & POLLIN)) { + // process message written on pipe here + +- message_capsul_t msg; +- +- int result = read (poll_fds[idx_pipe_fd].fd, &msg, sizeof(message_capsul_t)); ++ result = read(poll_fds[idx_pipe_fd].fd, &msg, ++ sizeof(struct message_capsul_t)); + if (result < 0) { +- lpmd_log_warn ("read on wakeup fd failed\n"); ++ lpmd_log_warn("read on wakeup fd failed\n"); + poll_fds[idx_pipe_fd].revents = 0; + continue; + } +- if (proc_message (&msg) < 0) { +- lpmd_log_debug ("Terminating thread..\n"); +- } ++ if (proc_message(&msg) < 0) ++ lpmd_log_debug("Terminating thread..\n"); + update_reason(UPDATE_USER); + } + +@@ -387,7 +365,7 @@ static void* lpmd_core_main_loop(void *arg) + + if (lpmd_config.wlt_proxy_enable) + wlt_proxy_uninit(); +- hfi_kill (); ++ hfi_kill(); + cgroup_cleanup(); + + return NULL; +@@ -398,7 +376,7 @@ int lpmd_main(void) + int wake_fds[2]; + int ret; + +- lpmd_log_debug ("lpmd_main begin\n"); ++ lpmd_log_debug("%s begin\n", __func__); + + ret = detect_supported_platform(&lpmd_config); + if (ret) +@@ -409,11 +387,11 @@ int lpmd_main(void) + goto cleanup; + + // Call all lpmd related functions here +- ret = lpmd_get_config (&lpmd_config); ++ ret = lpmd_get_config(&lpmd_config); + if (ret) + goto cleanup; + +- pthread_mutex_init (&lpmd_mutex, NULL); ++ pthread_mutex_init(&lpmd_mutex, NULL); + + ret = detect_lpm_cpus(lpmd_config.lp_mode_cpus); + if (ret) +@@ -429,7 +407,7 @@ int lpmd_main(void) + if (ret) + goto cleanup; + +- if (!has_hfi_capability ()) ++ if (!has_hfi_capability()) + lpmd_config.hfi_lpm_enable = 0; + + /* Must done after init_cpu() */ +@@ -444,26 +422,26 @@ int lpmd_main(void) + + connect_to_upower_daemon(); + // Pipe is used for communication between two processes +- ret = pipe (wake_fds); ++ ret = pipe(wake_fds); + if (ret) { +- lpmd_log_error ("pipe creation failed %d:\n", ret); ++ lpmd_log_error("pipe creation failed %d:\n", ret); + return LPMD_FATAL_ERROR; + } +- if (fcntl (wake_fds[0], F_SETFL, O_NONBLOCK) < 0) { +- lpmd_log_error ("Cannot set non-blocking on pipe: %s\n", strerror (errno)); ++ if (fcntl(wake_fds[0], F_SETFL, O_NONBLOCK) < 0) { ++ lpmd_log_error("Cannot set non-blocking on pipe: %s\n", strerror(errno)); + (void)close(wake_fds[0]); + (void)close(wake_fds[1]); + return LPMD_FATAL_ERROR; + } +- if (fcntl (wake_fds[1], F_SETFL, O_NONBLOCK) < 0) { +- lpmd_log_error ("Cannot set non-blocking on pipe: %s\n", strerror (errno)); ++ if (fcntl(wake_fds[1], F_SETFL, O_NONBLOCK) < 0) { ++ lpmd_log_error("Cannot set non-blocking on pipe: %s\n", strerror(errno)); + (void)close(wake_fds[0]); + (void)close(wake_fds[1]); + return LPMD_FATAL_ERROR; + } + write_pipe_fd = wake_fds[1]; + +- memset (poll_fds, 0, sizeof(poll_fds)); ++ memset(poll_fds, 0, sizeof(poll_fds)); + + idx_pipe_fd = poll_fd_cnt; + poll_fds[idx_pipe_fd].fd = wake_fds[0]; +@@ -471,7 +449,7 @@ int lpmd_main(void) + poll_fds[idx_pipe_fd].revents = 0; + poll_fd_cnt++; + +- poll_fds[poll_fd_cnt].fd = uevent_init (); ++ poll_fds[poll_fd_cnt].fd = uevent_init(); + if (poll_fds[poll_fd_cnt].fd > 0) { + idx_uevent_fd = poll_fd_cnt; + poll_fds[idx_uevent_fd].events = POLLIN; +@@ -480,7 +458,7 @@ int lpmd_main(void) + } + + if (lpmd_config.hfi_lpm_enable) { +- poll_fds[poll_fd_cnt].fd = hfi_init (); ++ poll_fds[poll_fd_cnt].fd = hfi_init(); + if (poll_fds[poll_fd_cnt].fd > 0) { + idx_hfi_fd = poll_fd_cnt; + poll_fds[idx_hfi_fd].events = POLLIN; +@@ -489,37 +467,35 @@ int lpmd_main(void) + } + } + +- if (lpmd_config.wlt_hint_enable) { +- if (lpmd_config.wlt_proxy_enable) { +- if (wlt_proxy_init() != LPMD_SUCCESS) { +- lpmd_config.wlt_proxy_enable = 0; +- lpmd_log_error ("Error setting up WLT Proxy. wlt_proxy_enable disabled\n"); +- } +- } +- if (!lpmd_config.hfi_lpm_enable) { +- lpmd_config.util_enable = 0; +- if (!lpmd_config.wlt_proxy_enable) { +- poll_fds[poll_fd_cnt].fd = wlt_init(); +- if (poll_fds[poll_fd_cnt].fd > 0) { +- idx_wlt_fd = poll_fd_cnt; +- poll_fds[idx_wlt_fd].events = POLLPRI; +- poll_fds[idx_wlt_fd].revents = 0; +- poll_fd_cnt++; +- } ++ if (lpmd_config.wlt_hint_enable && ++ lpmd_config.wlt_proxy_enable && ++ wlt_proxy_init() != LPMD_SUCCESS) { ++ lpmd_config.wlt_proxy_enable = 0; ++ lpmd_log_error("Error setting up WLT Proxy. wlt_proxy_enable disabled\n"); ++ } ++ ++ if (lpmd_config.wlt_hint_enable && !lpmd_config.hfi_lpm_enable) { ++ lpmd_config.util_enable = 0; ++ if (!lpmd_config.wlt_proxy_enable) { ++ poll_fds[poll_fd_cnt].fd = wlt_init(); ++ if (poll_fds[poll_fd_cnt].fd > 0) { ++ idx_wlt_fd = poll_fd_cnt; ++ poll_fds[idx_wlt_fd].events = POLLPRI; ++ poll_fds[idx_wlt_fd].revents = 0; ++ poll_fd_cnt++; + } + } + if (lpmd_config.wlt_notification_delay != -1) { +- if (wlt_set_notification_delay(lpmd_config.wlt_notification_delay) != LPMD_SUCCESS) { +- lpmd_log_error ("Error setting WLT notification delay. wlt_notification_delay set to default value\n"); +- } ++ if (wlt_set_notification_delay(lpmd_config.wlt_notification_delay) != LPMD_SUCCESS) ++ lpmd_log_error("Error setting WLT notification delay. wlt_notification_delay set to default value\n"); + } + } + +- pthread_attr_init (&lpmd_attr); +- pthread_attr_setdetachstate (&lpmd_attr, PTHREAD_CREATE_DETACHED); ++ pthread_attr_init(&lpmd_attr); ++ pthread_attr_setdetachstate(&lpmd_attr, PTHREAD_CREATE_DETACHED); + + /* Enable lpmd auto run when power profile daemon is not connected */ +- if (connect_to_power_profile_daemon ()) ++ if (connect_to_power_profile_daemon()) + lpmd_set_auto(); + + process_balance_slider_default_update(&lpmd_config); +@@ -529,12 +505,11 @@ int lpmd_main(void) + * lpmd_core_main_loop: is the thread where all LPMD actions take place. + * All other thread send message via pipe to trigger processing + */ +- ret = pthread_create (&lpmd_core_main, &lpmd_attr, lpmd_core_main_loop, NULL); ++ ret = pthread_create(&lpmd_core_main, &lpmd_attr, lpmd_core_main_loop, NULL); + if (ret) + return LPMD_FATAL_ERROR; + +- +- lpmd_log_debug ("lpmd_init succeeds\n"); ++ lpmd_log_debug("lpmd_init succeeds\n"); + + return LPMD_SUCCESS; + cleanup: +diff --git a/src/lpmd_socket.c b/src/lpmd_socket.c +index ab3078e..492f794 100644 +--- a/src/lpmd_socket.c ++++ b/src/lpmd_socket.c +@@ -1,26 +1,10 @@ +-/* +- * lpmd_socket.c: Intel Low Power Daemon socket helpers +- * +- * Copyright (C) 2023 Intel Corporation. All rights reserved. +- * +- * This program is free software; you can redistribute it and/or modify +- * it under the terms of the GNU General Public License as published by +- * the Free Software Foundation; either version 2 of the License, or +- * (at your option) any later version. +- * +- * This program is distributed in the hope that it will be useful, +- * but WITHOUT ANY WARRANTY; without even the implied warranty of +- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +- * GNU General Public License for more details. +- * +- * You should have received a copy of the GNU General Public License +- * along with this program; if not, write to the Free Software +- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +- * +- * This file is used to send messages to IRQ daemon via sockets. +- */ ++// SPDX-License-Identifier: GPL-2.0-or-later ++/* Copyright (C) 2026 Intel Corporation */ + ++#ifndef _GNU_SOURCE + #define _GNU_SOURCE ++#endif ++ + #include + #include + #include +@@ -61,22 +45,22 @@ int socket_init_connection(char *name) + if (!name) + return 0; + +- memset (&addr, 0, sizeof(struct sockaddr_un)); +- socket_fd = socket (AF_LOCAL, SOCK_STREAM, 0); ++ memset(&addr, 0, sizeof(struct sockaddr_un)); ++ socket_fd = socket(AF_LOCAL, SOCK_STREAM, 0); + if (socket_fd < 0) { +- perror ("Error opening socket"); ++ perror("Error opening socket"); + return 0; + } + addr.sun_family = AF_UNIX; + +- snprintf (addr.sun_path, sizeof(addr.sun_path), "%s", name); ++ snprintf(addr.sun_path, sizeof(addr.sun_path), "%s", name); + +- if (connect (socket_fd, (struct sockaddr*) &addr, sizeof(addr)) < 0) { ++ if (connect(socket_fd, (struct sockaddr *)&addr, sizeof(addr)) < 0) { + /* Try connect to abstract */ +- memset (&addr, 0, sizeof(struct sockaddr_un)); ++ memset(&addr, 0, sizeof(struct sockaddr_un)); + addr.sun_family = AF_UNIX; +- if (connect (socket_fd, (struct sockaddr*) &addr, sizeof(addr)) < 0) { +- close (socket_fd); ++ if (connect(socket_fd, (struct sockaddr *)&addr, sizeof(addr)) < 0) { ++ close(socket_fd); + return 0; + } + } +@@ -84,32 +68,32 @@ int socket_init_connection(char *name) + return socket_fd; + } + +-static struct msghdr* create_credentials_msg() ++static struct msghdr *create_credentials_msg(void) + { + struct ucred *credentials; + struct msghdr *msg; + struct cmsghdr *cmsg; + +- credentials = malloc (sizeof(struct ucred)); ++ credentials = malloc(sizeof(struct ucred)); + if (!credentials) + return NULL; + +- credentials->pid = getpid (); +- credentials->uid = geteuid (); +- credentials->gid = getegid (); ++ credentials->pid = getpid(); ++ credentials->uid = geteuid(); ++ credentials->gid = getegid(); + +- msg = malloc (sizeof(struct msghdr)); ++ msg = malloc(sizeof(struct msghdr)); + if (!msg) { +- free (credentials); ++ free(credentials); + return msg; + } + +- memset (msg, 0, sizeof(struct msghdr)); ++ memset(msg, 0, sizeof(struct msghdr)); + msg->msg_iovlen = 1; +- msg->msg_control = malloc (CMSG_SPACE(sizeof(struct ucred))); ++ msg->msg_control = malloc(CMSG_SPACE(sizeof(struct ucred))); + if (!msg->msg_control) { +- free (credentials); +- free (msg); ++ free(credentials); ++ free(msg); + return NULL; + } + +@@ -119,9 +103,9 @@ static struct msghdr* create_credentials_msg() + cmsg->cmsg_level = SOL_SOCKET; + cmsg->cmsg_type = SCM_CREDENTIALS; + cmsg->cmsg_len = CMSG_LEN(sizeof(struct ucred)); +- memcpy (CMSG_DATA(cmsg), credentials, sizeof(struct ucred)); ++ memcpy(CMSG_DATA(cmsg), credentials, sizeof(struct ucred)); + +- free (credentials); ++ free(credentials); + return msg; + } + +@@ -136,31 +120,30 @@ int socket_send_cmd(char *name, char *data) + if (!name || !data) + return LPMD_ERROR; + +- socket_fd = socket_init_connection (name); ++ socket_fd = socket_init_connection(name); + if (!socket_fd) + return LPMD_ERROR; + +- msg = create_credentials_msg (); ++ msg = create_credentials_msg(); + if (!msg) + return LPMD_ERROR; + +- iov.iov_base = (void*) data; +- iov.iov_len = strlen (data); ++ iov.iov_base = (void *)data; ++ iov.iov_len = strlen(data); + msg->msg_iov = &iov; + +- if (sendmsg (socket_fd, msg, 0) < 0) { +- free (msg->msg_control); +- free (msg); ++ if (sendmsg(socket_fd, msg, 0) < 0) { ++ free(msg->msg_control); ++ free(msg); + return LPMD_ERROR; + } + +- ret = read (socket_fd, buf, MAX_STR_LENGTH); ++ ret = read(socket_fd, buf, MAX_STR_LENGTH); + if (ret < 0) +- lpmd_log_debug ("read failed\n"); ++ lpmd_log_debug("read failed\n"); + +- close (socket_fd); +- free (msg->msg_control); +- free (msg); ++ close(socket_fd); ++ free(msg->msg_control); ++ free(msg); + return LPMD_SUCCESS; + } +- +diff --git a/src/lpmd_state_machine.c b/src/lpmd_state_machine.c +index 9927377..833d98d 100644 +--- a/src/lpmd_state_machine.c ++++ b/src/lpmd_state_machine.c +@@ -1,22 +1,7 @@ +-/* +- * lpmd_state_machine.c: intel_lpmd state machine +- * +- * Copyright (C) 2025 Intel Corporation. All rights reserved. +- * +- * This program is free software; you can redistribute it and/or modify +- * it under the terms of the GNU General Public License as published by +- * the Free Software Foundation; either version 2 of the License, or +- * (at your option) any later version. +- * +- * This program is distributed in the hope that it will be useful, +- * but WITHOUT ANY WARRANTY; without even the implied warranty of +- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +- * GNU General Public License for more details. +- * +- * You should have received a copy of the GNU General Public License +- * along with this program; if not, write to the Free Software +- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +- */ ++// SPDX-License-Identifier: GPL-2.0-or-later ++/* Copyright (C) 2026 Intel Corporation */ ++ ++ + #define _GNU_SOURCE + #include + #include +@@ -52,26 +37,26 @@ int update_lpmd_state(int new) + { + lpmd_lock(); + switch (new) { +- case LPMD_FREEZE: +- if (lpmd_state == LPMD_FREEZE) +- break; +- lpmd_log_debug ("Freeze lpmd\n"); +- saved_lpmd_state = lpmd_state; +- lpmd_state = LPMD_FREEZE; +- break; +- case LPMD_RESTORE: +- if (lpmd_state != LPMD_FREEZE) +- break; +- lpmd_log_debug ("Restore lpmd\n"); +- lpmd_state = saved_lpmd_state; +- saved_lpmd_state = lpmd_state; ++ case LPMD_FREEZE: ++ if (lpmd_state == LPMD_FREEZE) + break; +- default: +- if (lpmd_state == LPMD_FREEZE) +- saved_lpmd_state = new; +- else +- lpmd_state = new; ++ lpmd_log_debug("Freeze lpmd\n"); ++ saved_lpmd_state = lpmd_state; ++ lpmd_state = LPMD_FREEZE; ++ break; ++ case LPMD_RESTORE: ++ if (lpmd_state != LPMD_FREEZE) + break; ++ lpmd_log_debug("Restore lpmd\n"); ++ lpmd_state = saved_lpmd_state; ++ saved_lpmd_state = lpmd_state; ++ break; ++ default: ++ if (lpmd_state == LPMD_FREEZE) ++ saved_lpmd_state = new; ++ else ++ lpmd_state = new; ++ break; + } + lpmd_unlock(); + return 0; +@@ -84,7 +69,7 @@ int get_lpmd_state(void) + + /* LPMD config states control */ + +-int lpmd_init_config_state(lpmd_config_state_t *state) ++int lpmd_init_config_state(struct lpmd_config_state_t *state) + { + state->id = -1; + state->valid = 0; +@@ -131,9 +116,9 @@ int lpmd_init_config_state(lpmd_config_state_t *state) + + static int current_idx = DEFAULT_OFF; + +-static int config_state_match(lpmd_config_t *config, int idx) ++static int config_state_match(struct lpmd_config_t *config, int idx) + { +- lpmd_config_state_t *state = &config->config_states[idx]; ++ struct lpmd_config_state_t *state = &config->config_states[idx]; + int bcpu = config->data.util_cpu; + int bsys = config->data.util_sys; + int bgfx = config->data.util_gfx; +@@ -166,7 +151,8 @@ static int config_state_match(lpmd_config_t *config, int idx) + if (state->entry_system_load_thres && state->entry_system_load_thres < bsys) { + if (!state->exit_system_load_hyst) + return 0; +- if ((state->entry_load_sys + state->exit_system_load_hyst) < bsys || (state->entry_system_load_thres + state->exit_system_load_hyst) < bsys) ++ if ((state->entry_load_sys + state->exit_system_load_hyst) < bsys || ++ (state->entry_system_load_thres + state->exit_system_load_hyst) < bsys) + return 0; + } + +@@ -175,9 +161,9 @@ static int config_state_match(lpmd_config_t *config, int idx) + + static int polling_enabled; + +-static int get_config_state_interval(lpmd_config_t *config, int idx) ++static int get_config_state_interval(struct lpmd_config_t *config, int idx) + { +- lpmd_config_state_t *state = &config->config_states[idx]; ++ struct lpmd_config_state_t *state = &config->config_states[idx]; + + /* wlt proxy updates polling separately */ + if (config->wlt_proxy_enable) +@@ -189,7 +175,7 @@ static int get_config_state_interval(lpmd_config_t *config, int idx) + return 0; + } + +- /* Always start with minumum polling interval for a new state */ ++ /* Always start with minimum polling interval for a new state */ + if (idx != current_idx) { + config->data.polling_interval = state->min_poll_interval; + return 0; +@@ -197,7 +183,8 @@ static int get_config_state_interval(lpmd_config_t *config, int idx) + + /* CPU utilization based adaptive polling */ + if (state->poll_interval_increment == -1) { +- config->data.polling_interval = state->max_poll_interval * (10000 - config->data.util_cpu) / 10000; ++ config->data.polling_interval = ++ state->max_poll_interval * (10000 - config->data.util_cpu) / 10000; + config->data.polling_interval /= 100; + config->data.polling_interval *= 100; + goto end; +@@ -206,7 +193,7 @@ static int get_config_state_interval(lpmd_config_t *config, int idx) + /* lazy polling if load is sustained */ + if (state->poll_interval_increment > 0) + config->data.polling_interval += state->poll_interval_increment; +- ++ + end: + /* Adjust based on min/max limitation */ + if (config->data.polling_interval < state->min_poll_interval) +@@ -216,7 +203,7 @@ end: + return 0; + } + +-static void dump_state(lpmd_config_state_t *state, char *str, int debug) ++static void dump_state(struct lpmd_config_state_t *state, char *str, int debug) + { + char buf[MAX_STR_LENGTH]; + int offset = 0; +@@ -224,32 +211,50 @@ static void dump_state(lpmd_config_state_t *state, char *str, int debug) + if (debug && !in_debug_mode()) + return; + +- offset += snprintf(buf + offset , MAX_STR_LENGTH - offset, "[%6s] [%s] [%s]: ", str, lpmd_state_name[lpmd_state], state->name); ++ offset += snprintf(buf + offset, MAX_STR_LENGTH - offset, ++ "[%6s] [%s] [%s]: ", str, ++ lpmd_state_name[lpmd_state], state->name); + + if (state->wlt_type) +- offset += snprintf(buf + offset , MAX_STR_LENGTH - offset, "WLT [%2d] ", state->wlt_type); ++ offset += snprintf(buf + offset, MAX_STR_LENGTH - offset, ++ "WLT [%2d] ", state->wlt_type); + + if (state->wlt_type_mask) +- offset += snprintf(buf + offset , MAX_STR_LENGTH - offset, "WLTMASK [%2d] ", state->wlt_type_mask); ++ offset += snprintf(buf + offset, MAX_STR_LENGTH - offset, "WLTMASK [%2d] ", state->wlt_type_mask); + + if (state->entry_system_load_thres) +- offset += snprintf(buf + offset , MAX_STR_LENGTH - offset, "SYS [%6d] ", state->entry_system_load_thres / 100); ++ offset += snprintf(buf + offset, MAX_STR_LENGTH - offset, ++ "SYS [%6d] ", ++ state->entry_system_load_thres / 100); + + if (state->enter_cpu_load_thres) +- offset += snprintf(buf + offset , MAX_STR_LENGTH - offset, "CPU [%6d] ", state->enter_cpu_load_thres / 100); ++ offset += snprintf(buf + offset, MAX_STR_LENGTH - offset, ++ "CPU [%6d] ", ++ state->enter_cpu_load_thres / 100); + + if (state->enter_gfx_load_thres) +- offset += snprintf(buf + offset , MAX_STR_LENGTH - offset, "GFX [%6d] ", state->enter_gfx_load_thres / 100); +- +- offset += snprintf(buf + offset , MAX_STR_LENGTH - offset, "CPUMASK [%d] ", state->cpumask_idx); +- offset += snprintf(buf + offset , MAX_STR_LENGTH - offset, "IRQ [%d] ", state->irq_migrate); +- offset += snprintf(buf + offset , MAX_STR_LENGTH - offset, "ITMT [%d] ", state->itmt_state); +- offset += snprintf(buf + offset , MAX_STR_LENGTH - offset, "EPB [%d] ", state->epb); +- offset += snprintf(buf + offset , MAX_STR_LENGTH - offset, "EPP [%d] ", state->epp); +- offset += snprintf(buf + offset , MAX_STR_LENGTH - offset, "SliderAC [%d] ", state->balance_slider_ac); +- offset += snprintf(buf + offset , MAX_STR_LENGTH - offset, "SliderDC [%d] ", state->balance_slider_ac); +- offset += snprintf(buf + offset , MAX_STR_LENGTH - offset, "OffsetAC [%d] ", state->slider_offset_ac); +- offset += snprintf(buf + offset , MAX_STR_LENGTH - offset, "OffsetDC [%d] ", state->slider_offset_dc); ++ offset += snprintf(buf + offset, MAX_STR_LENGTH - offset, ++ "GFX [%6d] ", ++ state->enter_gfx_load_thres / 100); ++ ++ offset += snprintf(buf + offset, MAX_STR_LENGTH - offset, ++ "CPUMASK [%d] ", state->cpumask_idx); ++ offset += snprintf(buf + offset, MAX_STR_LENGTH - offset, ++ "IRQ [%d] ", state->irq_migrate); ++ offset += snprintf(buf + offset, MAX_STR_LENGTH - offset, ++ "ITMT [%d] ", state->itmt_state); ++ offset += snprintf(buf + offset, MAX_STR_LENGTH - offset, ++ "EPB [%d] ", state->epb); ++ offset += snprintf(buf + offset, MAX_STR_LENGTH - offset, ++ "EPP [%d] ", state->epp); ++ offset += snprintf(buf + offset, MAX_STR_LENGTH - offset, ++ "SliderAC [%d] ", state->balance_slider_ac); ++ offset += snprintf(buf + offset, MAX_STR_LENGTH - offset, ++ "SliderDC [%d] ", state->balance_slider_ac); ++ offset += snprintf(buf + offset, MAX_STR_LENGTH - offset, ++ "OffsetAC [%d] ", state->slider_offset_ac); ++ offset += snprintf(buf + offset, MAX_STR_LENGTH - offset, ++ "OffsetDC [%d] ", state->slider_offset_dc); + + if (debug) + lpmd_log_debug("%s\n", buf); +@@ -257,16 +262,16 @@ static void dump_state(lpmd_config_state_t *state, char *str, int debug) + lpmd_log_info("%s\n", buf); + } + +-static int choose_next_state(lpmd_config_t *config) ++static int choose_next_state(struct lpmd_config_t *config) + { + int i; + + switch (lpmd_state) { +- case LPMD_ON: +- return DEFAULT_ON; +- case LPMD_OFF: +- case LPMD_TERMINATE: +- return DEFAULT_OFF; ++ case LPMD_ON: ++ return DEFAULT_ON; ++ case LPMD_OFF: ++ case LPMD_TERMINATE: ++ return DEFAULT_OFF; + } + + /* +@@ -274,7 +279,7 @@ static int choose_next_state(lpmd_config_t *config) + * and there is no user config states defined in the config file + */ + if (config->config_states[DEFAULT_HFI].valid) +- return DEFAULT_HFI; ++ return DEFAULT_HFI; + + /* Choose a config state */ + for (i = CONFIG_STATE_BASE; i < CONFIG_STATE_BASE + config->config_state_count; ++i) { +@@ -288,21 +293,21 @@ static int choose_next_state(lpmd_config_t *config) + return STATE_NONE; + } + +-static int get_state_interval(lpmd_config_t *config, int idx) ++static int get_state_interval(struct lpmd_config_t *config, int idx) + { + switch (idx) { +- case DEFAULT_ON: +- case DEFAULT_OFF: +- case DEFAULT_HFI: +- config->data.polling_interval = -1; +- return 0; +- default: +- get_config_state_interval(config, idx); +- return 0; ++ case DEFAULT_ON: ++ case DEFAULT_OFF: ++ case DEFAULT_HFI: ++ config->data.polling_interval = -1; ++ return 0; ++ default: ++ get_config_state_interval(config, idx); ++ return 0; + } + } + +-static int need_enter(lpmd_config_t *config, int idx) ++static int need_enter(struct lpmd_config_t *config, int idx) + { + if (idx != current_idx) + return 1; +@@ -312,9 +317,9 @@ static int need_enter(lpmd_config_t *config, int idx) + return 0; + } + +-static int enter_state(lpmd_config_t *config, int idx) ++static int enter_state(struct lpmd_config_t *config, int idx) + { +- lpmd_config_state_t *state = &config->config_states[idx]; ++ struct lpmd_config_state_t *state = &config->config_states[idx]; + + state->entry_load_sys = config->data.util_sys; + state->entry_load_cpu = config->data.util_cpu; +@@ -322,7 +327,7 @@ static int enter_state(lpmd_config_t *config, int idx) + process_slider(config, state); + + process_itmt(state); +- ++ + process_epp_epb(state); + + process_irq(state); +@@ -332,67 +337,97 @@ static int enter_state(lpmd_config_t *config, int idx) + return 0; + } + +-static void dump_data(lpmd_config_t *config, int idx) ++static void dump_data(struct lpmd_config_t *config, int idx) + { ++ struct lpmd_config_state_t *state = &config->config_states[idx]; + char buf[MAX_STR_LENGTH]; ++ int epp, epb, ret; + char epp_str[32]; +- int epp, epb; + int offset = 0; +- lpmd_config_state_t *state = &config->config_states[idx]; + + if (!in_debug_mode()) + return; + +- offset += snprintf(buf + offset , MAX_STR_LENGTH - offset, "[ Data] [%s] [%s]: ", lpmd_state_name[lpmd_state], state->name); ++ offset += snprintf(buf + offset, MAX_STR_LENGTH - offset, ++ "[ Data] [%s] [%s]: ", lpmd_state_name[lpmd_state], ++ state->name); + + if (config->wlt_hint_enable) +- offset += snprintf(buf + offset , MAX_STR_LENGTH - offset, "WLT [%2d] ", config->data.wlt_hint); ++ offset += snprintf(buf + offset, MAX_STR_LENGTH - offset, ++ "WLT [%2d] ", config->data.wlt_hint); + + if (config->util_sys_enable) { + if (config->data.util_sys == -1) +- offset += snprintf(buf + offset , MAX_STR_LENGTH - offset, "SYS [ N/A] "); ++ offset += snprintf(buf + offset, ++ MAX_STR_LENGTH - offset, ++ "SYS [ N/A] "); + else +- offset += snprintf(buf + offset , MAX_STR_LENGTH - offset, "SYS [%3d.%02d] ", config->data.util_sys / 100, config->data.util_sys % 100); ++ offset += snprintf(buf + offset, ++ MAX_STR_LENGTH - offset, ++ "SYS [%3d.%02d] ", ++ config->data.util_sys / 100, ++ config->data.util_sys % 100); + } + + if (config->util_cpu_enable) { + if (config->data.util_cpu == -1) +- offset += snprintf(buf + offset , MAX_STR_LENGTH - offset, "CPU [ N/A] "); ++ offset += snprintf(buf + offset, ++ MAX_STR_LENGTH - offset, ++ "CPU [ N/A] "); + else +- offset += snprintf(buf + offset , MAX_STR_LENGTH - offset, "CPU [%3d.%02d] ", config->data.util_cpu / 100, config->data.util_cpu % 100); ++ offset += snprintf(buf + offset, ++ MAX_STR_LENGTH - offset, ++ "CPU [%3d.%02d] ", ++ config->data.util_cpu / 100, ++ config->data.util_cpu % 100); + } + + if (config->util_gfx_enable) { + if (config->data.util_gfx == -1) +- offset += snprintf(buf + offset , MAX_STR_LENGTH - offset, "GFX [ N/A] "); ++ offset += snprintf(buf + offset, ++ MAX_STR_LENGTH - offset, ++ "GFX [ N/A] "); + else +- offset += snprintf(buf + offset , MAX_STR_LENGTH - offset, "GFX [%3d.%02d] ", config->data.util_gfx / 100, config->data.util_gfx % 100); ++ offset += snprintf(buf + offset, ++ MAX_STR_LENGTH - offset, ++ "GFX [%3d.%02d] ", ++ config->data.util_gfx / 100, ++ config->data.util_gfx % 100); + } + + if (state->cpumask_idx != CPUMASK_NONE) +- offset += snprintf(buf + offset , MAX_STR_LENGTH - offset, "CPUMASK [%s] ", get_cpus_hexstr(state->cpumask_idx, false)); ++ offset += snprintf(buf + offset, MAX_STR_LENGTH - offset, ++ "CPUMASK [%s] ", ++ get_cpus_hexstr(state->cpumask_idx, false)); + else +- offset += snprintf(buf + offset , MAX_STR_LENGTH - offset, "CPUMASK [%s] ", get_cpus_hexstr(CPUMASK_ONLINE, false)); ++ offset += snprintf(buf + offset, MAX_STR_LENGTH - offset, ++ "CPUMASK [%s] ", ++ get_cpus_hexstr(CPUMASK_ONLINE, false)); + +- offset += snprintf(buf + offset , MAX_STR_LENGTH - offset, "ITMT [%d] ", get_itmt()); ++ offset += snprintf(buf + offset, MAX_STR_LENGTH - offset, ++ "ITMT [%d] ", get_itmt()); + +- int ret = get_epp_epb(&epp, epp_str, 32, &epb); ++ ret = get_epp_epb(&epp, epp_str, 32, &epb); + if (ret || epp == -1) +- offset += snprintf(buf + offset , MAX_STR_LENGTH - offset, "EPB [%d] EPP[%s] ", epb, epp_str); ++ offset += snprintf(buf + offset, MAX_STR_LENGTH - offset, ++ "EPB [%d] EPP[%s] ", epb, epp_str); + else +- offset += snprintf(buf + offset , MAX_STR_LENGTH - offset, "EPB [%d] EPP[%d] ", epb, epp); ++ offset += snprintf(buf + offset, MAX_STR_LENGTH - offset, ++ "EPB [%d] EPP[%d] ", epb, epp); + + if (config->hfi_lpm_enable) +- offset += snprintf(buf + offset , MAX_STR_LENGTH - offset, "UPDATE [%d] ", config->data.need_update); ++ offset += snprintf(buf + offset, MAX_STR_LENGTH - offset, ++ "UPDATE [%d] ", config->data.need_update); + +- offset += snprintf(buf + offset , MAX_STR_LENGTH - offset, "Interval [%d]", config->data.polling_interval); ++ offset += snprintf(buf + offset, MAX_STR_LENGTH - offset, ++ "Interval [%d]", config->data.polling_interval); + + lpmd_log_debug("%s\n", buf); + } + + int lpmd_enter_next_state(void) + { +- lpmd_config_t *config = get_lpmd_config(); ++ struct lpmd_config_t *config = get_lpmd_config(); + int idx = current_idx; + + lpmd_lock(); +@@ -431,78 +466,79 @@ end: + return 0; + } + +-static void dump_states(lpmd_config_t *lpmd_config) ++static void dump_states(struct lpmd_config_t *lpmd_config) + { + int i; +- lpmd_config_state_t *state; ++ struct lpmd_config_state_t *state; + + if (!lpmd_config) + return; + +- lpmd_log_info ("Mode:%d\n", lpmd_config->mode); +- lpmd_log_info ("HFI LPM Enable:%d\n", lpmd_config->hfi_lpm_enable); +- lpmd_log_info ("WLT Hint Enable:%d\n", lpmd_config->wlt_hint_enable); +- lpmd_log_info ("WLT Hint Notification Delay:%d\n", lpmd_config->wlt_notification_delay); +- lpmd_log_info ("WLT Proxy Enable:%d\n", lpmd_config->wlt_proxy_enable); +- lpmd_log_info ("WLT Proxy Enable:%d\n", lpmd_config->wlt_hint_poll_enable); +- lpmd_log_info ("WLT Hint mask:%d\n", lpmd_config->wlt_hint_mask); +- lpmd_log_info ("Util Enable:%d\n", lpmd_config->util_enable); +- lpmd_log_info ("Util entry threshold:%d\n", lpmd_config->util_entry_threshold); +- lpmd_log_info ("Util exit threshold:%d\n", lpmd_config->util_exit_threshold); +- lpmd_log_info ("Util LP Mode CPUs:%s\n", lpmd_config->lp_mode_cpus); +- lpmd_log_info ("EPP in LP Mode:%d\n", lpmd_config->lp_mode_epp); +- lpmd_log_info ("CPU Family:%d\n", lpmd_config->cpu_family); +- lpmd_log_info ("CPU Model:%d\n", lpmd_config->cpu_model); +- lpmd_log_info ("CPU Config:%s\n", lpmd_config->cpu_config); +- +- lpmd_log_info ("balance_slider_def_ac:%d\n", lpmd_config->balance_slider_def_ac); +- lpmd_log_info ("balance_slider_def_dc:%d\n", lpmd_config->balance_slider_def_dc); +- lpmd_log_info ("slider_offset_def_ac:%d\n", lpmd_config->slider_offset_def_ac); +- lpmd_log_info ("slider_offset_def_dc:%d\n", lpmd_config->slider_offset_def_dc); ++ lpmd_log_info("Mode:%d\n", lpmd_config->mode); ++ lpmd_log_info("HFI LPM Enable:%d\n", lpmd_config->hfi_lpm_enable); ++ lpmd_log_info("WLT Hint Enable:%d\n", lpmd_config->wlt_hint_enable); ++ lpmd_log_info("WLT Hint Notification Delay:%d\n", lpmd_config->wlt_notification_delay); ++ lpmd_log_info("WLT Proxy Enable:%d\n", lpmd_config->wlt_proxy_enable); ++ lpmd_log_info("WLT Proxy Enable:%d\n", lpmd_config->wlt_hint_poll_enable); ++ lpmd_log_info("WLT Hint mask:%d\n", lpmd_config->wlt_hint_mask); ++ lpmd_log_info("Util Enable:%d\n", lpmd_config->util_enable); ++ lpmd_log_info("Util entry threshold:%d\n", lpmd_config->util_entry_threshold); ++ lpmd_log_info("Util exit threshold:%d\n", lpmd_config->util_exit_threshold); ++ lpmd_log_info("Util LP Mode CPUs:%s\n", lpmd_config->lp_mode_cpus); ++ lpmd_log_info("EPP in LP Mode:%d\n", lpmd_config->lp_mode_epp); ++ lpmd_log_info("CPU Family:%d\n", lpmd_config->cpu_family); ++ lpmd_log_info("CPU Model:%d\n", lpmd_config->cpu_model); ++ lpmd_log_info("CPU Config:%s\n", lpmd_config->cpu_config); ++ ++ lpmd_log_info("balance_slider_def_ac:%d\n", lpmd_config->balance_slider_def_ac); ++ lpmd_log_info("balance_slider_def_dc:%d\n", lpmd_config->balance_slider_def_dc); ++ lpmd_log_info("slider_offset_def_ac:%d\n", lpmd_config->slider_offset_def_ac); ++ lpmd_log_info("slider_offset_def_dc:%d\n", lpmd_config->slider_offset_def_dc); + + for (i = 0; i < MAX_STATES; ++i) { + state = &lpmd_config->config_states[i]; + + if (!state->valid) + continue; +- lpmd_log_info ("Index:%d\n", i); +- lpmd_log_info ("\tID:%d\n", state->id); +- lpmd_log_info ("\tName:%s\n", state->name); +- lpmd_log_info ("\tentry_system_load_thres:%d\n", state->entry_system_load_thres); +- lpmd_log_info ("\texit_system_load_thres:%d\n", state->exit_system_load_thres); +- lpmd_log_info ("\texit_system_load_hyst:%d\n", state->exit_system_load_hyst); +- lpmd_log_info ("\tentry_cpu_load_thres:%d\n", state->enter_cpu_load_thres); +- lpmd_log_info ("\texit_cpu_load_thres:%d\n", state->exit_cpu_load_thres); +- lpmd_log_info ("\tentry_gfx_load_thres:%d\n", state->enter_gfx_load_thres); +- lpmd_log_info ("\texit_gfx_load_thres:%d\n", state->exit_gfx_load_thres); +- lpmd_log_info ("\tWLT Type:%d\n", state->wlt_type); +- lpmd_log_info ("\tWLT Type Mask:%d\n", state->wlt_type_mask); +- lpmd_log_info ("\tmin_poll_interval:%d\n", state->min_poll_interval); +- lpmd_log_info ("\tmax_poll_interval:%d\n", state->max_poll_interval); +- lpmd_log_info ("\tpoll_interval_increment:%d\n", state->poll_interval_increment); +- lpmd_log_info ("\tEPP:%d\n", state->epp); +- lpmd_log_info ("\tEPB:%d\n", state->epb); +- lpmd_log_info ("\tITMTState:%d\n", state->itmt_state); +- lpmd_log_info ("\tIRQMigrate:%d\n", state->irq_migrate); ++ ++ lpmd_log_info("Index:%d\n", i); ++ lpmd_log_info("\tID:%d\n", state->id); ++ lpmd_log_info("\tName:%s\n", state->name); ++ lpmd_log_info("\tentry_system_load_thres:%d\n", state->entry_system_load_thres); ++ lpmd_log_info("\texit_system_load_thres:%d\n", state->exit_system_load_thres); ++ lpmd_log_info("\texit_system_load_hyst:%d\n", state->exit_system_load_hyst); ++ lpmd_log_info("\tentry_cpu_load_thres:%d\n", state->enter_cpu_load_thres); ++ lpmd_log_info("\texit_cpu_load_thres:%d\n", state->exit_cpu_load_thres); ++ lpmd_log_info("\tentry_gfx_load_thres:%d\n", state->enter_gfx_load_thres); ++ lpmd_log_info("\texit_gfx_load_thres:%d\n", state->exit_gfx_load_thres); ++ lpmd_log_info("\tWLT Type:%d\n", state->wlt_type); ++ lpmd_log_info("\tWLT Type Mask:%d\n", state->wlt_type_mask); ++ lpmd_log_info("\tmin_poll_interval:%d\n", state->min_poll_interval); ++ lpmd_log_info("\tmax_poll_interval:%d\n", state->max_poll_interval); ++ lpmd_log_info("\tpoll_interval_increment:%d\n", state->poll_interval_increment); ++ lpmd_log_info("\tEPP:%d\n", state->epp); ++ lpmd_log_info("\tEPB:%d\n", state->epb); ++ lpmd_log_info("\tITMTState:%d\n", state->itmt_state); ++ lpmd_log_info("\tIRQMigrate:%d\n", state->irq_migrate); + if (state->active_cpus[0] != '\0') +- lpmd_log_info ("\tactive_cpus:%s\n", state->active_cpus); ++ lpmd_log_info("\tactive_cpus:%s\n", state->active_cpus); + if (state->active_p_cores[0] != '\0') +- lpmd_log_info ("\tactive_p_cores:%s\n", state->active_p_cores); ++ lpmd_log_info("\tactive_p_cores:%s\n", state->active_p_cores); + if (state->active_e_cores[0] != '\0') +- lpmd_log_info ("\tactive_e_cores:%s\n", state->active_e_cores); ++ lpmd_log_info("\tactive_e_cores:%s\n", state->active_e_cores); + if (state->active_l_cores[0] != '\0') +- lpmd_log_info ("\tactive_l_cores:%s\n", state->active_l_cores); +- lpmd_log_info ("\tCPUMASK idx:%d\n", state->cpumask_idx); +- lpmd_log_info ("\tBalancedSliderAC:%d\n", state->balance_slider_ac); +- lpmd_log_info ("\tBalancedSliderDC:%d\n", state->balance_slider_dc); +- lpmd_log_info ("\tSliderOffsetAC:%d\n", state->slider_offset_ac); +- lpmd_log_info ("\tSliderOffsetDC:%d\n", state->slider_offset_dc); ++ lpmd_log_info("\tactive_l_cores:%s\n", state->active_l_cores); ++ lpmd_log_info("\tCPUMASK idx:%d\n", state->cpumask_idx); ++ lpmd_log_info("\tBalancedSliderAC:%d\n", state->balance_slider_ac); ++ lpmd_log_info("\tBalancedSliderDC:%d\n", state->balance_slider_dc); ++ lpmd_log_info("\tSliderOffsetAC:%d\n", state->slider_offset_ac); ++ lpmd_log_info("\tSliderOffsetDC:%d\n", state->slider_offset_dc); + } + } + +-static int build_default_states(lpmd_config_t *config) ++static int build_default_states(struct lpmd_config_t *config) + { +- lpmd_config_state_t *state; ++ struct lpmd_config_state_t *state; + + state = &config->config_states[DEFAULT_OFF]; + lpmd_init_config_state(state); +@@ -535,7 +571,7 @@ static int build_default_states(lpmd_config_t *config) + * When HFI monitor is enabled and config states are not used, + * Switch system with different CPU affinity based on HFI hints + */ +- if (config->hfi_lpm_enable){ ++ if (config->hfi_lpm_enable) { + state = &config->config_states[DEFAULT_HFI]; + lpmd_init_config_state(state); + state->id = -1; +@@ -547,7 +583,7 @@ static int build_default_states(lpmd_config_t *config) + state->cpumask_idx = CPUMASK_HFI; + state->steady = 0; + state->valid = 1; +- ++ + config->config_state_count = 1; + return 0; + } +@@ -593,9 +629,9 @@ static int build_default_states(lpmd_config_t *config) + return 0; + } + +-static int config_states_update_config(lpmd_config_t *config) ++static int config_states_update_config(struct lpmd_config_t *config) + { +- lpmd_config_state_t *state; ++ struct lpmd_config_state_t *state; + int i; + + for (i = CONFIG_STATE_BASE; i < CONFIG_STATE_BASE + config->config_state_count; i++) { +@@ -622,12 +658,11 @@ static int config_states_update_config(lpmd_config_t *config) + return 0; + } + +- + /* + * Return 0 on success - either when nothing requires setting up Return -1 on error + * and -2 if there are no active cpus specified. + */ +-static int build_state_cpumask_activecpus(lpmd_config_state_t *state) ++static int build_state_cpumask_activecpus(struct lpmd_config_state_t *state) + { + state->steady = 1; + +@@ -672,7 +707,7 @@ static int build_state_cpumask_activecpus(lpmd_config_state_t *state) + return 0; + } + +-static int build_state_cpumask_cputypes(lpmd_config_state_t *state, unsigned char **cmasks) ++static int build_state_cpumask_cputypes(struct lpmd_config_state_t *state, unsigned char **cmasks) + { + int ret; + +@@ -711,9 +746,9 @@ static int build_state_cpumask_cputypes(lpmd_config_state_t *state, unsigned cha + + #define DEFAULT_POLL_RATE_MS 1000 + +-int lpmd_build_config_states(lpmd_config_t *lpmd_config) ++int lpmd_build_config_states(struct lpmd_config_t *lpmd_config) + { +- lpmd_config_state_t *state; ++ struct lpmd_config_state_t *state; + int ret, i; + + build_default_states(lpmd_config); +@@ -727,13 +762,16 @@ int lpmd_build_config_states(lpmd_config_t *lpmd_config) + else if (ret) + continue; + +- if (state->entry_system_load_thres || state->enter_cpu_load_thres || state->enter_gfx_load_thres) ++ if (state->entry_system_load_thres || ++ state->enter_cpu_load_thres || state->enter_gfx_load_thres) + polling_enabled = 1; + + if (state->min_poll_interval <= 0) +- state->min_poll_interval = state->max_poll_interval > DEFAULT_POLL_RATE_MS ? DEFAULT_POLL_RATE_MS : state->max_poll_interval; ++ state->min_poll_interval = state->max_poll_interval > DEFAULT_POLL_RATE_MS ? ++ DEFAULT_POLL_RATE_MS : state->max_poll_interval; + if (state->max_poll_interval <= 0) +- state->max_poll_interval = state->min_poll_interval > DEFAULT_POLL_RATE_MS ? state->min_poll_interval : DEFAULT_POLL_RATE_MS; ++ state->max_poll_interval = state->min_poll_interval > DEFAULT_POLL_RATE_MS ? ++ state->min_poll_interval : DEFAULT_POLL_RATE_MS; + if (state->poll_interval_increment <= 0) + state->poll_interval_increment = -1; + +@@ -757,7 +795,6 @@ int lpmd_build_config_states(lpmd_config_t *lpmd_config) + else + state->enter_gfx_load_thres *= 100; + +- + state->valid = 1; + } + +diff --git a/src/lpmd_uevent.c b/src/lpmd_uevent.c +index 2f286cc..8897c4b 100644 +--- a/src/lpmd_uevent.c ++++ b/src/lpmd_uevent.c +@@ -1,24 +1,10 @@ +-/* +- * lpmd_cpu.c: CPU related processing +- * +- * Copyright (C) 2025 Intel Corporation. All rights reserved. +- * +- * This program is free software; you can redistribute it and/or modify +- * it under the terms of the GNU General Public License as published by +- * the Free Software Foundation; either version 2 of the License, or +- * (at your option) any later version. +- * +- * This program is distributed in the hope that it will be useful, +- * but WITHOUT ANY WARRANTY; without even the implied warranty of +- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +- * GNU General Public License for more details. +- * +- * You should have received a copy of the GNU General Public License +- * along with this program; if not, write to the Free Software +- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +- */ ++// SPDX-License-Identifier: GPL-2.0-or-later ++/* Copyright (C) 2026 Intel Corporation */ + ++#ifndef _GNU_SOURCE + #define _GNU_SOURCE ++#endif ++ + #include + #include + +@@ -35,23 +21,24 @@ static int has_cpu_uevent(void) + const char *cpu_path = "/devices/system/cpu/cpu"; + char buffer[MAX_STR_LENGTH]; + +- len = recv (uevent_fd, buffer, sizeof(buffer) - 1, MSG_DONTWAIT); ++ len = recv(uevent_fd, buffer, sizeof(buffer) - 1, MSG_DONTWAIT); + if (len <= 0) + return 0; + buffer[len] = '\0'; + +- lpmd_log_debug ("Receive uevent: %s\n", buffer); ++ lpmd_log_debug("Receive uevent: %s\n", buffer); + + while (i < len) { +- if (strlen (buffer + i) > dev_path_len +- && !strncmp (buffer + i, dev_path, dev_path_len)) { +- if (!strncmp (buffer + i + dev_path_len, cpu_path, +- strlen (cpu_path))) { +- lpmd_log_debug ("\tMatches: %s\n", buffer + i + dev_path_len); ++ if (strlen(buffer + i) > dev_path_len && ++ !strncmp(buffer + i, dev_path, dev_path_len)) { ++ if (!strncmp(buffer + i + dev_path_len, cpu_path, ++ strlen(cpu_path))) { ++ lpmd_log_debug("\tMatches: %s\n", ++ buffer + i + dev_path_len); + return 1; + } + } +- i += strlen (buffer + i) + 1; ++ i += strlen(buffer + i) + 1; + } + + return 0; +@@ -65,18 +52,18 @@ int check_cpu_hotplug(void) + int curr; + int ret; + +- if (!has_cpu_uevent ()) ++ if (!has_cpu_uevent()) + return 0; + +- filep = fopen (PATH_PROC_STAT, "r"); ++ filep = fopen(PATH_PROC_STAT, "r"); + if (!filep) + return 0; + + curr = cpumask_alloc(); + if (curr == CPUMASK_NONE) + err(3, "ALLOC_CPUMASK"); +- +- while (!feof (filep)) { ++ ++ while (!feof(filep)) { + char *tmpline = NULL; + size_t size = 0; + char *line; +@@ -87,27 +74,27 @@ int check_cpu_hotplug(void) + tmpline = NULL; + size = 0; + +- if (getline (&tmpline, &size, filep) <= 0) { +- free (tmpline); ++ if (getline(&tmpline, &size, filep) <= 0) { ++ free(tmpline); + break; + } + +- line = strdup (tmpline); ++ line = strdup(tmpline); + +- p = strtok (line, " "); ++ p = strtok(line, " "); + +- ret = sscanf (p, "cpu%d", &cpu); ++ ret = sscanf(p, "cpu%d", &cpu); + if (ret != 1) + goto free; + + cpumask_add_cpu(cpu, curr); + + free: +- free (tmpline); +- free (line); ++ free(tmpline); ++ free(line); + } + +- fclose (filep); ++ fclose(filep); + + ret = cpumask_equal(curr, CPUMASK_ONLINE); + cpumask_free(curr); +@@ -124,22 +111,23 @@ int uevent_init(void) + { + struct sockaddr_nl nls; + +- memset (&nls, 0, sizeof(struct sockaddr_nl)); ++ memset(&nls, 0, sizeof(struct sockaddr_nl)); + + nls.nl_family = AF_NETLINK; + nls.nl_pid = getpid(); + nls.nl_groups = -1; + +- uevent_fd = socket (PF_NETLINK, SOCK_DGRAM, NETLINK_KOBJECT_UEVENT); ++ uevent_fd = socket(PF_NETLINK, SOCK_DGRAM, NETLINK_KOBJECT_UEVENT); + if (uevent_fd < 0) + return uevent_fd; + +- if (bind (uevent_fd, (struct sockaddr*) &nls, sizeof(struct sockaddr_nl))) { +- lpmd_log_warn ("kob_uevent bind failed\n"); +- close (uevent_fd); ++ if (bind(uevent_fd, (struct sockaddr *)&nls, ++ sizeof(struct sockaddr_nl))) { ++ lpmd_log_warn("kob_uevent bind failed\n"); ++ close(uevent_fd); + return -1; + } + +- lpmd_log_debug ("Uevent binded\n"); ++ lpmd_log_debug("Uevent binded\n"); + return uevent_fd; + } +diff --git a/src/lpmd_util.c b/src/lpmd_util.c +index 63cf7c5..67dff74 100644 +--- a/src/lpmd_util.c ++++ b/src/lpmd_util.c +@@ -1,25 +1,6 @@ +-/* +- * util.c: intel_lpmd utilization monitor +- * +- * Copyright (C) 2023 Intel Corporation. All rights reserved. +- * +- * This program is free software; you can redistribute it and/or modify +- * it under the terms of the GNU General Public License as published by +- * the Free Software Foundation; either version 2 of the License, or +- * (at your option) any later version. +- * +- * This program is distributed in the hope that it will be useful, +- * but WITHOUT ANY WARRANTY; without even the implied warranty of +- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +- * GNU General Public License for more details. +- * +- * You should have received a copy of the GNU General Public License +- * along with this program; if not, write to the Free Software +- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +- * +- * This file contains logic similar to "top" program to get utilization from +- * /proc/sys kernel interface. +- */ ++// SPDX-License-Identifier: GPL-2.0-or-later ++/* Copyright(c) 2022 Intel Corporation. All rights reserved. */ ++ + #define _GNU_SOURCE + #include + #include +@@ -40,7 +21,6 @@ + + #define PATH_PROC_STAT "/proc/stat" + +- + enum type_stat { + STAT_CPU, + STAT_USER, +@@ -117,7 +97,8 @@ static int get_gfx_util_sysfs(unsigned long long time_ms) + unsigned long long gfx_util, sam_util; + int ret; + +- gfx_util = sam_util = -1; ++ gfx_util = -1; ++ sam_util = -1; + + fp = fopen(path_gfx_rc6, "r"); + if (fp) { +@@ -167,7 +148,7 @@ static int parse_gfx_util_sysfs(void) + if (!gfx_sysfs_available) + return 1; + +- clock_gettime (CLOCK_MONOTONIC, &ts_cur); ++ clock_gettime(CLOCK_MONOTONIC, &ts_cur); + + if (!ts_prev.tv_sec && !ts_prev.tv_nsec) { + ret = probe_gfx_util_sysfs(); +@@ -179,7 +160,8 @@ static int parse_gfx_util_sysfs(void) + return 0; + } + +- time_ms = (ts_cur.tv_sec - ts_prev.tv_sec) * 1000 + (ts_cur.tv_nsec - ts_prev.tv_nsec) / 1000000; ++ time_ms = (ts_cur.tv_sec - ts_prev.tv_sec) * 1000 + ++ (ts_cur.tv_nsec - ts_prev.tv_nsec) / 1000000; + + ts_prev = ts_cur; + busy_gfx = get_gfx_util_sysfs(time_ms); +@@ -191,10 +173,8 @@ static int parse_gfx_util_sysfs(void) + #define MSR_PKG_ANY_GFXE_C0_RES 0x65A + static int parse_gfx_util_msr(void) + { +- static uint64_t val_prev; +- uint64_t val; +- static uint64_t tsc_prev; +- uint64_t tsc; ++ static uint64_t val_prev, tsc_prev; ++ uint64_t _busy_gfx, val, tsc; + int cpu; + + busy_gfx = -1; +@@ -214,9 +194,7 @@ static int parse_gfx_util_msr(void) + return 0; + } + +- if (val > val_prev && tsc >tsc_prev) { +- uint64_t _busy_gfx; +- ++ if (val > val_prev && tsc > tsc_prev) { + _busy_gfx = abs(val - val_prev) * 10000ULL / abs(tsc - tsc_prev); + if (_busy_gfx < INT_MAX) + busy_gfx = (int)_busy_gfx; +@@ -226,7 +204,7 @@ static int parse_gfx_util_msr(void) + val_prev = val; + return 0; + err: +- lpmd_log_debug("parse_gfx_util_msr failed\n"); ++ lpmd_log_debug("%s failed\n", __func__); + return 1; + } + +@@ -270,32 +248,32 @@ static int parse_proc_stat(void) + int sys_idx = count - 1; + size_t size = sizeof(struct proc_stat_info) * count; + +- filep = fopen (PATH_PROC_STAT, "r"); ++ filep = fopen(PATH_PROC_STAT, "r"); + if (!filep) + return 1; + + if (!proc_stat_prev) +- proc_stat_prev = calloc(sizeof(struct proc_stat_info), count); ++ proc_stat_prev = calloc(count, sizeof(struct proc_stat_info)); + + if (!proc_stat_prev) { +- fclose (filep); ++ fclose(filep); + return 1; + } + + if (!proc_stat_cur) +- proc_stat_cur = calloc(sizeof(struct proc_stat_info), count); ++ proc_stat_cur = calloc(count, sizeof(struct proc_stat_info)); + + if (!proc_stat_cur) { + free(proc_stat_prev); +- fclose (filep); ++ fclose(filep); + proc_stat_prev = NULL; + return 1; + } + +- memcpy (proc_stat_prev, proc_stat_cur, size); +- memset (proc_stat_cur, 0, size); ++ memcpy(proc_stat_prev, proc_stat_cur, size); ++ memset(proc_stat_cur, 0, size); + +- while (!feof (filep)) { ++ while (!feof(filep)) { + int idx; + char *tmpline = NULL; + struct proc_stat_info *info; +@@ -307,68 +285,66 @@ static int parse_proc_stat(void) + tmpline = NULL; + size = 0; + +- if (getline (&tmpline, &size, filep) <= 0) { +- free (tmpline); ++ if (getline(&tmpline, &size, filep) <= 0) { ++ free(tmpline); + break; + } + +- line = strdup (tmpline); ++ line = strdup(tmpline); + +- p = strtok (line, " "); ++ p = strtok(line, " "); + +- if (strncmp (p, "cpu", 3)) { +- free (tmpline); +- free (line); ++ if (strncmp(p, "cpu", 3)) { ++ free(tmpline); ++ free(line); + continue; + } + +- ret = sscanf (p, "cpu%d", &cpu); +- if (ret == -1 && !(strncmp (p, "cpu", 3))) { ++ ret = sscanf(p, "cpu%d", &cpu); ++ if (ret == -1 && !(strncmp(p, "cpu", 3))) { + /* Read system line */ + info = &proc_stat_cur[sys_idx]; +- } +- else if (ret == 1) { ++ } else if (ret == 1) { + info = &proc_stat_cur[cpu]; +- } +- else { +- free (tmpline); +- free (line); ++ } else { ++ free(tmpline); ++ free(line); + continue; + } + + info->valid = 1; + idx = STAT_CPU; + +- while (p != NULL) { ++ while (p) { + if (idx >= STAT_MAX) + break; + + if (idx == STAT_CPU) { + idx++; +- p = strtok (NULL, " "); ++ p = strtok(NULL, " "); + continue; + } + +- if (sscanf (p, "%llu", &info->stat[idx]) <= 0) ++ if (sscanf(p, "%llu", &info->stat[idx]) <= 0) + lpmd_log_debug("Failed to parse /proc/stat, defer update in next snapshot."); + +- p = strtok (NULL, " "); ++ p = strtok(NULL, " "); + idx++; + } + +- free (tmpline); +- free (line); ++ free(tmpline); ++ free(line); + } + +- fclose (filep); +- busy_sys = calculate_busypct (&proc_stat_cur[sys_idx], &proc_stat_prev[sys_idx]); ++ fclose(filep); ++ busy_sys = calculate_busypct(&proc_stat_cur[sys_idx], &proc_stat_prev[sys_idx]); + + busy_cpu = 0; + for (i = 1; i <= get_max_online_cpu(); i++) { + if (!proc_stat_cur[i].valid) + continue; + +- val = calculate_busypct (&proc_stat_cur[i], &proc_stat_prev[i]); ++ val = calculate_busypct(&proc_stat_cur[i], &proc_stat_prev[i]); + if (busy_cpu < val) + busy_cpu = val; + } +@@ -376,10 +352,10 @@ static int parse_proc_stat(void) + return 0; + } + +-int util_update(lpmd_config_t *lpmd_config) ++int util_update(struct lpmd_config_t *lpmd_config) + { + if (lpmd_config->util_sys_enable || lpmd_config->util_cpu_enable) { +- parse_proc_stat (); ++ parse_proc_stat(); + lpmd_config->data.util_sys = busy_sys; + lpmd_config->data.util_cpu = busy_cpu; + } +diff --git a/src/lpmd_wlt.c b/src/lpmd_wlt.c +index d44a895..becf327 100644 +--- a/src/lpmd_wlt.c ++++ b/src/lpmd_wlt.c +@@ -1,27 +1,12 @@ +-/* +- * lpmd_wlt.c: intel_lpmd WLT (WorkLoadType) monitor +- * +- * Copyright (C) 2025 Intel Corporation. All rights reserved. +- * +- * This program is free software; you can redistribute it and/or modify +- * it under the terms of the GNU General Public License as published by +- * the Free Software Foundation; either version 2 of the License, or +- * (at your option) any later version. +- * +- * This program is distributed in the hope that it will be useful, +- * but WITHOUT ANY WARRANTY; without even the implied warranty of +- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +- * GNU General Public License for more details. +- * +- * You should have received a copy of the GNU General Public License +- * along with this program; if not, write to the Free Software +- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +- */ ++// SPDX-License-Identifier: GPL-2.0-or-later ++/* Copyright (C) 2026 Intel Corporation */ ++ ++#ifndef _GNU_SOURCE + #define _GNU_SOURCE ++#endif + + #include "lpmd.h" + +- + // Workload type classification + #define WORKLOAD_NOTIFICATION_DELAY_ATTRIBUTE "/sys/bus/pci/devices/0000:00:04.0/workload_hint/notification_delay_ms" + #define WORKLOAD_ENABLE_ATTRIBUTE "/sys/bus/pci/devices/0000:00:04.0/workload_hint/workload_hint_enable" +@@ -66,7 +51,7 @@ int wlt_exit(void) + + // Disable WLT notification + if (write(fd, "0\n", 2) < 0) { +- close (fd); ++ close(fd); + return 0; + } + +@@ -76,12 +61,12 @@ int wlt_exit(void) + } + + // Initialize Workload type notifications +-int wlt_init (void) ++int wlt_init(void) + { + char delay_str[64]; + int fd; + +- lpmd_log_debug ("init_wlt begin\n"); ++ lpmd_log_debug("init_wlt begin\n"); + + // Set notification delay + fd = open(WORKLOAD_NOTIFICATION_DELAY_ATTRIBUTE, O_RDWR); +@@ -116,7 +101,7 @@ int wlt_init (void) + return fd; + } + +- lpmd_log_debug ("init_wlt end wlt fd:%d\n", fd); ++ lpmd_log_debug("init_wlt end wlt fd:%d\n", fd); + + return fd; + } +diff --git a/src/wlt_proxy/include/state_common.h b/src/wlt_proxy/include/state_common.h +index 8825362..a1cd661 100644 +--- a/src/wlt_proxy/include/state_common.h ++++ b/src/wlt_proxy/include/state_common.h +@@ -1,79 +1,70 @@ +-/* +- * state_common.h: Intel Linux Energy Optimizer proxy detection common header file +- * +- * Copyright (C) 2024 Intel Corporation. All rights reserved. +- * +- * This program is free software; you can redistribute it and/or modify +- * it under the terms of the GNU General Public License as published by +- * the Free Software Foundation; either version 2 of the License, or +- * (at your option) any later version. +- * +- * This program is distributed in the hope that it will be useful, +- * but WITHOUT ANY WARRANTY; without even the implied warranty of +- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +- * GNU General Public License for more details. +- * +- * You should have received a copy of the GNU General Public License +- * along with this program; if not, write to the Free Software +- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +- */ ++/* SPDX-License-Identifier: GPL-2.0-or-later */ ++/* Copyright (C) 2026 Intel Corporation */ + + #ifndef _WLT_PROXY_COMMON_H_ + #define _WLT_PROXY_COMMON_H_ + + /* threshold (%) for instantaneous utilizations */ +-#define UTIL_LOWEST 1 +-#define UTIL_LOWER 2 +-#define UTIL_LOW 10 +-#define UTIL_FILL_START 35 +-#define UTIL_BELOW_HALF 40 +-#define UTIL_HALF 50 +-#define UTIL_ABOVE_HALF 70 +-#define UTIL_NEAR_FULL 90 ++#define UTIL_LOWEST 1 ++#define UTIL_LOWER 2 ++#define UTIL_LOW 10 ++#define UTIL_FILL_START 35 ++#define UTIL_BELOW_HALF 40 ++#define UTIL_HALF 50 ++#define UTIL_ABOVE_HALF 70 ++#define UTIL_NEAR_FULL 90 + + /* floating point comparison */ +-#define EPSILON (0.01) +-#define A_LTE_B(A,B) (((B-A) >= EPSILON) ? 1 : 0 ) +-#define A_GTE_B(A,B) (((A-B) >= EPSILON) ? 1 : 0 ) +-#define A_GT_B(A,B) (((A-B) > EPSILON) ? 1 : 0 ) ++#define EPSILON (0.01) ++#define A_LTE_B(A, B) ((((B) - (A)) >= EPSILON) ? 1 : 0) ++#define A_GTE_B(A, B) ((((A) - (B)) >= EPSILON) ? 1 : 0) ++#define A_GT_B(A, B) ((((A) - (B)) > EPSILON) ? 1 : 0) + + /* state indexes for WLT proxy detection based cpu usage high to low */ + enum state_idx { +- INIT_MODE, +- PERF_MODE, +- MDRT4E_MODE, +- MDRT3E_MODE, +- MDRT2E_MODE, +- RESP_MODE, +- NORM_MODE, +- DEEP_MODE ++ INIT_MODE, ++ PERF_MODE, ++ MDRT4E_MODE, ++ MDRT3E_MODE, ++ MDRT2E_MODE, ++ RESP_MODE, ++ NORM_MODE, ++ DEEP_MODE + }; +-#define MAX_MODE 8 ++ ++extern int state_demote; /* from state_manager.c */ ++extern int burst_count; /* from spike_mgmt.c */ ++extern struct group_util grp; /* from state_util.c */ ++extern int next_proxy_poll; /* from wlt_proxy.c */ ++extern int max_util; /* from state_machine.c */ ++extern int wlt_type; /* from wlt_proxy.c */ ++ ++#define MAX_MODE 8 + + struct group_util { +- /* top 3 max utils and last (min) util */ +- float c0_max; +- float c0_min; +- float worst_stall; +- int worst_stall_cpu; +- float c0_2nd_max; +- float c0_3rd_max; +- int delta; +- +- /* simple moving average for top 3 utils */ +- int sma_sum[3]; +- int sma_avg1; +- int sma_avg2; +- int sma_avg3; +- int sma_pos; ++ /* top 3 max utils and last (min) util */ ++ float c0_max; ++ float c0_min; ++ float worst_stall; ++ int worst_stall_cpu; ++ float c0_2nd_max; ++ float c0_3rd_max; ++ int delta; ++ ++ /* simple moving average for top 3 utils */ ++ int sma_sum[3]; ++ int sma_avg1; ++ int sma_avg2; ++ int sma_avg3; ++ int sma_pos; + }; + + /* feature states */ +-#define DEACTIVATED (-1) +-#define UNDEFINED (0) +-#define RUNNING (1) +-#define ACTIVATED (2) +-#define PAUSE (3) ++#define DEACTIVATED (-1) ++#define UNDEFINED (0) ++#define RUNNING (1) ++#define ACTIVATED (2) ++#define PAUSE (3) + + /* state_manager.c */ + void uninit_state_manager(void); +@@ -82,13 +73,13 @@ enum state_idx get_cur_state(void); + + int get_last_poll(void); + int get_poll_ms(enum state_idx); +-int get_state_poll(int, enum state_idx); ++int get_state_poll(int util, enum state_idx); + +-int set_stay_count(enum state_idx, int); ++int set_stay_count(enum state_idx, int count); + int get_stay_count(enum state_idx); + + int staytime_to_staycount(enum state_idx state); +-int prep_state_change(enum state_idx, enum state_idx, int); ++int prep_state_change(enum state_idx, enum state_idx, int reset); + + int do_countdown(enum state_idx); + +@@ -96,21 +87,21 @@ int do_countdown(enum state_idx); + int util_init_proxy(void); + void util_uninit_proxy(void); + +-int state_max_avg(); +-int update_perf_diffs(float *, int); ++int state_max_avg(void); ++int update_perf_diffs(float *sum_norm_perf, int stat_init_only); + + int max_mt_detected(enum state_idx); + + /* state_machine.c */ +-int state_machine_auto(); ++int state_machine_auto(void); + + /* spike_mgmt.c */ +-int add_spike_time(int); +-int add_non_spike_time(int); ++int add_spike_time(int duration); ++int add_non_spike_time(int duration); + int get_spike_rate(void); + int get_burst_rate_per_min(void); + int fresh_burst_response(int initial_val); + int burst_rate_breach(void); +-int strikeout_once(int); ++int strikeout_once(int n); + + #endif /* _WLT_PROXY_COMMON_H_ */ +diff --git a/src/wlt_proxy/include/wlt_proxy.h b/src/wlt_proxy/include/wlt_proxy.h +index 977540f..992a25b 100644 +--- a/src/wlt_proxy/include/wlt_proxy.h ++++ b/src/wlt_proxy/include/wlt_proxy.h +@@ -1,29 +1,11 @@ +-/* +- * wlt_proxy.h: Intel Linux Energy Optimizer proxy detection header file +- * +- * Copyright (C) 2024 Intel Corporation. All rights reserved. +- * +- * This program is free software; you can redistribute it and/or modify +- * it under the terms of the GNU General Public License as published by +- * the Free Software Foundation; either version 2 of the License, or +- * (at your option) any later version. +- * +- * This program is distributed in the hope that it will be useful, +- * but WITHOUT ANY WARRANTY; without even the implied warranty of +- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +- * GNU General Public License for more details. +- * +- * You should have received a copy of the GNU General Public License +- * along with this program; if not, write to the Free Software +- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +- */ ++/* SPDX-License-Identifier: GPL-2.0-or-later */ ++/* Copyright (C) 2026 Intel Corporation */ ++ + #ifndef _WLT_PROXY_H_ + #define _WLT_PROXY_H_ + +-int read_wlt_proxy(int* interval); +- +-int wlt_proxy_init(); +- ++int read_wlt_proxy(int *interval); ++int wlt_proxy_init(void); + void wlt_proxy_uninit(void); + + #endif/* _WLT_PROXY_H_ */ +diff --git a/src/wlt_proxy/spike_mgmt.c b/src/wlt_proxy/spike_mgmt.c +index d0b2623..4de009a 100644 +--- a/src/wlt_proxy/spike_mgmt.c ++++ b/src/wlt_proxy/spike_mgmt.c +@@ -1,24 +1,6 @@ +-/* +- * spike_mgmt.c: Intel Low Power Daemon WLT proxy spike detection in CPU usage. +- * +- * Copyright (C) 2024 Intel Corporation. All rights reserved. +- * +- * This program is free software; you can redistribute it and/or modify +- * it under the terms of the GNU General Public License as published by +- * the Free Software Foundation; either version 2 of the License, or +- * (at your option) any later version. +- * +- * This program is distributed in the hope that it will be useful, +- * but WITHOUT ANY WARRANTY; without even the implied warranty of +- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +- * GNU General Public License for more details. +- * +- * You should have received a copy of the GNU General Public License +- * along with this program; if not, write to the Free Software +- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +- * +- * This file contains condition checks for CPU utilization spikes and idleness count/detection. +- */ ++// SPDX-License-Identifier: GPL-2.0-or-later ++/* Copyright (C) 2026 Intel Corporation */ ++ + #define _GNU_SOURCE + + #include +@@ -51,38 +33,40 @@ + * SPIKE_TIME_BIAS macro will bias this to be longer or shorter based on + * recent history (i.e more prominent the spiking, the longer it will be remembered) + */ +-#define MAX_TRACKED_SPIKE_TIME 1000 +-#define MAX_BURST_COUNT 1000 +-#define BURST_COUNT_THRESHOLD 3 ++#define MAX_TRACKED_SPIKE_TIME 1000 ++#define MAX_BURST_COUNT 1000 ++#define BURST_COUNT_THRESHOLD 3 + + //shorten time by 50% if spike rate was as low as 0. No change if spike rate was 100 +-#define SPIKE_TIME_BIAS(avg, min) ((100 - avg) * min/(2 * 100)) ++#define SPIKE_TIME_BIAS(avg, min) ((100 - (avg)) * (min) / (2 * 100)) + +-extern int state_demote; +-int burst_count = 0; ++int burst_count; + + /*local variables*/ + static int total_spike_time; +-static int spike_sec_prev = 0; ++static int spike_sec_prev; + static int spike_rate_total; + static int spike_rate_samples; + static int burst_rate_per_min; +-static bool spike_burst_flag = false; ++static bool spike_burst_flag; + static float bc_reset_min = 90.0; + static int once_flag; + static int strike_count; + + /** increment avg spike rate */ +-int update_spike_rate_avg(int sr) { +- spike_rate_total += sr; +- spike_rate_samples++; +- return 1; ++int update_spike_rate_avg(int sr) ++{ ++ spike_rate_total += sr; ++ spike_rate_samples++; ++ return 1; + } + + /** reset avg spike rate */ +-int clear_spike_rate_avg() { +- spike_rate_samples = spike_rate_total = 0; +- return 1; ++int clear_spike_rate_avg(void) ++{ ++ spike_rate_samples = 0; ++ spike_rate_total = 0; ++ return 1; + } + + /** +@@ -91,121 +75,129 @@ int clear_spike_rate_avg() { + * just a refresh to burst_count (0) + * burst count is decremented if no spikes in last 1 min + */ +-static int update_burst_count(int real_spike_burst) { +- float minutes = 1.0; +- clockid_t clk = CLOCK_MONOTONIC; +- struct timespec ts; +- +- if (clock_gettime(clk, &ts)) { +- perror("clock_gettime1"); +- return -1; +- } +- +- if (spike_sec_prev) { +- minutes = (float)(ts.tv_sec - spike_sec_prev) / bc_reset_min; +- } else { +- spike_sec_prev = ts.tv_sec; +- return 0; +- } +- +- if (real_spike_burst && (get_cur_state() <= MDRT4E_MODE)) { +- burst_count++; +- spike_sec_prev = ts.tv_sec; +- } else if ((minutes > 1.0) || (burst_count > MAX_BURST_COUNT)) { +- burst_count = 0; +- spike_sec_prev = ts.tv_sec; +- } +- +- if (minutes < 1.0) { +- burst_rate_per_min = burst_count; +- } else if (minutes && (minutes > 1.0)) { +- burst_rate_per_min = (int)((float)burst_count / minutes); +- } +- +- return burst_rate_per_min; ++static int update_burst_count(int real_spike_burst) ++{ ++ float minutes = 1.0; ++ clockid_t clk = CLOCK_MONOTONIC; ++ struct timespec ts; ++ ++ if (clock_gettime(clk, &ts)) { ++ perror("clock_gettime1"); ++ return -1; ++ } ++ ++ if (spike_sec_prev) { ++ minutes = (float)(ts.tv_sec - spike_sec_prev) / bc_reset_min; ++ } else { ++ spike_sec_prev = ts.tv_sec; ++ return 0; ++ } ++ ++ if (real_spike_burst && (get_cur_state() <= MDRT4E_MODE)) { ++ burst_count++; ++ spike_sec_prev = ts.tv_sec; ++ } else if ((minutes > 1.0) || (burst_count > MAX_BURST_COUNT)) { ++ burst_count = 0; ++ spike_sec_prev = ts.tv_sec; ++ } ++ ++ if (minutes < 1.0) ++ burst_rate_per_min = burst_count; ++ else if (minutes && (minutes > 1.0)) ++ burst_rate_per_min = (int)((float)burst_count / minutes); ++ ++ return burst_rate_per_min; + } + +-int get_burst_rate_per_min(void) { +- return burst_rate_per_min; ++int get_burst_rate_per_min(void) ++{ ++ return burst_rate_per_min; + } + +-int fresh_burst_response(int initial_burst_rate) { +- if (!initial_burst_rate) +- return 0; +- if ((initial_burst_rate >= BURST_COUNT_THRESHOLD) || +- (get_burst_rate_per_min() > initial_burst_rate)) +- return 1; +- return 0; ++int fresh_burst_response(int initial_burst_rate) ++{ ++ if (!initial_burst_rate) ++ return 0; ++ if (initial_burst_rate >= BURST_COUNT_THRESHOLD || ++ get_burst_rate_per_min() > initial_burst_rate) ++ return 1; ++ return 0; + } + +-int burst_rate_breach(void) { +- return (get_burst_rate_per_min() >= BURST_COUNT_THRESHOLD) ? 1 : 0; ++int burst_rate_breach(void) ++{ ++ return (get_burst_rate_per_min() >= BURST_COUNT_THRESHOLD) ? 1 : 0; + } + + /* Calculate spike rate */ +-int get_spike_rate() { +- int spike_pct = total_spike_time * 100 / MAX_TRACKED_SPIKE_TIME; +- return (spike_pct > 100) ? 100 : spike_pct; ++int get_spike_rate(void) ++{ ++ int spike_pct = total_spike_time * 100 / MAX_TRACKED_SPIKE_TIME; ++ ++ return (spike_pct > 100) ? 100 : spike_pct; + } + + /* count spikes */ +-int add_spike_time(int duration) { +- int spike_rate; +- +- if (total_spike_time < MAX_TRACKED_SPIKE_TIME) +- total_spike_time += duration; +- +- /* spike burst has more than 1 spike */ +- if (!spike_burst_flag) { +- /* rising edge of spike burst */ +- spike_burst_flag = true; +- } else if (state_demote && !once_flag) { +- update_burst_count(1); +- once_flag = 1; +- } +- +- spike_rate = get_spike_rate(); +- update_spike_rate_avg(spike_rate); +- return 1; ++int add_spike_time(int duration) ++{ ++ int spike_rate; ++ ++ if (total_spike_time < MAX_TRACKED_SPIKE_TIME) ++ total_spike_time += duration; ++ ++ /* spike burst has more than 1 spike */ ++ if (!spike_burst_flag) { ++ /* rising edge of spike burst */ ++ spike_burst_flag = true; ++ } else if (state_demote && !once_flag) { ++ update_burst_count(1); ++ once_flag = 1; ++ } ++ ++ spike_rate = get_spike_rate(); ++ update_spike_rate_avg(spike_rate); ++ return 1; + } + + /* count idleness / non spike times */ +-int add_non_spike_time(int duration) { +- float avg; +- int sr; +- +- if (total_spike_time > 0) +- total_spike_time -= duration; +- total_spike_time = (total_spike_time < 0) ? 0 : total_spike_time; +- +- sr = get_spike_rate(); +- if (!sr && spike_burst_flag) { +- /* falling edge of burst */ +- spike_burst_flag = false; +- avg = spike_rate_total / spike_rate_samples; +- +- if (!once_flag) +- update_burst_count(1); +- +- bc_reset_min = 60.0 - (int)SPIKE_TIME_BIAS(avg, bc_reset_min); +- clear_spike_rate_avg(); +- once_flag = 0; +- } else { +- update_burst_count(0); +- once_flag = 0; +- } +- return 1; ++int add_non_spike_time(int duration) ++{ ++ float avg; ++ int sr; ++ ++ if (total_spike_time > 0) ++ total_spike_time -= duration; ++ total_spike_time = (total_spike_time < 0) ? 0 : total_spike_time; ++ ++ sr = get_spike_rate(); ++ if (!sr && spike_burst_flag) { ++ /* falling edge of burst */ ++ spike_burst_flag = false; ++ avg = spike_rate_total / spike_rate_samples; ++ ++ if (!once_flag) ++ update_burst_count(1); ++ ++ bc_reset_min = 60.0 - (int)SPIKE_TIME_BIAS(avg, bc_reset_min); ++ clear_spike_rate_avg(); ++ once_flag = 0; ++ } else { ++ update_burst_count(0); ++ once_flag = 0; ++ } ++ return 1; + } + + /* decrement strike count */ +-int strikeout_once(int n) { +- if (!strike_count) +- strike_count = n; +- else +- strike_count -= 1; ++int strikeout_once(int n) ++{ ++ if (!strike_count) ++ strike_count = n; ++ else ++ strike_count -= 1; + +- if (strike_count < 0) +- strike_count = 0; ++ if (strike_count < 0) ++ strike_count = 0; + +- return strike_count; ++ return strike_count; + } +diff --git a/src/wlt_proxy/state_machine.c b/src/wlt_proxy/state_machine.c +index 150616e..33e86d2 100644 +--- a/src/wlt_proxy/state_machine.c ++++ b/src/wlt_proxy/state_machine.c +@@ -1,24 +1,5 @@ +-/* +- * state_machine.c: Intel Low Power Daemon WLT proxy state change handling. +- * +- * Copyright (C) 2024 Intel Corporation. All rights reserved. +- * +- * This program is free software; you can redistribute it and/or modify +- * it under the terms of the GNU General Public License as published by +- * the Free Software Foundation; either version 2 of the License, or +- * (at your option) any later version. +- * +- * This program is distributed in the hope that it will be useful, +- * but WITHOUT ANY WARRANTY; without even the implied warranty of +- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +- * GNU General Public License for more details. +- * +- * You should have received a copy of the GNU General Public License +- * along with this program; if not, write to the Free Software +- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +- * +- * This file contains condition checks for state switch. +- */ ++// SPDX-License-Identifier: GPL-2.0-or-later ++/* Copyright (C) 2026 Intel Corporation */ + + #define _GNU_SOURCE + #include +@@ -32,305 +13,303 @@ + * e.g due to memory or other dependency. If work is reasonably scaling well, + * values in 80 to 90+% is expected + */ +-#define STALL_SCALE_LOWER_MARK 60 ++#define STALL_SCALE_LOWER_MARK 60 + +-#define N_STRIKE (10) ++#define N_STRIKE (10) + + /* threshold (%) for sustained (avg) utilizations */ +-#define SUS_LOWER 2 +-#define SUS_LOW_RANGE_START 4 +-#define SUS_LOW_RANGE_END 25 +- +-extern int burst_count; +-extern struct group_util grp; +-extern int state_demote; +-extern int next_proxy_poll; ++#define SUS_LOWER 2 ++#define SUS_LOW_RANGE_START 4 ++#define SUS_LOW_RANGE_END 25 + + int max_util; + +-static int only_once = 0; ++static int only_once; + + /* function checks conditions for state switch */ +-int state_machine_auto() { ++int state_machine_auto(void) ++{ ++ int mdrt_count, perf_count, initial_burst_count, sr, ismt; ++ int present_state = get_cur_state(); ++ float dummy, sum_c0; ++ int completed_poll; ++ ++ update_perf_diffs(&dummy, 0); ++ max_util = (int)round(grp.c0_max); //end ++ ++ /* ++ * we do not want to track avg util for following case: ++ * a) Responsive transit mode (fast poll can flood avg leading to incorrect decisions) ++ */ ++ if (present_state != RESP_MODE) ++ state_max_avg(); + +- float dummy; +- int present_state = get_cur_state(); ++ completed_poll = get_last_poll(); ++ sum_c0 = grp.c0_max + grp.c0_2nd_max + grp.c0_3rd_max; ++ initial_burst_count = get_burst_rate_per_min(); + +- update_perf_diffs(&dummy, 0); +- max_util = (int)round(grp.c0_max); //end ++ mdrt_count = get_stay_count(MDRT3E_MODE); ++ sr = get_spike_rate(); + +- /* +- * we do not want to track avg util for following case: +- * a) Responsive transit mode (fast poll can flood avg leading to incorrect decisions) +- */ +- if (present_state != RESP_MODE) +- state_max_avg(); ++ if (A_LTE_B(grp.c0_max, UTIL_NEAR_FULL)) ++ add_non_spike_time(completed_poll); ++ else if (A_GT_B(grp.c0_max, UTIL_NEAR_FULL) || sr) ++ add_spike_time(completed_poll); + +- int completed_poll = get_last_poll(); +- float sum_c0 = grp.c0_max + grp.c0_2nd_max + grp.c0_3rd_max; +- int mdrt_count; +- int perf_count, initial_burst_count; +- initial_burst_count = get_burst_rate_per_min(); +- mdrt_count = get_stay_count(MDRT3E_MODE); +- int sr = get_spike_rate(); ++ /* should we reset perf-count due to new burst? */ ++ if (fresh_burst_response(initial_burst_count)) { ++ set_stay_count(PERF_MODE, staytime_to_staycount(PERF_MODE)); ++ set_stay_count(MDRT3E_MODE, 0); ++ } + +- if (A_LTE_B(grp.c0_max, UTIL_NEAR_FULL)) { +- add_non_spike_time(completed_poll); +- } else if (A_GT_B(grp.c0_max, UTIL_NEAR_FULL) || sr) { +- add_spike_time(completed_poll); +- } ++ perf_count = get_stay_count(PERF_MODE); ++ if (!perf_count && !mdrt_count) ++ set_stay_count(MDRT3E_MODE, staytime_to_staycount(MDRT3E_MODE)); + +- /* should we reset perf-count due to new burst? */ +- if (fresh_burst_response(initial_burst_count)) { +- set_stay_count(PERF_MODE, staytime_to_staycount(PERF_MODE)); +- set_stay_count(MDRT3E_MODE, 0); +- } +- perf_count = get_stay_count(PERF_MODE); +- if (!perf_count && !mdrt_count) +- set_stay_count(MDRT3E_MODE, staytime_to_staycount(MDRT3E_MODE)); ++ state_demote = 0; ++ ismt = !max_mt_detected(INIT_MODE); + +- state_demote = 0; +- int isMT = !max_mt_detected(INIT_MODE); ++ if (only_once == 0) { ++ lpmd_log_debug("present_state, isMT, C0_max, C0_2ndMax, sum_c0, sma avg1, sma avg2, sma avg3, worst_stall, next_proxy_poll\n"); ++ only_once = 1; ++ } + +- if(only_once == 0) { +- lpmd_log_debug("present_state, isMT, C0_max, C0_2ndMax, sum_c0, sma avg1, sma avg2, sma avg3, worst_stall, next_proxy_poll\n"); +- only_once = 1; +- } +- lpmd_log_debug("%d, %d, %.2f, %.2f, %.2f, %d, %d, %d, %.2f, %d\n", \ +- present_state, \ +- isMT, \ +- grp.c0_max, \ +- grp.c0_2nd_max, \ +- sum_c0, \ +- grp.sma_avg1, \ +- grp.sma_avg2, \ +- grp.sma_avg3, \ +- grp.worst_stall, \ +- next_proxy_poll); ++ lpmd_log_debug("%d, %d, %.2f, %.2f, %.2f, %d, %d, %d, %.2f, %d\n", ++ present_state, ++ ismt, ++ grp.c0_max, ++ grp.c0_2nd_max, ++ sum_c0, ++ grp.sma_avg1, ++ grp.sma_avg2, ++ grp.sma_avg3, ++ grp.worst_stall, ++ next_proxy_poll); + +- switch (present_state) { +- case INIT_MODE: +- /* +- * init mode is super-set of all default/available cpu on the system. +- */ +- /* promote -- if not high multi-thread trend */ +- if (!max_mt_detected(INIT_MODE)) { +- lpmd_log_debug("INIT_MODE to PERF_MODE\n"); +- prep_state_change(INIT_MODE, PERF_MODE, 0); +- break; +- } +- // stay -- full MT +- break; ++ switch (present_state) { ++ case INIT_MODE: ++ // init mode is super-set of all default/available cpu on the system ++ // promote -- if not high multi-thread trend ++ if (!max_mt_detected(INIT_MODE)) { ++ lpmd_log_debug("INIT_MODE to PERF_MODE\n"); ++ prep_state_change(INIT_MODE, PERF_MODE, 0); ++ break; ++ } ++ // stay -- full MT ++ break; + +- case PERF_MODE: +- // Demote -- if highly MT +- if (max_mt_detected(PERF_MODE)) { +- lpmd_log_debug("PERF_MODE to INIT_MODE = mt detected.\n"); +- prep_state_change(PERF_MODE, INIT_MODE, 0); +- break; +- } +- // Stay -- if there was recent perf/resp bursts +- if (burst_count > 0 && !do_countdown(PERF_MODE)){ +- lpmd_log_debug("PERF_MODE: burst_count is %d > 0 && !do_countdown\n", burst_count); +- break; +- } +- // Promote but through responsive watch -- if top sampled util and their avg are receding. +- if (A_LTE_B(sum_c0, (2 * UTIL_LOW)) && +- A_LTE_B(grp.sma_avg1, UTIL_ABOVE_HALF)) { +- lpmd_log_debug("PERF_MODE to RESP_MODE\n"); +- prep_state_change(PERF_MODE, RESP_MODE, 0); +- break; +- } +- // Promote -- to moderate (3) MT state +- if (!burst_rate_breach() && A_LTE_B(grp.c0_max, UTIL_LOW)) // && A_LTE_B(sum_avg, UTIL_BELOW_HALF)) +- { +- set_stay_count(MDRT3E_MODE, 0); +- lpmd_log_debug("PERF_MODE to MDRT3E_MODE\n"); +- prep_state_change(PERF_MODE, MDRT3E_MODE, 0); +- break; +- } +- //Stay -- all else +- break; ++ case PERF_MODE: ++ // Demote -- if highly MT ++ if (max_mt_detected(PERF_MODE)) { ++ lpmd_log_debug("PERF_MODE to INIT_MODE = mt detected.\n"); ++ prep_state_change(PERF_MODE, INIT_MODE, 0); ++ break; ++ } ++ // Stay -- if there was recent perf/resp bursts ++ if (burst_count > 0 && !do_countdown(PERF_MODE)) { ++ lpmd_log_debug("PERF_MODE: burst_count is %d > 0 && !do_countdown\n", ++ burst_count); ++ break; ++ } ++ // Promote but through responsive watch -- if top sampled util and their avg are receding. ++ if (A_LTE_B(sum_c0, (2 * UTIL_LOW)) && ++ A_LTE_B(grp.sma_avg1, UTIL_ABOVE_HALF)) { ++ lpmd_log_debug("PERF_MODE to RESP_MODE\n"); ++ prep_state_change(PERF_MODE, RESP_MODE, 0); ++ break; ++ } ++ // Promote -- to moderate (3) MT state ++ if (!burst_rate_breach() && ++ A_LTE_B(grp.c0_max, UTIL_LOW)) { // && A_LTE_B(sum_avg, UTIL_BELOW_HALF)) ++ set_stay_count(MDRT3E_MODE, 0); ++ lpmd_log_debug("PERF_MODE to MDRT3E_MODE\n"); ++ prep_state_change(PERF_MODE, MDRT3E_MODE, 0); ++ break; ++ } ++ //Stay -- all else ++ break; + +- case RESP_MODE: +- // Demote -- if ST above halfway mark and avg trending higher +- if (A_GT_B(grp.c0_max, UTIL_ABOVE_HALF) +- && A_GT_B(grp.sma_avg1, UTIL_BELOW_HALF)) { +- lpmd_log_debug("RESP_MODE to PERF_MODE\n"); +- prep_state_change(RESP_MODE, PERF_MODE, 0); +- break; +- } +- // Stay -- if there were recent burst of spikes +- if (perf_count && burst_rate_breach()) +- break; ++ case RESP_MODE: ++ // Demote -- if ST above halfway mark and avg trending higher ++ if (A_GT_B(grp.c0_max, UTIL_ABOVE_HALF) && ++ A_GT_B(grp.sma_avg1, UTIL_BELOW_HALF)) { ++ lpmd_log_debug("RESP_MODE to PERF_MODE\n"); ++ prep_state_change(RESP_MODE, PERF_MODE, 0); ++ break; ++ } ++ // Stay -- if there were recent burst of spikes ++ if (perf_count && burst_rate_breach()) ++ break; + +- // Promote -- all else +- if (A_LTE_B(grp.worst_stall * 100, STALL_SCALE_LOWER_MARK)) { +- lpmd_log_debug("worst stall is less than STALL_SCALE_LOWER_MARK -- stay here.\n"); +- } else { +- lpmd_log_debug("RESP_MODE to MDRT3E_MODE\n"); +- prep_state_change(RESP_MODE, MDRT3E_MODE, 0); +- } +- break; ++ // Promote -- all else ++ if (A_LTE_B(grp.worst_stall * 100, STALL_SCALE_LOWER_MARK)) { ++ lpmd_log_debug("worst stall is less than STALL_SCALE_LOWER_MARK -- stay here.\n"); ++ } else { ++ lpmd_log_debug("RESP_MODE to MDRT3E_MODE\n"); ++ prep_state_change(RESP_MODE, MDRT3E_MODE, 0); ++ } ++ break; + +- case MDRT4E_MODE: +- if (A_LTE_B(grp.worst_stall * 100, STALL_SCALE_LOWER_MARK)) { +- lpmd_log_debug("MDRT4E_MODE to RESP_MODE\n"); +- prep_state_change(MDRT4E_MODE, RESP_MODE, 0); +- break; +- } +- // Demote +- if (A_GT_B(grp.c0_max, UTIL_NEAR_FULL)) { +- if (!burst_rate_breach() && strikeout_once(N_STRIKE)) +- break; +- lpmd_log_debug("MDRT4E_MODE to PERF_MODE\n"); +- prep_state_change(MDRT4E_MODE, PERF_MODE, 0); +- break; +- } +- // promote +- if (A_LTE_B(grp.sma_avg1, SUS_LOW_RANGE_END) && +- A_LTE_B(grp.sma_avg2, SUS_LOW_RANGE_END) && +- A_LTE_B(sum_c0, UTIL_HALF)) { +- if (!do_countdown(MDRT4E_MODE)) +- break; +- lpmd_log_debug("MDRT4E_MODE to NORM_MODE\n"); +- prep_state_change(MDRT4E_MODE, NORM_MODE, 0); +- break; +- } +- // stay +- break; ++ case MDRT4E_MODE: ++ if (A_LTE_B(grp.worst_stall * 100, STALL_SCALE_LOWER_MARK)) { ++ lpmd_log_debug("MDRT4E_MODE to RESP_MODE\n"); ++ prep_state_change(MDRT4E_MODE, RESP_MODE, 0); ++ break; ++ } ++ // Demote ++ if (A_GT_B(grp.c0_max, UTIL_NEAR_FULL)) { ++ if (!burst_rate_breach() && strikeout_once(N_STRIKE)) ++ break; ++ lpmd_log_debug("MDRT4E_MODE to PERF_MODE\n"); ++ prep_state_change(MDRT4E_MODE, PERF_MODE, 0); ++ break; ++ } ++ // promote ++ if (A_LTE_B(grp.sma_avg1, SUS_LOW_RANGE_END) && ++ A_LTE_B(grp.sma_avg2, SUS_LOW_RANGE_END) && ++ A_LTE_B(sum_c0, UTIL_HALF)) { ++ if (!do_countdown(MDRT4E_MODE)) ++ break; ++ lpmd_log_debug("MDRT4E_MODE to NORM_MODE\n"); ++ prep_state_change(MDRT4E_MODE, NORM_MODE, 0); ++ break; ++ } ++ // stay ++ break; + +- case MDRT3E_MODE: +- // Demote -- if mem bound work is stalling but didn't show higher utilization +- if (A_LTE_B(grp.worst_stall * 100, STALL_SCALE_LOWER_MARK)) { +- lpmd_log_debug("MDRT3E_MODE to RESP_MODE %.2f < %d\n", grp.worst_stall, STALL_SCALE_LOWER_MARK); +- prep_state_change(MDRT3E_MODE, RESP_MODE, 0); +- break; +- } +- // Demote to perf +- if (A_GT_B(grp.c0_max, UTIL_NEAR_FULL)) { +- if (!burst_rate_breach() && strikeout_once(N_STRIKE)) { +- lpmd_log_debug("MDRT3E_MODE: burst_rate_breach AND strikeout_once - not met\n"); +- break; +- } +- lpmd_log_debug("MDRT3E_MODE to PERF_MODE\n"); +- prep_state_change(MDRT3E_MODE, PERF_MODE, 0); +- break; +- } ++ case MDRT3E_MODE: ++ // Demote -- if mem bound work is stalling but didn't show higher utilization ++ if (A_LTE_B(grp.worst_stall * 100, STALL_SCALE_LOWER_MARK)) { ++ lpmd_log_debug("MDRT3E_MODE to RESP_MODE %.2f < %d\n", ++ grp.worst_stall, STALL_SCALE_LOWER_MARK); ++ prep_state_change(MDRT3E_MODE, RESP_MODE, 0); ++ break; ++ } ++ // Demote to perf ++ if (A_GT_B(grp.c0_max, UTIL_NEAR_FULL)) { ++ if (!burst_rate_breach() && strikeout_once(N_STRIKE)) { ++ lpmd_log_debug("MDRT3E_MODE: burst_rate_breach AND strikeout_once - not met\n"); ++ break; ++ } ++ lpmd_log_debug("MDRT3E_MODE to PERF_MODE\n"); ++ prep_state_change(MDRT3E_MODE, PERF_MODE, 0); ++ break; ++ } + +- // Demote to 4 thread sustained +- if (A_GTE_B(grp.sma_avg1, SUS_LOW_RANGE_END) && +- A_GTE_B(grp.sma_avg2, (SUS_LOW_RANGE_END - 5))) { +- lpmd_log_debug("MDRT3E_MODE to MDRT4E_MODE %d > %d\n", grp.sma_avg1, SUS_LOW_RANGE_END); +- prep_state_change(MDRT3E_MODE, MDRT4E_MODE, 0); +- break; +- } +- // promote +- if ((A_GT_B(grp.sma_avg1, SUS_LOW_RANGE_START) && +- A_LTE_B(grp.sma_avg1, SUS_LOW_RANGE_END)) && +- (A_GT_B(grp.sma_avg2, SUS_LOW_RANGE_START) && +- A_LTE_B(grp.sma_avg2, SUS_LOW_RANGE_END))) { +- if (!do_countdown(MDRT3E_MODE)) { +- lpmd_log_debug("MDRT3E_MODE: to MDRT2E_MODE - do countdown not met\n"); +- break; +- } +- lpmd_log_debug("MDRT3E_MODE to MDRT2E_MODE %d < %d\n", grp.sma_avg1, MDRT2E_MODE); +- prep_state_change(MDRT3E_MODE, MDRT2E_MODE, 0); +- break; +- } +- // Promote -- if top three avg util are trending lower. +- if (A_LTE_B(grp.sma_avg1, SUS_LOW_RANGE_END) && +- (A_LTE_B(grp.sma_avg2, SUS_LOWER) && +- A_LTE_B(grp.sma_avg3, SUS_LOWER))) { +- if (!do_countdown(MDRT3E_MODE)) { +- lpmd_log_debug("MDRT3E_MODE: to NORM_MODE - do countdown not met\n"); +- break; +- } +- lpmd_log_debug("MDRT3E_MODE to NORM_MODE\n"); +- prep_state_change(MDRT3E_MODE, NORM_MODE, 0); +- break; +- } ++ // Demote to 4 thread sustained ++ if (A_GTE_B(grp.sma_avg1, SUS_LOW_RANGE_END) && ++ A_GTE_B(grp.sma_avg2, (SUS_LOW_RANGE_END - 5))) { ++ lpmd_log_debug("MDRT3E_MODE to MDRT4E_MODE %d > %d\n", ++ grp.sma_avg1, SUS_LOW_RANGE_END); ++ prep_state_change(MDRT3E_MODE, MDRT4E_MODE, 0); ++ break; ++ } ++ // promote ++ if ((A_GT_B(grp.sma_avg1, SUS_LOW_RANGE_START) && ++ A_LTE_B(grp.sma_avg1, SUS_LOW_RANGE_END)) && ++ (A_GT_B(grp.sma_avg2, SUS_LOW_RANGE_START) && ++ A_LTE_B(grp.sma_avg2, SUS_LOW_RANGE_END))) { ++ if (!do_countdown(MDRT3E_MODE)) { ++ lpmd_log_debug("MDRT3E_MODE: to MDRT2E_MODE - do countdown not met\n"); ++ break; ++ } ++ lpmd_log_debug("MDRT3E_MODE to MDRT2E_MODE %d < %d\n", ++ grp.sma_avg1, MDRT2E_MODE); ++ prep_state_change(MDRT3E_MODE, MDRT2E_MODE, 0); ++ break; ++ } ++ // Promote -- if top three avg util are trending lower. ++ if (A_LTE_B(grp.sma_avg1, SUS_LOW_RANGE_END) && ++ (A_LTE_B(grp.sma_avg2, SUS_LOWER) && ++ A_LTE_B(grp.sma_avg3, SUS_LOWER))) { ++ if (!do_countdown(MDRT3E_MODE)) { ++ lpmd_log_debug("MDRT3E_MODE: to NORM_MODE - do countdown not met\n"); ++ break; ++ } ++ lpmd_log_debug("MDRT3E_MODE to NORM_MODE\n"); ++ prep_state_change(MDRT3E_MODE, NORM_MODE, 0); ++ break; ++ } + +- lpmd_log_debug("MDRT3E_MODE: stay\n"); +- break; ++ lpmd_log_debug("MDRT3E_MODE: stay\n"); ++ break; + +- case MDRT2E_MODE: +- // Demote -- if mem bound work is stalling but didn't show higher utilization +- if (A_LTE_B(grp.worst_stall * 100, STALL_SCALE_LOWER_MARK)) { +- lpmd_log_debug("MDRT2E_MODE to RESP_MODE\n"); +- prep_state_change(MDRT2E_MODE, RESP_MODE, 0); +- break; +- } +- // Demote -- if instant util nearing full or sustained moderate avg1 trend with avg2 trailing closeby +- if (A_GT_B(grp.c0_max, UTIL_NEAR_FULL) || +- (A_GTE_B(grp.sma_avg1, SUS_LOW_RANGE_END) && +- A_GTE_B(grp.sma_avg2, SUS_LOW_RANGE_END - 10))) { +- if (!burst_rate_breach() && strikeout_once(N_STRIKE)) +- break; +- lpmd_log_debug("MDRT2E_MODE to MDRT3E_MODE\n"); +- prep_state_change(MDRT2E_MODE, MDRT3E_MODE, 0); +- break; +- } +- // Promote -- if top two avg util are trending lower. +- if ((A_GT_B(grp.sma_avg1, SUS_LOW_RANGE_START) +- && A_LTE_B(grp.sma_avg1, SUS_LOW_RANGE_END)) +- && A_LTE_B(grp.sma_avg2, SUS_LOW_RANGE_END)) { +- if (!do_countdown(MDRT2E_MODE)) { +- break; +- } +- lpmd_log_debug("MDRT2E_MODE to NORM_MODE\n"); +- prep_state_change(MDRT2E_MODE, NORM_MODE, 0); +- break; +- } +- // stay +- break; ++ case MDRT2E_MODE: ++ // Demote -- if mem bound work is stalling but didn't show higher utilization ++ if (A_LTE_B(grp.worst_stall * 100, STALL_SCALE_LOWER_MARK)) { ++ lpmd_log_debug("MDRT2E_MODE to RESP_MODE\n"); ++ prep_state_change(MDRT2E_MODE, RESP_MODE, 0); ++ break; ++ } ++ // Demote -- if instant util nearing full or sustained moderate avg1 trend with avg2 trailing closeby ++ if (A_GT_B(grp.c0_max, UTIL_NEAR_FULL) || ++ (A_GTE_B(grp.sma_avg1, SUS_LOW_RANGE_END) && ++ A_GTE_B(grp.sma_avg2, SUS_LOW_RANGE_END - 10))) { ++ if (!burst_rate_breach() && strikeout_once(N_STRIKE)) ++ break; ++ lpmd_log_debug("MDRT2E_MODE to MDRT3E_MODE\n"); ++ prep_state_change(MDRT2E_MODE, MDRT3E_MODE, 0); ++ break; ++ } ++ // Promote -- if top two avg util are trending lower. ++ if ((A_GT_B(grp.sma_avg1, SUS_LOW_RANGE_START) && ++ A_LTE_B(grp.sma_avg1, SUS_LOW_RANGE_END)) && ++ A_LTE_B(grp.sma_avg2, SUS_LOW_RANGE_END)) { ++ if (!do_countdown(MDRT2E_MODE)) ++ break; ++ lpmd_log_debug("MDRT2E_MODE to NORM_MODE\n"); ++ prep_state_change(MDRT2E_MODE, NORM_MODE, 0); ++ break; ++ } ++ // stay ++ break; + +- case NORM_MODE: +- // Demote -- if mem bound work is stalling but didn't show higher utilization +- if (A_LTE_B(grp.worst_stall * 100, STALL_SCALE_LOWER_MARK)) { +- lpmd_log_debug("NORM_MODE to RESP_MODE\n"); +- prep_state_change(NORM_MODE, RESP_MODE, 0); +- break; +- } +- // Demote -- if instant util more than half or if signs of sustained ST activity. +- if (A_GT_B(grp.c0_max, UTIL_HALF) +- || (A_GT_B(grp.sma_avg1, UTIL_BELOW_HALF))) { +- /* In this state its better to absorb few spike (noise) before reacting */ +- if (!burst_rate_breach() && strikeout_once(N_STRIKE)) +- break; +- lpmd_log_debug("NORM_MODE to MDRT2E_MODE\n"); +- prep_state_change(NORM_MODE, MDRT2E_MODE, 0); +- break; +- } +- // Promote -- if top few instant util or top avg is trending lower. +- if ((A_LTE_B(grp.c0_max, UTIL_LOW) +- && A_LTE_B(grp.c0_2nd_max, UTIL_LOWEST)) +- || A_LTE_B(grp.sma_avg1, SUS_LOWER)) { +- /* its better to absorb few dips before reacting out of a steady-state */ +- if (!do_countdown(NORM_MODE)) +- break; +- lpmd_log_debug("NORM_MODE to DEEP_MODE\n"); +- prep_state_change(NORM_MODE, DEEP_MODE, 0); +- break; +- } +- break; ++ case NORM_MODE: ++ // Demote -- if mem bound work is stalling but didn't show higher utilization ++ if (A_LTE_B(grp.worst_stall * 100, STALL_SCALE_LOWER_MARK)) { ++ lpmd_log_debug("NORM_MODE to RESP_MODE\n"); ++ prep_state_change(NORM_MODE, RESP_MODE, 0); ++ break; ++ } ++ // Demote -- if instant util more than half or if signs of sustained ST activity. ++ if (A_GT_B(grp.c0_max, UTIL_HALF) || ++ (A_GT_B(grp.sma_avg1, UTIL_BELOW_HALF))) { ++ /* In this state its better to absorb few spike (noise) before reacting */ ++ if (!burst_rate_breach() && strikeout_once(N_STRIKE)) ++ break; ++ lpmd_log_debug("NORM_MODE to MDRT2E_MODE\n"); ++ prep_state_change(NORM_MODE, MDRT2E_MODE, 0); ++ break; ++ } ++ // Promote -- if top few instant util or top avg is trending lower. ++ if ((A_LTE_B(grp.c0_max, UTIL_LOW) && ++ A_LTE_B(grp.c0_2nd_max, UTIL_LOWEST)) || ++ A_LTE_B(grp.sma_avg1, SUS_LOWER)) { ++ /* its better to absorb few dips before reacting out of a steady-state */ ++ if (!do_countdown(NORM_MODE)) ++ break; ++ lpmd_log_debug("NORM_MODE to DEEP_MODE\n"); ++ prep_state_change(NORM_MODE, DEEP_MODE, 0); ++ break; ++ } ++ break; + +- case DEEP_MODE: +- // Demote -- if mem bound work is stalling but didn't show higher util. +- if (A_LTE_B(grp.worst_stall * 100, STALL_SCALE_LOWER_MARK)) { +- lpmd_log_debug("DEEP_MODE to RESP_MODE\n"); +- prep_state_change(DEEP_MODE, RESP_MODE, 0); +- break; +- } +- // Demote -- if there are early signs of instantaneous utilization build-up. +- if (A_GT_B(grp.c0_max, UTIL_FILL_START)) { +- lpmd_log_debug("DEEP_MODE to NORM_MODE\n"); +- prep_state_change(DEEP_MODE, NORM_MODE, 0); +- break; +- } ++ case DEEP_MODE: ++ // Demote -- if mem bound work is stalling but didn't show higher util. ++ if (A_LTE_B(grp.worst_stall * 100, STALL_SCALE_LOWER_MARK)) { ++ lpmd_log_debug("DEEP_MODE to RESP_MODE\n"); ++ prep_state_change(DEEP_MODE, RESP_MODE, 0); ++ break; ++ } ++ // Demote -- if there are early signs of instantaneous utilization build-up. ++ if (A_GT_B(grp.c0_max, UTIL_FILL_START)) { ++ lpmd_log_debug("DEEP_MODE to NORM_MODE\n"); ++ prep_state_change(DEEP_MODE, NORM_MODE, 0); ++ break; ++ } + +- break; +- } ++ break; ++ } + +- return 1; ++ return 1; + } +diff --git a/src/wlt_proxy/state_manager.c b/src/wlt_proxy/state_manager.c +index 9753442..72b29cb 100644 +--- a/src/wlt_proxy/state_manager.c ++++ b/src/wlt_proxy/state_manager.c +@@ -1,24 +1,6 @@ +-/* +- * state_manager.c: Intel Linux Energy Optimizer WLT proxy detection state manager +- * +- * Copyright (C) 2024 Intel Corporation. All rights reserved. +- * +- * This program is free software; you can redistribute it and/or modify +- * it under the terms of the GNU General Public License as published by +- * the Free Software Foundation; either version 2 of the License, or +- * (at your option) any later version. +- * +- * This program is distributed in the hope that it will be useful, +- * but WITHOUT ANY WARRANTY; without even the implied warranty of +- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +- * GNU General Public License for more details. +- * +- * You should have received a copy of the GNU General Public License +- * along with this program; if not, write to the Free Software +- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +- * +- * This file contains the proxy workload type detection - state definition, initialization and set/get functions. +- */ ++// SPDX-License-Identifier: GPL-2.0-or-later ++/* Copyright (C) 2026 Intel Corporation */ ++ + #define _GNU_SOURCE + #include + +@@ -27,11 +9,11 @@ + #include "wlt_proxy.h" //set_workload_hint + + #ifdef __GNUC__ +-#define likely(x) __builtin_expect(!!(x), 1) +-#define unlikely(x) __builtin_expect(!!(x), 0) ++#define likely(x) __builtin_expect(!!(x), 1) ++#define unlikely(x) __builtin_expect(!!(x), 0) + #else +-#define likely(x) (x) +-#define unlikely(x) (x) ++#define likely(x) (x) ++#define unlikely(x) (x) + #endif + + /* +@@ -40,271 +22,282 @@ + * avoid unexpected decision due to this as it may not be tied to workload per-se. + * any setting below, say 100ms, needs careful assessment. + */ +-#define MIN_POLL_PERIOD 100 ++#define MIN_POLL_PERIOD 100 + +-#define BASE_POLL_RESP 96 +-#define BASE_POLL_MT 100 +-#define BASE_POLL_PERF 280 +-#define BASE_POLL_MDRT4E 600 // e.g., 4E cores of a module +-#define BASE_POLL_MDRT3E 800 // e.g., 3E cores of a module +-#define BASE_POLL_MDRT2E 1000 // e.g., 2E cores of a module +-#define BASE_POLL_NORM 1200 +-#define BASE_POLL_DEEP 1800 ++#define BASE_POLL_RESP 96 ++#define BASE_POLL_MT 100 ++#define BASE_POLL_PERF 280 ++#define BASE_POLL_MDRT4E 600 // e.g., 4E cores of a module ++#define BASE_POLL_MDRT3E 800 // e.g., 3E cores of a module ++#define BASE_POLL_MDRT2E 1000 // e.g., 2E cores of a module ++#define BASE_POLL_NORM 1200 ++#define BASE_POLL_DEEP 1800 + + /* hold period (ms) before moving to deeper state */ +-#define MDRT_MODE_STAY (4000) +-#define PERF_MODE_STAY (10000) ++#define MDRT_MODE_STAY (4000) ++#define PERF_MODE_STAY (10000) + + /* poll interval type */ + enum elastic_poll { +- ZEROTH, +- LINEAR, +- QUADRATIC, +- CUBIC, ++ ZEROTH, ++ LINEAR, ++ QUADRATIC, ++ CUBIC, + }; + + /* state properties */ +-struct _stState { +- bool disabled; +- char *name; +- char *str; +- char *str_reverse; +- char *hexstr; +- char *hexstr_reverse; +- int poll; +- enum elastic_poll poll_order; +- int stay_count; +- int stay_count_update_sec; +- int stay_count_update_sec_prev; +- int spike_type; +- float stay_scalar; +- int ppw_enabled; +- int last_max_util; +- int last_poll; ++struct st_state { ++ bool disabled; ++ char *name; ++ char *str; ++ char *str_reverse; ++ char *hexstr; ++ char *hexstr_reverse; ++ int poll; ++ enum elastic_poll poll_order; ++ int stay_count; ++ int stay_count_update_sec; ++ int stay_count_update_sec_prev; ++ int spike_type; ++ float stay_scalar; ++ int ppw_enabled; ++ int last_max_util; ++ int last_poll; + }; + +-static struct _stState state_info[MAX_MODE] = { +- [INIT_MODE] = {.name = "Avail cpu: P/E/L",.poll = BASE_POLL_MT,.poll_order = ZEROTH}, +- [PERF_MODE] = {.name = "Perf:non-soc cpu",.poll = BASE_POLL_PERF,.poll_order = ZEROTH}, +- [MDRT2E_MODE] = {.name = "Moderate 2E",.poll = BASE_POLL_MDRT2E,.poll_order = LINEAR}, +- [MDRT3E_MODE] = {.name = "Moderate 3E",.poll = BASE_POLL_MDRT3E,.poll_order = LINEAR}, +- [MDRT4E_MODE] = {.name = "Moderate 4E",.poll = BASE_POLL_MDRT4E, .poll_order = LINEAR}, +- [RESP_MODE] = {.name = "Responsive 2L",.poll = BASE_POLL_RESP, .poll_order = CUBIC}, +- [NORM_MODE] = {.name = "Normal LP 2L",.poll = BASE_POLL_NORM, .poll_order = QUADRATIC}, +- [DEEP_MODE] = {.name = "Deep LP 1L",.poll = BASE_POLL_DEEP, .poll_order = CUBIC}, ++static struct st_state state_info[MAX_MODE] = { ++ [INIT_MODE] = { .name = "Avail cpu: P/E/L", ++ .poll = BASE_POLL_MT, ++ .poll_order = ZEROTH }, ++ [PERF_MODE] = { .name = "Perf:non-soc cpu", ++ .poll = BASE_POLL_PERF, ++ .poll_order = ZEROTH }, ++ [MDRT2E_MODE] = { .name = "Moderate 2E", ++ .poll = BASE_POLL_MDRT2E, ++ .poll_order = LINEAR }, ++ [MDRT3E_MODE] = { .name = "Moderate 3E", ++ .poll = BASE_POLL_MDRT3E, ++ .poll_order = LINEAR }, ++ [MDRT4E_MODE] = { .name = "Moderate 4E", ++ .poll = BASE_POLL_MDRT4E, ++ .poll_order = LINEAR }, ++ [RESP_MODE] = { .name = "Responsive 2L", ++ .poll = BASE_POLL_RESP, ++ .poll_order = CUBIC }, ++ [NORM_MODE] = { .name = "Normal LP 2L", ++ .poll = BASE_POLL_NORM, ++ .poll_order = QUADRATIC }, ++ [DEEP_MODE] = { .name = "Deep LP 1L", ++ .poll = BASE_POLL_DEEP, ++ .poll_order = CUBIC }, + }; + + static enum state_idx cur_state = NORM_MODE; + static int needs_state_reset = 1; +-extern int wlt_type; + +-int state_demote = 0; +-extern int next_proxy_poll; +-extern int max_util; ++int state_demote; + + static void set_state_reset(void) + { +- needs_state_reset = 1; ++ needs_state_reset = 1; + } + + enum state_idx get_cur_state(void) + { +- return cur_state; ++ return cur_state; + } + + static void set_cur_state(enum state_idx state) + { +- cur_state = state; ++ cur_state = state; + } + + static int is_state_valid(enum state_idx state) + { +- return ((state >= INIT_MODE) && (state < MAX_MODE) +- && !state_info[state].disabled); ++ return ((state >= INIT_MODE) && (state < MAX_MODE) && ++ !state_info[state].disabled); + } + + int get_poll_ms(enum state_idx state) + { +- return state_info[state].poll; ++ return state_info[state].poll; + } + + int get_stay_count(enum state_idx state) + { +- return (state_info[state].stay_count); ++ return state_info[state].stay_count; + } + + int set_stay_count(enum state_idx state, int count) + { +- return (state_info[state].stay_count = count); ++ return (state_info[state].stay_count = count); + } + + /* return 1 if stay count reaches 0 */ + int do_countdown(enum state_idx state) + { +- state_info[state].stay_count -= 1; ++ state_info[state].stay_count -= 1; + +- if (state_info[state].stay_count <= 0) { +- state_info[state].stay_count = 0; +- return 1; +- } ++ if (state_info[state].stay_count <= 0) { ++ state_info[state].stay_count = 0; ++ return 1; ++ } + +- return 0; ++ return 0; + } + + /* get poll value in microsec */ + int get_state_poll(int util, enum state_idx state) + { +- int poll, scale = (100 - util); +- float scale2; +- int order = (int)state_info[state].poll_order; +- +- /* avoiding fpow() overhead */ +- switch (order) { +- case ZEROTH: +- scale2 = (float)1; +- break; +- case LINEAR: +- scale2 = (float)scale / 100; +- break; +- case QUADRATIC: +- scale2 = (float)scale *scale / 10000; +- break; +- case CUBIC: +- scale2 = (float)scale *scale * scale / 1000000; +- break; +- default: +- scale2 = (float)scale / 100; +- break; +- } +- +- poll = (int)(state_info[cur_state].poll * scale2); +- +- /* limiting min poll to MIN_POLL_PERIOD ms */ +- if (poll < MIN_POLL_PERIOD) +- return MIN_POLL_PERIOD; +- +- return poll; ++ int poll, scale = (100 - util); ++ float scale2; ++ int order = (int)state_info[state].poll_order; ++ ++ /* avoiding fpow() overhead */ ++ switch (order) { ++ case ZEROTH: ++ scale2 = (float)1; ++ break; ++ case LINEAR: ++ scale2 = (float)scale / 100; ++ break; ++ case QUADRATIC: ++ scale2 = (float)scale * scale / 10000; ++ break; ++ case CUBIC: ++ scale2 = (float)scale * scale * scale / 1000000; ++ break; ++ default: ++ scale2 = (float)scale / 100; ++ break; ++ } ++ ++ poll = (int)(state_info[cur_state].poll * scale2); ++ ++ /* limiting min poll to MIN_POLL_PERIOD ms */ ++ if (poll < MIN_POLL_PERIOD) ++ return MIN_POLL_PERIOD; ++ ++ return poll; + } + + int get_last_maxutil(void) + { +- return state_info[cur_state].last_max_util; ++ return state_info[cur_state].last_max_util; + } + + static int set_last_maxutil(int v) + { +- state_info[cur_state].last_max_util = v; +- return 1; ++ state_info[cur_state].last_max_util = v; ++ return 1; + } + + int set_last_poll(int v) + { +- state_info[cur_state].last_poll = v; +- return 1; ++ state_info[cur_state].last_poll = v; ++ return 1; + } + + int get_last_poll(void) + { +- return state_info[cur_state].last_poll; ++ return state_info[cur_state].last_poll; + } + + /* initiate state change */ + static int apply_state_change(void) + { +- float test; ++ float test; + +- if (!needs_state_reset) { +- return 0; +- } ++ if (!needs_state_reset) ++ return 0; + +- update_perf_diffs(&test, 1); +- needs_state_reset = 0; ++ update_perf_diffs(&test, 1); ++ needs_state_reset = 0; + +- return 1; ++ return 1; + } + + /* Internal state to WLT mapping*/ +-static int get_state_mapping(enum state_idx state){ +- +- switch(state) { +- case PERF_MODE: +- return WLT_BURSTY; ++static int get_state_mapping(enum state_idx state) ++{ ++ switch (state) { ++ case PERF_MODE: ++ return WLT_BURSTY; + +- case RESP_MODE: +- case NORM_MODE: +- return WLT_BATTERY_LIFE; ++ case RESP_MODE: ++ case NORM_MODE: ++ return WLT_BATTERY_LIFE; + +- case DEEP_MODE: +- return WLT_IDLE; ++ case DEEP_MODE: ++ return WLT_IDLE; + +- case INIT_MODE: +- case MDRT4E_MODE: +- case MDRT3E_MODE: +- case MDRT2E_MODE: +- return WLT_SUSTAINED; ++ case INIT_MODE: ++ case MDRT4E_MODE: ++ case MDRT3E_MODE: ++ case MDRT2E_MODE: ++ return WLT_SUSTAINED; + +- default: +- return WLT_IDLE; +- } ++ default: ++ return WLT_IDLE; ++ } + } + + /* prepare for state change */ + int prep_state_change(enum state_idx from_state, enum state_idx to_state, +- int reset) ++ int reset) + { +- set_cur_state(to_state); +- set_state_reset(); +- set_last_maxutil(DEACTIVATED); ++ set_cur_state(to_state); ++ set_state_reset(); ++ set_last_maxutil(DEACTIVATED); + +- if (to_state < from_state) +- state_demote = 1; ++ if (to_state < from_state) ++ state_demote = 1; + +- //proxy: apply state change and get poll interval +- apply_state_change(); ++ //proxy: apply state change and get poll interval ++ apply_state_change(); + +- if (likely(is_state_valid(to_state))) { +- next_proxy_poll = get_state_poll(max_util, to_state); +- } ++ if (likely(is_state_valid(to_state))) ++ next_proxy_poll = get_state_poll(max_util, to_state); + +- wlt_type = get_state_mapping(to_state); ++ wlt_type = get_state_mapping(to_state); + +- return 1; ++ return 1; + } + + /* return staycount for the state */ + int staytime_to_staycount(enum state_idx state) + { +- int stay_count = 0; +- +- switch (state) { +- case MDRT2E_MODE: +- case MDRT3E_MODE: +- case MDRT4E_MODE: +- stay_count = (int)MDRT_MODE_STAY/get_poll_ms(MDRT3E_MODE); +- break; +- case PERF_MODE: +- stay_count = (int)PERF_MODE_STAY/get_poll_ms(PERF_MODE); +- break; ++ int stay_count = 0; ++ ++ switch (state) { ++ case MDRT2E_MODE: ++ case MDRT3E_MODE: ++ case MDRT4E_MODE: ++ stay_count = (int)MDRT_MODE_STAY / get_poll_ms(MDRT3E_MODE); ++ break; ++ case PERF_MODE: ++ stay_count = (int)PERF_MODE_STAY / get_poll_ms(PERF_MODE); ++ break; + default: +- break; +- } +- return stay_count; ++ break; ++ } ++ return stay_count; + } + + /* cleanup */ +-void uninit_state_manager() { +- +- for (int idx = INIT_MODE; idx < MAX_MODE; idx++) { +- if(state_info[idx].str != NULL) +- free(state_info[idx].str); ++void uninit_state_manager(void) ++{ ++ for (int idx = INIT_MODE; idx < MAX_MODE; idx++) { ++ if (state_info[idx].str) ++ free(state_info[idx].str); + +- if(state_info[idx].str_reverse != NULL) +- free(state_info[idx].str_reverse); ++ if (state_info[idx].str_reverse) ++ free(state_info[idx].str_reverse); + +- if(state_info[idx].hexstr != NULL) +- free(state_info[idx].hexstr); ++ if (state_info[idx].hexstr) ++ free(state_info[idx].hexstr); + +- if(state_info[idx].hexstr_reverse != NULL) +- free(state_info[idx].hexstr_reverse); +- } ++ if (state_info[idx].hexstr_reverse) ++ free(state_info[idx].hexstr_reverse); ++ } + } +diff --git a/src/wlt_proxy/state_util.c b/src/wlt_proxy/state_util.c +index d937d5f..23fa1d2 100644 +--- a/src/wlt_proxy/state_util.c ++++ b/src/wlt_proxy/state_util.c +@@ -1,24 +1,6 @@ +-/* +- * state_util.c: Intel Linux Energy Optimizer WLT calculations +- * +- * Copyright (C) 2024 Intel Corporation. All rights reserved. +- * +- * This program is free software; you can redistribute it and/or modify +- * it under the terms of the GNU General Public License as published by +- * the Free Software Foundation; either version 2 of the License, or +- * (at your option) any later version. +- * +- * This program is distributed in the hope that it will be useful, +- * but WITHOUT ANY WARRANTY; without even the implied warranty of +- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +- * GNU General Public License for more details. +- * +- * You should have received a copy of the GNU General Public License +- * along with this program; if not, write to the Free Software +- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +- * +- * This file contains the proxy workload type detection data collection and calculations [perf, sma]. +- */ ++// SPDX-License-Identifier: GPL-2.0-or-later ++/* Copyright (C) 2026 Intel Corporation */ ++ + + #include //perf_event_attr + #include //syscall __NR_perf_event_open +@@ -31,59 +13,57 @@ + + /* + * simple moving average (sma), event count based - not time. +- * updated for upto top 3 max util streams. ++ * updated for up to top 3 max util streams. + * exact cpu # is not tracked; only the max since continuum of task + * keeps switching cpus anyway. + * array implementation with SMA_LENGTH number of values. + */ +-#define SMA_LENGTH (25) +-#define SMA_CPU_COUNT (3) +-#define SCALE_DECIMAL (100) ++#define SMA_LENGTH (25) ++#define SMA_CPU_COUNT (3) ++#define SCALE_DECIMAL (100) + + static int sample[3][SMA_LENGTH]; + +-typedef struct { +- +- int cpu; +- +- enum core_type cpu_type; +- +- int aperf_fd; +- int mperf_fd; +- int pperf_fd; +- +- uint64_t aperf_diff; +- uint64_t mperf_diff; +- uint64_t pperf_diff; +- uint64_t tsc_diff; +- +- uint64_t nperf; +- /* +- * As initial freq f0 changes to some other value +- * in the next cycle, it influences the initial +- * load l0 and associated stall-factor (1-s0) +- * track them for perf-per-watt evaluation. +- */ +- float f0; +- float l0; +- float s0; +- +-} perf_stats_t; +- +-perf_stats_t *perf_stats; ++struct perf_stats_t { ++ int cpu; ++ ++ enum core_type cpu_type; ++ ++ int aperf_fd; ++ int mperf_fd; ++ int pperf_fd; ++ ++ uint64_t aperf_diff; ++ uint64_t mperf_diff; ++ uint64_t pperf_diff; ++ uint64_t tsc_diff; ++ ++ uint64_t nperf; ++ /* ++ * As initial freq f0 changes to some other value ++ * in the next cycle, it influences the initial ++ * load l0 and associated stall-factor (1-s0) ++ * track them for perf-per-watt evaluation. ++ */ ++ float f0; ++ float l0; ++ float s0; ++}; ++ ++struct perf_stats_t *perf_stats; + struct group_util grp; + + struct thread_data { +- unsigned long long tsc; +- unsigned long long aperf; +- unsigned long long mperf; +- unsigned long long pperf; ++ unsigned long long tsc; ++ unsigned long long aperf; ++ unsigned long long mperf; ++ unsigned long long pperf; + } *thread_even, *thread_odd; + +-static uint64_t *last_aperf = NULL; +-static uint64_t *last_mperf = NULL; +-static uint64_t *last_pperf = NULL; +-static uint64_t *last_tsc = NULL; ++static uint64_t *last_aperf; ++static uint64_t *last_mperf; ++static uint64_t *last_pperf; ++static uint64_t *last_tsc; + + /* + * Intel Alderlake hardware errata #ADL026: pperf bits 31:64 could be incorrect. +@@ -91,20 +71,20 @@ static uint64_t *last_tsc = NULL; + * forms/client/platforms/alder-lake-desktop/682436/007/errata-details/#ADL026 + * u644diff() implements a workaround. Assuming real diffs less than MAX(uint32) + */ +-#define u64diff(b, a) (((uint64_t)b < (uint64_t)a) ? \ +- (uint64_t)((uint32_t)~0UL - (uint32_t)a + (uint32_t)b) :\ +- ((uint64_t)b - (uint64_t)a)) ++#define u64diff(b, a) (((uint64_t)b < (uint64_t)a) ? \ ++ (uint64_t)((uint32_t)~0UL - (uint32_t)a + (uint32_t)b) : \ ++ ((uint64_t)b - (uint64_t)a)) + + /* routine to evaluate & store a per-cpu msr value's diff */ +-#define VARI(a, b, i) a##b[i] +-#define cpu_generate_msr_diff(scope) \ +-uint64_t cpu_get_diff_##scope(uint64_t cur_value, int instance)\ +-{ \ +- uint64_t diff; \ +- diff = (VARI(last_, scope, instance) == 0) ? \ +- 0 : u64diff(cur_value, VARI(last_, scope, instance)); \ +- VARI(last_, scope, instance) = cur_value; \ +- return diff; \ ++#define VARI(a, b, i) (a##b[i]) ++#define cpu_generate_msr_diff(scope) \ ++uint64_t cpu_get_diff_##scope(uint64_t cur_value, int instance) \ ++{ \ ++ uint64_t diff; \ ++ diff = (VARI(last_, scope, instance) == 0) ? \ ++ 0 : u64diff(cur_value, VARI(last_, scope, instance)); \ ++ VARI(last_, scope, instance) = cur_value; \ ++ return diff; \ + } + + /********************Perf calculation - begin *****************************************/ +@@ -115,465 +95,486 @@ cpu_generate_msr_diff(pperf); + cpu_generate_msr_diff(tsc); + + /* initialize perf_stat structure */ +-static int perf_stat_init(void) { +- +- int max_cpus = get_max_cpus(); +- +- perf_stats = NULL; +- perf_stats = calloc(sizeof(perf_stats_t), max_cpus); +- if ( !perf_stats ) { +- lpmd_log_error("WLT_Proxy: memory failure\n"); +- return 0; +- } +- +- for (int t = 0; t < max_cpus; t++) { +- if(!is_cpu_online(t)) { +- continue; +- } +- +- perf_stats[t].cpu = t; +- +- if (is_cpu_pcore(t)) { +- perf_stats[t].cpu_type = P_CORE; +- } else if (is_cpu_ecore(t)) { +- perf_stats[t].cpu_type = E_CORE; +- } else { +- perf_stats[t].cpu_type = L_CORE; +- } +- } +- +- return 1; ++static int perf_stat_init(void) ++{ ++ int max_cpus = get_max_cpus(); ++ ++ perf_stats = NULL; ++ perf_stats = calloc(max_cpus, sizeof(struct perf_stats_t)); ++ if (!perf_stats) { ++ lpmd_log_error("WLT_Proxy: memory failure\n"); ++ return 0; ++ } ++ ++ for (int t = 0; t < max_cpus; t++) { ++ if (!is_cpu_online(t)) ++ continue; ++ ++ perf_stats[t].cpu = t; ++ ++ if (is_cpu_pcore(t)) ++ perf_stats[t].cpu_type = P_CORE; ++ else if (is_cpu_ecore(t)) ++ perf_stats[t].cpu_type = E_CORE; ++ else ++ perf_stats[t].cpu_type = L_CORE; ++ } ++ ++ return 1; + } + + /* is cpu applicable for the given state*/ + static int cpu_applicable(int cpu, enum state_idx state) + { +- switch (state) { +- case INIT_MODE: +- //for INIT mode need all cores [P,E,L] +- return 1; +- case NORM_MODE: // 2 L cores +- case DEEP_MODE: // 1 L core +- case RESP_MODE: // all L core +- case MDRT2E_MODE: // 2 E cores +- case MDRT3E_MODE: // 3 E cores +- case MDRT4E_MODE: // 4 E cores +- case PERF_MODE: +- if (perf_stats[cpu].cpu_type != L_CORE) { +- return 1; +- } +- default: +- break; +- } +- +- return 0; ++ switch (state) { ++ case INIT_MODE: ++ //for INIT mode need all cores [P,E,L] ++ return 1; ++ case NORM_MODE: // 2 L cores ++ case DEEP_MODE: // 1 L core ++ case RESP_MODE: // all L core ++ case MDRT2E_MODE: // 2 E cores ++ case MDRT3E_MODE: // 3 E cores ++ case MDRT4E_MODE: // 4 E cores ++ case PERF_MODE: ++ if (perf_stats[cpu].cpu_type != L_CORE) ++ return 1; ++ default: ++ break; ++ } ++ ++ return 0; + } + + static int init_perf_calculations(int n) + { +- if (!perf_stat_init()) { +- lpmd_log_error("\nerror initiating cpu proxy\n"); +- return -1; +- } +- +- last_aperf = calloc(sizeof(uint64_t), n); +- last_mperf = calloc(sizeof(uint64_t), n); +- last_pperf = calloc(sizeof(uint64_t), n); +- last_tsc = calloc(sizeof(uint64_t), n); +- if (!last_aperf || !last_mperf || !last_mperf || !last_tsc) { +- lpmd_log_error("calloc failure perf vars\n"); +- return -2; +- } +- +- return LPMD_SUCCESS; ++ if (!perf_stat_init()) { ++ lpmd_log_error("\nerror initiating cpu proxy\n"); ++ return -1; ++ } ++ ++ last_aperf = calloc(n, sizeof(uint64_t)); ++ last_mperf = calloc(n, sizeof(uint64_t)); ++ last_pperf = calloc(n, sizeof(uint64_t)); ++ last_tsc = calloc(n, sizeof(uint64_t)); ++ if (!last_aperf || !last_mperf || !last_mperf || !last_tsc) { ++ lpmd_log_error("calloc failure perf vars\n"); ++ return -2; ++ } ++ ++ return LPMD_SUCCESS; + } + +-/*helper - pperf reading */ +-static int read_perf_counter_info(const char *const path, const char *const parse_format, void *value_ptr) { +- int fdmt; +- int bytes_read; +- char buf[64]; +- int ret = -1; +- +- fdmt = open(path, O_RDONLY, 0); +- if (fdmt == -1) { +- lpmd_log_error("Failed to parse perf counter info %s\n", path); +- ret = -1; +- goto cleanup_and_exit; +- } +- +- bytes_read = read(fdmt, buf, sizeof(buf) - 1); +- if (bytes_read <= 0 || bytes_read >= (int)sizeof(buf)) { +- lpmd_log_error("Failed to parse perf counter info %s\n", path); +- ret = -1; +- goto cleanup_and_exit; +- } +- +- buf[bytes_read] = '\0'; +- +- if (sscanf(buf, parse_format, value_ptr) != 1) { +- lpmd_log_error("Failed to parse perf counter info %s\n", path); +- ret = -1; +- goto cleanup_and_exit; +- } +- +- ret = 0; ++/* helper - pperf reading */ ++static int read_perf_counter_info(const char *const path, ++ const char *const parse_format, ++ void *value_ptr) ++{ ++ int fdmt; ++ int bytes_read; ++ char buf[64]; ++ int ret = -1; ++ ++ fdmt = open(path, O_RDONLY, 0); ++ if (fdmt == -1) { ++ lpmd_log_error("Failed to parse perf counter info %s\n", path); ++ ret = -1; ++ goto cleanup_and_exit; ++ } ++ ++ bytes_read = read(fdmt, buf, sizeof(buf) - 1); ++ if (bytes_read <= 0 || bytes_read >= (int)sizeof(buf)) { ++ lpmd_log_error("Failed to parse perf counter info %s\n", path); ++ ret = -1; ++ goto cleanup_and_exit; ++ } ++ ++ buf[bytes_read] = '\0'; ++ ++ if (sscanf(buf, parse_format, value_ptr) != 1) { ++ lpmd_log_error("Failed to parse perf counter info %s\n", path); ++ ret = -1; ++ goto cleanup_and_exit; ++ } ++ ++ ret = 0; + + cleanup_and_exit: +- if (fdmt >= 0) +- close(fdmt); ++ if (fdmt >= 0) ++ close(fdmt); + +- return ret; ++ return ret; + } + +-/*helper - pperf reading */ +-static unsigned int read_perf_counter_info_n(const char *const path, const char *const parse_format) { +- unsigned int v; +- int status; ++/* helper - pperf reading */ ++static unsigned int read_perf_counter_info_n(const char *const path, ++ const char *const parse_format) ++{ ++ unsigned int v; ++ int status; + +- status = read_perf_counter_info(path, parse_format, &v); +- if (status) +- v = -1; ++ status = read_perf_counter_info(path, parse_format, &v); ++ if (status) ++ v = -1; + +- return v; ++ return v; + } + +-/*helper - pperf reading */ +-static int read_pperf_config(void) { +- const char *const path = "/sys/bus/event_source/devices/msr/events/pperf"; +- const char *const format = "event=%x"; ++/* helper - pperf reading */ ++static int read_pperf_config(void) ++{ ++ const char *const path = "/sys/bus/event_source/devices/msr/events/pperf"; ++ const char *const format = "event=%x"; + +- return read_perf_counter_info_n(path, format); ++ return read_perf_counter_info_n(path, format); + } + +-/*helper - pperf reading */ +-static unsigned int read_aperf_config(void) { +- const char *const path = "/sys/bus/event_source/devices/msr/events/aperf"; +- const char *const format = "event=%x"; ++/* helper - pperf reading */ ++static unsigned int read_aperf_config(void) ++{ ++ const char *const path = "/sys/bus/event_source/devices/msr/events/aperf"; ++ const char *const format = "event=%x"; + +- return read_perf_counter_info_n(path, format); ++ return read_perf_counter_info_n(path, format); + } + +-/*helper - pperf reading */ +-static unsigned int read_mperf_config(void) { +- const char *const path = "/sys/bus/event_source/devices/msr/events/mperf"; +- const char *const format = "event=%x"; ++/* helper - pperf reading */ ++static unsigned int read_mperf_config(void) ++{ ++ const char *const path = "/sys/bus/event_source/devices/msr/events/mperf"; ++ const char *const format = "event=%x"; + +- return read_perf_counter_info_n(path, format); ++ return read_perf_counter_info_n(path, format); + } + +-/*helper - pperf reading */ +-static unsigned int read_msr_type(void) { +- const char *const path = "/sys/bus/event_source/devices/msr/type"; +- const char *const format = "%u"; ++/* helper - pperf reading */ ++static unsigned int read_msr_type(void) ++{ ++ const char *const path = "/sys/bus/event_source/devices/msr/type"; ++ const char *const format = "%u"; + +- return read_perf_counter_info_n(path, format); ++ return read_perf_counter_info_n(path, format); + } + +-/*helper - pperf reading */ +-static long perf_event_open(struct perf_event_attr *hw_event, pid_t pid, int cpu, int group_fd, unsigned long flags) { +- return syscall(__NR_perf_event_open, hw_event, pid, cpu, group_fd, flags); ++/* helper - pperf reading */ ++static long perf_event_open(struct perf_event_attr *hw_event, pid_t pid, ++ int cpu, int group_fd, unsigned long flags) ++{ ++ return syscall(__NR_perf_event_open, hw_event, pid, cpu, group_fd, flags); + } + +-/*helper - pperf reading */ +-static long open_perf_counter(int cpu, unsigned int type, unsigned int config, int group_fd, __u64 read_format) { +- struct perf_event_attr attr; +- const pid_t pid = -1; +- const unsigned long flags = 0; ++/* helper - pperf reading */ ++static long open_perf_counter(int cpu, unsigned int type, unsigned int config, ++ int group_fd, __u64 read_format) ++{ ++ struct perf_event_attr attr; ++ const pid_t pid = -1; ++ const unsigned long flags = 0; ++ ++ memset(&attr, 0, sizeof(struct perf_event_attr)); + +- memset(&attr, 0, sizeof(struct perf_event_attr)); ++ attr.type = type; ++ attr.size = sizeof(struct perf_event_attr); ++ attr.config = config; ++ attr.disabled = 0; ++ attr.sample_type = PERF_SAMPLE_IDENTIFIER; ++ attr.read_format = read_format; + +- attr.type = type; +- attr.size = sizeof(struct perf_event_attr); +- attr.config = config; +- attr.disabled = 0; +- attr.sample_type = PERF_SAMPLE_IDENTIFIER; +- attr.read_format = read_format; ++ const int fd = perf_event_open(&attr, pid, cpu, group_fd, flags); + +- const int fd = perf_event_open(&attr, pid, cpu, group_fd, flags); ++ return fd; ++} + +- return fd; ++/* helper - pperf reading */ ++static void open_amperf_fd(int cpu) ++{ ++ const unsigned int msr_type = read_msr_type(); ++ const unsigned int aperf_config = read_aperf_config(); ++ const unsigned int mperf_config = read_mperf_config(); ++ const unsigned int pperf_config = read_pperf_config(); ++ ++ perf_stats[cpu].aperf_fd = open_perf_counter(cpu, msr_type, aperf_config, -1, PERF_FORMAT_GROUP); ++ perf_stats[cpu].mperf_fd = open_perf_counter(cpu, msr_type, mperf_config, perf_stats[cpu].aperf_fd, PERF_FORMAT_GROUP); ++ perf_stats[cpu].pperf_fd = open_perf_counter(cpu, msr_type, pperf_config, perf_stats[cpu].aperf_fd, PERF_FORMAT_GROUP); + } + +-/*helper - pperf reading */ +-static void open_amperf_fd(int cpu) { +- const unsigned int msr_type = read_msr_type(); +- const unsigned int aperf_config = read_aperf_config(); +- const unsigned int mperf_config = read_mperf_config(); +- const unsigned int pperf_config = read_pperf_config(); ++/* helper - pperf reading */ ++static int get_amperf_fd(int cpu) ++{ ++ if (perf_stats[cpu].aperf_fd) ++ return perf_stats[cpu].aperf_fd; + +- perf_stats[cpu].aperf_fd = open_perf_counter(cpu, msr_type, aperf_config, -1, PERF_FORMAT_GROUP); +- perf_stats[cpu].mperf_fd = open_perf_counter(cpu, msr_type, mperf_config, perf_stats[cpu].aperf_fd, PERF_FORMAT_GROUP); +- perf_stats[cpu].pperf_fd = open_perf_counter(cpu, msr_type, pperf_config, perf_stats[cpu].aperf_fd, PERF_FORMAT_GROUP); ++ open_amperf_fd(cpu); + ++ return perf_stats[cpu].aperf_fd; + } + +-/*helper - pperf reading */ +-static int get_amperf_fd(int cpu) { +- if (perf_stats[cpu].aperf_fd) +- return perf_stats[cpu].aperf_fd; ++/* helper - pperf reading */ ++static unsigned long long rdtsc(void) ++{ ++ unsigned int low, high; + +- open_amperf_fd(cpu); ++ asm volatile ("rdtsc" : "=a" (low), "=d"(high)); + +- return perf_stats[cpu].aperf_fd; ++ return low | ((unsigned long long)high) << 32; + } + +-/*helper - pperf reading */ +-static unsigned long long rdtsc(void) { +- unsigned int low, high; ++/* ++ * Helper for - Reading APERF, MPERF and TSC using the perf API. ++ * Calc perf [cpu utilization per core] difference from MSR registers ++ */ ++static int read_aperf_mperf_tsc_perf(struct thread_data *t, int cpu) ++{ ++ union { ++ struct { ++ unsigned long nr_entries; ++ unsigned long aperf; ++ unsigned long mperf; ++ unsigned long pperf; ++ }; + +- asm volatile ("rdtsc":"=a" (low), "=d"(high)); ++ unsigned long as_array[4]; ++ } cnt; ++ const int fd_amperf = get_amperf_fd(cpu); + +- return low | ((unsigned long long)high) << 32; +-} ++ if (fd_amperf == -1) ++ return LPMD_ERROR; ++ ++ /* ++ * Read the TSC with rdtsc, because we want the absolute value and not ++ * the offset from the start of the counter. ++ */ ++ t->tsc = rdtsc(); ++ ++ const int n = read(fd_amperf, &cnt.as_array[0], sizeof(cnt.as_array)); + +-/* Helper for - Reading APERF, MPERF and TSC using the perf API. +- Calc perf [cpu utilization per core] difference from MSR registers */ +-static int read_aperf_mperf_tsc_perf(struct thread_data *t, int cpu) { +- union { +- struct { +- unsigned long nr_entries; +- unsigned long aperf; +- unsigned long mperf; +- unsigned long pperf; +- }; +- +- unsigned long as_array[4]; +- } cnt; +- +- const int fd_amperf = get_amperf_fd(cpu); +- if(fd_amperf == -1) { +- return LPMD_ERROR; +- } +- +- /* +- * Read the TSC with rdtsc, because we want the absolute value and not +- * the offset from the start of the counter. +- */ +- t->tsc = rdtsc(); +- +- const int n = read(fd_amperf, &cnt.as_array[0], sizeof(cnt.as_array)); +- +- if (n != sizeof(cnt.as_array)) +- return -2; +- +- t->aperf = cnt.aperf; +- t->mperf = cnt.mperf; +- t->pperf = cnt.pperf; +- +- return LPMD_SUCCESS; ++ if (n != sizeof(cnt.as_array)) ++ return -2; ++ ++ t->aperf = cnt.aperf; ++ t->mperf = cnt.mperf; ++ t->pperf = cnt.pperf; ++ ++ return LPMD_SUCCESS; + } + +-/*Calc perf [cpu utilization per core] difference from MSR registers */ +-int update_perf_diffs(float *sum_norm_perf, int stat_init_only) { +- +- int maxed_cpu = -1; +- float min_load = 100.0, min_s0 = 1.0, next_s0 = 1.0; +- float max_load = 0, max_2nd_load = 0, max_3rd_load = 0, next_load = 0; +- int t, min_s0_cpu = 0, first_pass = 1; +- +- for (t = 0; t < get_max_online_cpu(); t++) { +- if (!cpu_applicable(t, get_cur_state())) { +- continue; +- } +- +- /*reading through perf api*/ +- struct thread_data tdata; +- if(read_aperf_mperf_tsc_perf(&tdata , t) != LPMD_SUCCESS) { +- lpmd_log_error("read_aperf_mperf_tsc_perf failed for cpu = %d\n", t); +- continue; +- } +- perf_stats[t].pperf_diff = cpu_get_diff_pperf(tdata.pperf, t); +- perf_stats[t].aperf_diff = cpu_get_diff_aperf(tdata.aperf, t); +- perf_stats[t].mperf_diff = cpu_get_diff_mperf(tdata.mperf, t); +- perf_stats[t].tsc_diff = cpu_get_diff_tsc(tdata.tsc, t); +- +- if (stat_init_only) +- continue; +- +- /* +- * Normalized perf metric defined as pperf per load per time. +- * The rationale is detailed here: +- * github.com/intel/psst >whitepapers >Generic_perf_per_watt.pdf +- * Given that delta_load = delta_mperf/delta_tsc, we can rewrite +- * as given below. +- */ +- if (perf_stats[t].tsc_diff) { +- next_load = +- (float)100 *perf_stats[t].mperf_diff / +- perf_stats[t].tsc_diff; +- perf_stats[t].l0 = next_load; +- } +- +- if (A_LTE_B(max_load, next_load)) { +- max_load = next_load; +- maxed_cpu = perf_stats[t].cpu; +- } else if (A_LTE_B(max_2nd_load, next_load)) { +- max_2nd_load = next_load; +- } else if (A_LTE_B(max_3rd_load, next_load)) { +- max_3rd_load = next_load; +- } +- /* min scalability */ +- if (perf_stats[t].aperf_diff) { +- next_s0 = (float)perf_stats[t].pperf_diff / +- perf_stats[t].aperf_diff; +- /* since aperf/pperf are not read oneshot, ratio > 1 is not ruled out */ +- next_s0 = (next_s0 >= 1) ? (1 - EPSILON) : next_s0; +- } +- if (A_LTE_B(next_s0, min_s0) || first_pass) { +- min_s0 = next_s0; +- min_s0_cpu = perf_stats[t].cpu; +- } +- +- if (A_GT_B(min_load, next_load)) { +- min_load = next_load; +- } +- first_pass = 0; +- } +- +- if (stat_init_only) +- return 0; +- +- grp.worst_stall = min_s0; +- grp.worst_stall_cpu = min_s0_cpu; +- +- grp.c0_max = max_load; +- grp.c0_2nd_max = max_2nd_load; +- grp.c0_3rd_max = max_3rd_load; +- grp.c0_min = min_load; +- +- return maxed_cpu; ++/* Calc perf [cpu utilization per core] difference from MSR registers */ ++int update_perf_diffs(float *sum_norm_perf, int stat_init_only) ++{ ++ float max_load = 0, max_2nd_load = 0, max_3rd_load = 0, next_load = 0; ++ float min_load = 100.0, min_s0 = 1.0, next_s0 = 1.0; ++ int t, min_s0_cpu = 0, first_pass = 1; ++ struct thread_data tdata; ++ int maxed_cpu = -1; ++ ++ for (t = 0; t < get_max_online_cpu(); t++) { ++ if (!cpu_applicable(t, get_cur_state())) ++ continue; ++ ++ /*reading through perf api*/ ++ if (read_aperf_mperf_tsc_perf(&tdata, t) != LPMD_SUCCESS) { ++ lpmd_log_error("read_aperf_mperf_tsc_perf failed for cpu = %d\n", t); ++ continue; ++ } ++ perf_stats[t].pperf_diff = cpu_get_diff_pperf(tdata.pperf, t); ++ perf_stats[t].aperf_diff = cpu_get_diff_aperf(tdata.aperf, t); ++ perf_stats[t].mperf_diff = cpu_get_diff_mperf(tdata.mperf, t); ++ perf_stats[t].tsc_diff = cpu_get_diff_tsc(tdata.tsc, t); ++ ++ if (stat_init_only) ++ continue; ++ ++ /* ++ * Normalized perf metric defined as pperf per load per time. ++ * The rationale is detailed here: ++ * github.com/intel/psst >whitepapers >Generic_perf_per_watt.pdf ++ * Given that delta_load = delta_mperf/delta_tsc, we can rewrite ++ * as given below. ++ */ ++ if (perf_stats[t].tsc_diff) { ++ next_load = (float)100 * perf_stats[t].mperf_diff / ++ perf_stats[t].tsc_diff; ++ perf_stats[t].l0 = next_load; ++ } ++ ++ if (A_LTE_B(max_load, next_load)) { ++ max_load = next_load; ++ maxed_cpu = perf_stats[t].cpu; ++ } else if (A_LTE_B(max_2nd_load, next_load)) { ++ max_2nd_load = next_load; ++ } else if (A_LTE_B(max_3rd_load, next_load)) { ++ max_3rd_load = next_load; ++ } ++ /* min scalability */ ++ if (perf_stats[t].aperf_diff) { ++ next_s0 = (float)perf_stats[t].pperf_diff / ++ perf_stats[t].aperf_diff; ++ /* since aperf/pperf are not read oneshot, ratio > 1 is not ruled out */ ++ next_s0 = (next_s0 >= 1) ? (1 - EPSILON) : next_s0; ++ } ++ if (A_LTE_B(next_s0, min_s0) || first_pass) { ++ min_s0 = next_s0; ++ min_s0_cpu = perf_stats[t].cpu; ++ } ++ ++ if (A_GT_B(min_load, next_load)) ++ min_load = next_load; ++ ++ first_pass = 0; ++ } ++ ++ if (stat_init_only) ++ return 0; ++ ++ grp.worst_stall = min_s0; ++ grp.worst_stall_cpu = min_s0_cpu; ++ ++ grp.c0_max = max_load; ++ grp.c0_2nd_max = max_2nd_load; ++ grp.c0_3rd_max = max_3rd_load; ++ grp.c0_min = min_load; ++ ++ return maxed_cpu; + } + + /* close perf fd's */ +-static void close_amperf_fd(int cpu) { +- if(perf_stats[cpu].aperf_fd) close(perf_stats[cpu].aperf_fd); +- if(perf_stats[cpu].mperf_fd) close(perf_stats[cpu].mperf_fd); +- if(perf_stats[cpu].pperf_fd) close(perf_stats[cpu].pperf_fd); ++static void close_amperf_fd(int cpu) ++{ ++ if (perf_stats[cpu].aperf_fd) ++ close(perf_stats[cpu].aperf_fd); ++ if (perf_stats[cpu].mperf_fd) ++ close(perf_stats[cpu].mperf_fd); ++ if (perf_stats[cpu].pperf_fd) ++ close(perf_stats[cpu].pperf_fd); + } + + /* cleanup perf_stat structure */ +-static void perf_stat_uninit() { +- int max_cpus = get_max_cpus(); +- +- if (perf_stats) { +- for (size_t i = 0; i < max_cpus; ++i) { +- close_amperf_fd(i); +- memset( &perf_stats[i], 0, sizeof(perf_stats_t)); +- } +- free(perf_stats); +- } ++static void perf_stat_uninit(void) ++{ ++ int max_cpus = get_max_cpus(); ++ ++ if (perf_stats) { ++ for (size_t i = 0; i < max_cpus; ++i) { ++ close_amperf_fd(i); ++ memset(&perf_stats[i], 0, sizeof(struct perf_stats_t)); ++ } ++ free(perf_stats); ++ } + } + +-static void uninit_perf_calculations() { +- +- perf_stat_uninit(); +- +- if (last_aperf) +- free(last_aperf); +- if (last_mperf) +- free(last_mperf); +- if (last_pperf) +- free(last_pperf); +- if (last_tsc) +- free(last_tsc); ++static void uninit_perf_calculations(void) ++{ ++ perf_stat_uninit(); ++ ++ if (last_aperf) ++ free(last_aperf); ++ if (last_mperf) ++ free(last_mperf); ++ if (last_pperf) ++ free(last_pperf); ++ if (last_tsc) ++ free(last_tsc); + } +-/********************perf calculation - end *****************************************/ + ++/********************perf calculation - end *****************************************/ + + /********************SMA calculation - begin *****************************************/ + + /* initialize avg calculation variables */ +-static void init_sma_calculations() { +- for (int i = 0; i < SMA_CPU_COUNT; i++) { +- grp.sma_sum[i] = -1; +- for (int j = 0; j < SMA_LENGTH; j++) +- sample[i][j] = 0; +- } +- grp.sma_pos = -1; ++static void init_sma_calculations(void) ++{ ++ for (int i = 0; i < SMA_CPU_COUNT; i++) { ++ grp.sma_sum[i] = -1; ++ for (int j = 0; j < SMA_LENGTH; j++) ++ sample[i][j] = 0; ++ } ++ grp.sma_pos = -1; + } + + /* Helper avg calculation */ +-static int do_sum(int *sam, int len) { +- int sum = 0; ++static int do_sum(int *sam, int len) ++{ ++ int sum = 0; + +- for (int i = 0; i < len; i++) +- sum += sam[i]; +- return sum; ++ for (int i = 0; i < len; i++) ++ sum += sam[i]; ++ return sum; + } + + /* average cpu usage */ +-int state_max_avg() { +- grp.sma_pos += 1; +- +- int v1 = (int)round(grp.c0_max * SCALE_DECIMAL); +- int v2 = (int)round(grp.c0_2nd_max * SCALE_DECIMAL); +- int v3 = (int)round(grp.c0_3rd_max * SCALE_DECIMAL); +- +- if (grp.sma_pos == SMA_LENGTH) +- grp.sma_pos = 0; +- if (grp.sma_sum[0] == -1) { +- sample[0][grp.sma_pos] = v1; +- sample[1][grp.sma_pos] = v2; +- sample[2][grp.sma_pos] = v3; +- if (grp.sma_pos == SMA_LENGTH - 1) { +- grp.sma_sum[0] = do_sum(sample[0], SMA_LENGTH); +- grp.sma_sum[1] = do_sum(sample[1], SMA_LENGTH); +- grp.sma_sum[2] = do_sum(sample[2], SMA_LENGTH); +- } +- } else { +- grp.sma_sum[0] = grp.sma_sum[0] - sample[0][grp.sma_pos] + v1; +- grp.sma_sum[1] = grp.sma_sum[1] - sample[1][grp.sma_pos] + v2; +- grp.sma_sum[2] = grp.sma_sum[2] - sample[2][grp.sma_pos] + v3; +- sample[0][grp.sma_pos] = v1; +- sample[1][grp.sma_pos] = v2; +- sample[2][grp.sma_pos] = v3; +- } +- +- grp.sma_avg1 = +- (int)round((double)grp.sma_sum[0] / (double)(SMA_LENGTH * SCALE_DECIMAL)); +- grp.sma_avg2 = +- (int)round((double)grp.sma_sum[1] / (double)(SMA_LENGTH * SCALE_DECIMAL)); +- grp.sma_avg3 = +- (int)round((double)grp.sma_sum[2] / (double)(SMA_LENGTH * SCALE_DECIMAL)); +- +- return 1; ++int state_max_avg(void) ++{ ++ grp.sma_pos += 1; ++ ++ int v1 = (int)round(grp.c0_max * SCALE_DECIMAL); ++ int v2 = (int)round(grp.c0_2nd_max * SCALE_DECIMAL); ++ int v3 = (int)round(grp.c0_3rd_max * SCALE_DECIMAL); ++ ++ if (grp.sma_pos == SMA_LENGTH) ++ grp.sma_pos = 0; ++ if (grp.sma_sum[0] == -1) { ++ sample[0][grp.sma_pos] = v1; ++ sample[1][grp.sma_pos] = v2; ++ sample[2][grp.sma_pos] = v3; ++ if (grp.sma_pos == SMA_LENGTH - 1) { ++ grp.sma_sum[0] = do_sum(sample[0], SMA_LENGTH); ++ grp.sma_sum[1] = do_sum(sample[1], SMA_LENGTH); ++ grp.sma_sum[2] = do_sum(sample[2], SMA_LENGTH); ++ } ++ } else { ++ grp.sma_sum[0] = grp.sma_sum[0] - sample[0][grp.sma_pos] + v1; ++ grp.sma_sum[1] = grp.sma_sum[1] - sample[1][grp.sma_pos] + v2; ++ grp.sma_sum[2] = grp.sma_sum[2] - sample[2][grp.sma_pos] + v3; ++ sample[0][grp.sma_pos] = v1; ++ sample[1][grp.sma_pos] = v2; ++ sample[2][grp.sma_pos] = v3; ++ } ++ ++ grp.sma_avg1 = (int)round((double)grp.sma_sum[0] / ++ (double)(SMA_LENGTH * SCALE_DECIMAL)); ++ grp.sma_avg2 = (int)round((double)grp.sma_sum[1] / ++ (double)(SMA_LENGTH * SCALE_DECIMAL)); ++ grp.sma_avg3 = (int)round((double)grp.sma_sum[2] / ++ (double)(SMA_LENGTH * SCALE_DECIMAL)); ++ ++ return 1; + } + + /********************SMA calculation - end *****************************************/ + + /* return multi threaded false if at least one cpu is under utilizied */ +-int max_mt_detected(enum state_idx state) { +- for (int t = 0; t < get_max_online_cpu(); t++) { +- +- if (!cpu_applicable(t, state)) +- continue; +- +- if A_LTE_B +- (perf_stats[t].l0, (UTIL_LOW)) +- return 0; +- } +- return 1; ++int max_mt_detected(enum state_idx state) ++{ ++ for (int t = 0; t < get_max_online_cpu(); t++) { ++ if (!cpu_applicable(t, state)) ++ continue; ++ ++ if A_LTE_B(perf_stats[t].l0, (UTIL_LOW)) ++ return 0; ++ } ++ return 1; + } + + /* initialize */ +-int util_init_proxy(void) { +- float dummy; ++int util_init_proxy(void) ++{ ++ float dummy; + +- if(init_perf_calculations(get_max_online_cpu()) < 0) { +- lpmd_log_error("WLT_Proxy: error initializing perf calculations"); +- return LPMD_ERROR; +- } ++ if (init_perf_calculations(get_max_online_cpu()) < 0) { ++ lpmd_log_error("WLT_Proxy: error initializing perf calculations"); ++ return LPMD_ERROR; ++ } + +- update_perf_diffs(&dummy, 1); ++ update_perf_diffs(&dummy, 1); + +- init_sma_calculations(); ++ init_sma_calculations(); + +- return LPMD_SUCCESS; ++ return LPMD_SUCCESS; + } + + /* cleanup */ +-void util_uninit_proxy(void) { +- uninit_perf_calculations(); +- uninit_state_manager(); ++void util_uninit_proxy(void) ++{ ++ uninit_perf_calculations(); ++ uninit_state_manager(); + } +diff --git a/src/wlt_proxy/wlt_proxy.c b/src/wlt_proxy/wlt_proxy.c +index 24bfa44..80b229c 100644 +--- a/src/wlt_proxy/wlt_proxy.c ++++ b/src/wlt_proxy/wlt_proxy.c +@@ -1,24 +1,5 @@ +-/* +- * wlt_proxy.c: Intel Linux Energy Optimizer WLT proxy +- * +- * Copyright (C) 2024 Intel Corporation. All rights reserved. +- * +- * This program is free software; you can redistribute it and/or modify +- * it under the terms of the GNU General Public License as published by +- * the Free Software Foundation; either version 2 of the License, or +- * (at your option) any later version. +- * +- * This program is distributed in the hope that it will be useful, +- * but WITHOUT ANY WARRANTY; without even the implied warranty of +- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +- * GNU General Public License for more details. +- * +- * You should have received a copy of the GNU General Public License +- * along with this program; if not, write to the Free Software +- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +- * +- * This file contains the Workload type detection proxy entry and callback functions. +- */ ++// SPDX-License-Identifier: GPL-2.0-or-later ++/* Copyright (C) 2026 Intel Corporation */ + + #include "lpmd.h" //wlt_type + #include "state_common.h" +@@ -30,19 +11,22 @@ int next_proxy_poll = 1000; + int wlt_type = WLT_IDLE; + + /* called at the configured interval to take action; return next interval and workload type*/ +-int read_wlt_proxy(int *interval) { +- state_machine_auto(); +- *interval = next_proxy_poll; ++int read_wlt_proxy(int *interval) ++{ ++ state_machine_auto(); ++ *interval = next_proxy_poll; + +- return wlt_type; ++ return wlt_type; + } + + /* Returns success if proxy supported on platform */ +-int wlt_proxy_init() { +- return util_init_proxy(); ++int wlt_proxy_init(void) ++{ ++ return util_init_proxy(); + } + + /* make sure all resource are properly released and closed */ +-void wlt_proxy_uninit(void) { +- util_uninit_proxy(); ++void wlt_proxy_uninit(void) ++{ ++ util_uninit_proxy(); + } +diff --git a/tests/lpm_test_interface.sh b/tests/lpm_test_interface.sh +index 89e5628..2bb0f1e 100755 +--- a/tests/lpm_test_interface.sh ++++ b/tests/lpm_test_interface.sh +@@ -1,4 +1,6 @@ + #!/bin/bash ++# SPDX-License-Identifier: GPL-2.0-or-later ++# Copyright (C) 2026 Intel Corporation + + if [ "$(whoami)" != "root" ] + then +diff --git a/tools/intel_lpmd_control.c b/tools/intel_lpmd_control.c +index 81dc340..dea54b8 100644 +--- a/tools/intel_lpmd_control.c ++++ b/tools/intel_lpmd_control.c +@@ -1,24 +1,5 @@ +-/* +- * intel_lpmd_control.c: Intel Low Power Daemon control utility +- * +- * Copyright (C) 2023 Intel Corporation. All rights reserved. +- * +- * This program is free software; you can redistribute it and/or modify +- * it under the terms of the GNU General Public License as published by +- * the Free Software Foundation; either version 2 of the License, or +- * (at your option) any later version. +- * +- * This program is distributed in the hope that it will be useful, +- * but WITHOUT ANY WARRANTY; without even the implied warranty of +- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +- * GNU General Public License for more details. +- * +- * You should have received a copy of the GNU General Public License +- * along with this program; if not, write to the Free Software +- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +- * +- * This program can be used to control modes of Low power mode daemon +- */ ++// SPDX-License-Identifier: GPL-2.0-or-later ++/* Copyright (C) 2026 Intel Corporation */ + + #include + #include +@@ -36,83 +17,80 @@ + #define INTEL_LPMD_SERVICE_OBJECT_PATH "/org/freedesktop/intel_lpmd" + #define INTEL_LPMD_SERVICE_INTERFACE "org.freedesktop.intel_lpmd" + +-int +-main(int argc, char **argv) ++int main(int argc, char **argv) + { + g_autoptr(GDBusConnection) connection = NULL; +- g_autoptr (GString) command = NULL; ++ g_autoptr(GString) command = NULL; ++ g_autoptr(GVariant) result = NULL; + GError *error = NULL; ++ const gchar *state; + +- if (geteuid () != 0) { +- g_warning ("Must run as root"); +- exit (1); ++ if (geteuid()) { ++ g_warning("Must run as root"); ++ exit(1); + } + + if (argc < 2) { +- fprintf (stderr, "intel_lpmd_control: missing control command\n"); +- fprintf (stderr, "syntax:\n"); +- fprintf (stderr, "intel_lpmd_control ON|OFF|AUTO|STATUS\n"); +- exit (0); ++ fprintf(stderr, "intel_lpmd_control: missing control command\n"); ++ fprintf(stderr, "syntax:\n"); ++ fprintf(stderr, "intel_lpmd_control ON|OFF|AUTO|STATUS\n"); ++ exit(0); + } + + connection = g_bus_get_sync(G_BUS_TYPE_SYSTEM, NULL, &error); +- if (connection == NULL) ++ if (!connection) + return FALSE; + +- if (!strncmp (argv[1], "STATUS", 6)) { +- g_autoptr(GVariant) result = NULL; +- +- result = g_dbus_connection_call_sync (connection, +- INTEL_LPMD_SERVICE_NAME, +- INTEL_LPMD_SERVICE_OBJECT_PATH, +- INTEL_LPMD_SERVICE_INTERFACE, +- "GetState", +- NULL, +- G_VARIANT_TYPE ("(s)"), +- G_DBUS_CALL_FLAGS_NONE, +- -1, +- NULL, +- &error); +- +- if (error != NULL) { +- g_warning ("Fail on connecting lpmd: %s", error->message); +- exit (1); ++ if (!strncmp(argv[1], "STATUS", 6)) { ++ result = g_dbus_connection_call_sync(connection, ++ INTEL_LPMD_SERVICE_NAME, ++ INTEL_LPMD_SERVICE_OBJECT_PATH, ++ INTEL_LPMD_SERVICE_INTERFACE, ++ "GetState", ++ NULL, ++ G_VARIANT_TYPE("(s)"), ++ G_DBUS_CALL_FLAGS_NONE, ++ -1, ++ NULL, ++ &error); ++ ++ if (error) { ++ g_warning("Fail on connecting lpmd: %s", error->message); ++ exit(1); + } + +- const gchar *state; +- +- g_variant_get (result, "(&s)", &state); +- g_print ("%s\n", state); ++ g_variant_get(result, "(&s)", &state); ++ g_print("%s\n", state); + + return 0; + } + +- if (!strncmp (argv[1], "ON", 2)) +- command = g_string_new ("LPM_FORCE_ON"); +- else if (!strncmp (argv[1], "OFF", 3)) +- command = g_string_new ("LPM_FORCE_OFF"); +- else if (!strncmp (argv[1], "AUTO", 4)) +- command = g_string_new ("LPM_AUTO"); +- else { +- g_warning ("intel_lpmd_control: Invalid command"); +- exit (1); ++ if (!strncmp(argv[1], "ON", 2)) { ++ command = g_string_new("LPM_FORCE_ON"); ++ } else if (!strncmp(argv[1], "OFF", 3)) { ++ command = g_string_new("LPM_FORCE_OFF"); ++ } else if (!strncmp(argv[1], "AUTO", 4)) { ++ command = g_string_new("LPM_AUTO"); ++ } else { ++ g_warning("intel_lpmd_control: Invalid command"); ++ exit(1); + } + +- g_dbus_connection_call_sync (connection, +- INTEL_LPMD_SERVICE_NAME, +- INTEL_LPMD_SERVICE_OBJECT_PATH, +- INTEL_LPMD_SERVICE_INTERFACE, +- command->str, +- NULL, +- NULL, +- G_DBUS_CALL_FLAGS_NONE, +- -1, +- NULL, +- &error); +- +- if (error != NULL) { +- g_warning ("Fail on connecting lpmd: %s", error->message); +- exit (1); ++ g_dbus_connection_call_sync(connection, ++ INTEL_LPMD_SERVICE_NAME, ++ INTEL_LPMD_SERVICE_OBJECT_PATH, ++ INTEL_LPMD_SERVICE_INTERFACE, ++ command->str, ++ NULL, ++ NULL, ++ G_DBUS_CALL_FLAGS_NONE, ++ -1, ++ NULL, ++ &error); ++ ++ if (error) { ++ g_warning("Fail on connecting lpmd: %s", error->message); ++ exit(1); + } + + return 0; +-- +2.55.0 + diff --git a/0052-Add-a-simple-Makefile-to-use-without-autotools.patch b/0052-Add-a-simple-Makefile-to-use-without-autotools.patch new file mode 100644 index 0000000..17626be --- /dev/null +++ b/0052-Add-a-simple-Makefile-to-use-without-autotools.patch @@ -0,0 +1,209 @@ +From 3ae7d167215da71489b54f84de15562444677a3d Mon Sep 17 00:00:00 2001 +From: "Fabio M. De Francesco" +Date: Fri, 5 Jun 2026 12:54:48 -0700 +Subject: [PATCH 52/56] Add a simple Makefile to use without autotools + +Kernel tools don't use the autogen system and a smaller, simpler build +system makes things easier to install, there are less dependencies. + +Use the same logic to create a Makefile.simple. + +Assisted-by: Claude:claude-opus-4-7 +Signed-off-by: Fabio M. De Francesco +Tested-by: Maciej Wieczor-Retman +Signed-off-by: Maciej Wieczor-Retman +[Srinivas- Kept autotools Makefiles for easy migrations for current distro] +Signed-off-by: Srinivas Pandruvada +--- + Makefile.simple | 179 ++++++++++++++++++++++++++++++++++++++++++++++++ + 1 file changed, 179 insertions(+) + create mode 100644 Makefile.simple + +diff --git a/Makefile.simple b/Makefile.simple +new file mode 100644 +index 0000000..652c14b +--- /dev/null ++++ b/Makefile.simple +@@ -0,0 +1,179 @@ ++# SPDX-License-Identifier: GPL-2.0-or-later ++ ++# Install paths (matching automake defaults) ++prefix ?= /usr/local ++sbindir ?= $(prefix)/sbin ++confdir ?= $(prefix)/etc/intel_lpmd ++rundir ?= $(prefix)/var/run/intel_lpmd ++systemd_unitdir ?= /usr/lib/systemd/system ++dbus_sysdir ?= /etc/dbus-1/system.d ++mandir ?= $(prefix)/share/man ++ ++ifeq ($(srctree),) ++srctree := $(patsubst %/,%,$(dir $(CURDIR))) ++srctree := $(patsubst %/,%,$(dir $(srctree))) ++srctree := $(patsubst %/,%,$(dir $(srctree))) ++srctree := $(patsubst %/,%,$(dir $(srctree))) ++endif ++ ++# Do not use make's built-in rules ++MAKEFLAGS += -r ++ ++VERSION = 0.1.0 ++ ++# pkg-config dependencies ++ifeq ($(shell pkg-config --exists glib-2.0 gio-2.0 gio-unix-2.0 gmodule-2.0 && echo yes),yes) ++ GLIB_CFLAGS := $(shell pkg-config --cflags glib-2.0 gio-2.0 gio-unix-2.0 gmodule-2.0) ++ GLIB_LIBS := $(shell pkg-config --libs glib-2.0 gio-2.0 gio-unix-2.0 gmodule-2.0) ++else ++ $(error No glib-2.0 pkg-config found, please install libglib2.0-dev/glib2-devel) ++endif ++ ++ifeq ($(shell pkg-config --exists libxml-2.0 && echo yes),yes) ++ XML2_CFLAGS := $(shell pkg-config --cflags libxml-2.0) ++ XML2_LIBS := $(shell pkg-config --libs libxml-2.0) ++else ++ $(error No libxml-2.0 pkg-config found, please install libxml2-dev/libxml2-devel) ++endif ++ ++ifeq ($(shell pkg-config --exists upower-glib && echo yes),yes) ++ UPOWER_CFLAGS := $(shell pkg-config --cflags upower-glib) ++ UPOWER_LIBS := $(shell pkg-config --libs upower-glib) ++else ++ $(error No upower-glib pkg-config found, please install libupower-glib-dev/upower-devel) ++endif ++ ++ifeq ($(shell pkg-config --exists libnl-3.0 libnl-genl-3.0 && echo yes),yes) ++ NL3_CFLAGS := $(shell pkg-config --cflags libnl-3.0 libnl-genl-3.0) ++ NL3_LIBS := $(shell pkg-config --libs libnl-3.0 libnl-genl-3.0) ++else ++ $(error No libnl-3.0 pkg-config found, please install libnl-3-dev libnl-genl-3-dev/libnl3-devel) ++endif ++ ++ifeq ($(shell pkg-config --exists libsystemd && echo yes),yes) ++ SYSTEMD_CFLAGS := $(shell pkg-config --cflags libsystemd) ++ SYSTEMD_LIBS := $(shell pkg-config --libs libsystemd) ++else ++ $(error No libsystemd pkg-config found, please install libsystemd-dev/systemd-devel) ++endif ++ ++override CFLAGS += -O2 -Wall -g -DGDBUS=1 \ ++ -DGLIB_SUPPORT \ ++ -DGETTEXT_PACKAGE=\"intel_lpmd\" \ ++ -DPACKAGE_VERSION=\"$(VERSION)\" \ ++ -DTDCONFDIR=\"$(confdir)\" \ ++ -DTDRUNDIR=\"$(rundir)\" \ ++ -DTDLOCALEDIR=\"$(prefix)/share/locale\" \ ++ -I. -Isrc/include -Isrc/wlt_proxy/include \ ++ $(GLIB_CFLAGS) $(XML2_CFLAGS) $(UPOWER_CFLAGS) $(NL3_CFLAGS) $(SYSTEMD_CFLAGS) ++ ++override LDFLAGS += \ ++ $(GLIB_LIBS) $(XML2_LIBS) $(UPOWER_LIBS) $(NL3_LIBS) $(SYSTEMD_LIBS) -lm ++ ++# Source files ++LPMD_SRCS = \ ++ src/lpmd_cgroup.c \ ++ src/lpmd_config.c \ ++ src/lpmd_cpu.c \ ++ src/lpmd_cpumask.c \ ++ src/lpmd_dbus_server.c \ ++ src/lpmd_helpers.c \ ++ src/lpmd_hfi.c \ ++ src/lpmd_irq.c \ ++ src/lpmd_main.c \ ++ src/lpmd_misc.c \ ++ src/lpmd_proc.c \ ++ src/lpmd_socket.c \ ++ src/lpmd_state_machine.c \ ++ src/lpmd_uevent.c \ ++ src/lpmd_util.c \ ++ src/lpmd_wlt.c \ ++ src/wlt_proxy/spike_mgmt.c \ ++ src/wlt_proxy/state_machine.c \ ++ src/wlt_proxy/state_manager.c \ ++ src/wlt_proxy/state_util.c \ ++ src/wlt_proxy/wlt_proxy.c ++ ++LPMD_OBJS = $(LPMD_SRCS:.c=.o) lpmd-resource.o ++CTRL_OBJS = tools/intel_lpmd_control.o ++ ++ALL_TARGETS := intel_lpmd intel_lpmd_control ++ALL_PROGRAMS := $(patsubst %,$(OUTPUT)%,$(ALL_TARGETS)) ++ ++all: $(ALL_PROGRAMS) ++ ++# Generated files ++config.h: FORCE ++ $(QUIET_GEN)echo '/* Auto-generated - do not edit */' > $@ && \ ++ echo '#define GDBUS 1' >> $@ && \ ++ echo '#define GETTEXT_PACKAGE "intel_lpmd"' >> $@ && \ ++ echo '#define PACKAGE_VERSION "$(VERSION)"' >> $@ ++ ++lpmd-resource.c: lpmd-resource.gresource.xml src/intel_lpmd_dbus_interface.xml ++ $(QUIET_GEN)glib-compile-resources --sourcedir=. --generate-source \ ++ --target=$@ $< ++ ++prepare: config.h lpmd-resource.c ++ ++%.o: %.c | prepare ++ $(Q)mkdir -p $(dir $@) ++ $(QUIET_CC)$(CC) $(CFLAGS) -c -o $@ $< ++ ++$(OUTPUT)intel_lpmd: $(LPMD_OBJS) ++ $(QUIET_LINK)$(CC) $(CFLAGS) $^ $(LDFLAGS) -o $@ ++ ++$(OUTPUT)intel_lpmd_control: $(CTRL_OBJS) ++ $(QUIET_LINK)$(CC) $(CFLAGS) $< $(GLIB_LIBS) -o $@ ++ ++$(OUTPUT)intel_lpmd_focus_helper: $(FOCUS_OBJS) ++ $(QUIET_LINK)$(CC) $(CFLAGS) $< $(GLIB_LIBS) -o $@ ++ ++DATA_CONFIGS = \ ++ data/intel_lpmd_config.xml \ ++ data/intel_lpmd_config_examples.xml \ ++ data/intel_lpmd_config_experimental.xml \ ++ data/intel_lpmd_config_F6_M170.xml \ ++ data/intel_lpmd_config_F6_M189.xml \ ++ data/intel_lpmd_config_F6_M204.xml ++ ++MAN_PAGES = \ ++ man/intel_lpmd.8 \ ++ man/intel_lpmd_control.8 \ ++ man/intel_lpmd_config.xml.5 ++ ++install: $(ALL_PROGRAMS) ++ install -d -m 755 $(DESTDIR)$(sbindir) ++ install $(OUTPUT)intel_lpmd $(DESTDIR)$(sbindir) ++ install $(OUTPUT)intel_lpmd_control $(DESTDIR)$(sbindir) ++ install -d -m 755 $(DESTDIR)$(confdir) ++ install -m 644 $(DATA_CONFIGS) $(DESTDIR)$(confdir) ++ install -d -m 755 $(DESTDIR)$(rundir) ++ install -d -m 755 $(DESTDIR)$(systemd_unitdir) ++ sed 's|@sbindir@|$(sbindir)|g' data/intel_lpmd.service.in > \ ++ $(DESTDIR)$(systemd_unitdir)/intel_lpmd.service ++ install -d -m 755 $(DESTDIR)$(dbus_sysdir) ++ install -m 644 data/org.freedesktop.intel_lpmd.conf $(DESTDIR)$(dbus_sysdir) ++ install -d -m 755 $(DESTDIR)$(mandir)/man5 ++ install -m 644 man/intel_lpmd_config.xml.5 $(DESTDIR)$(mandir)/man5/ ++ install -d -m 755 $(DESTDIR)$(mandir)/man8 ++ install -m 644 man/intel_lpmd.8 $(DESTDIR)$(mandir)/man8/ ++ install -m 644 man/intel_lpmd_control.8 $(DESTDIR)$(mandir)/man8/ ++ ++uninstall: ++ rm -f $(DESTDIR)$(sbindir)/intel_lpmd ++ rm -f $(DESTDIR)$(sbindir)/intel_lpmd_control ++ rm -rf $(DESTDIR)$(confdir) ++ rm -f $(DESTDIR)$(systemd_unitdir)/intel_lpmd.service ++ rm -f $(DESTDIR)$(dbus_sysdir)/org.freedesktop.intel_lpmd.conf ++ rm -f $(DESTDIR)$(mandir)/man5/intel_lpmd_config.xml.5 ++ rm -f $(DESTDIR)$(mandir)/man8/intel_lpmd.8 ++ rm -f $(DESTDIR)$(mandir)/man8/intel_lpmd_control.8 ++ @echo "Note: $(DESTDIR)$(rundir) not removed (may contain runtime data)" ++ ++clean: ++ rm -f $(ALL_PROGRAMS) config.h lpmd-resource.c ++ find $(or $(OUTPUT),.) -name '*.o' -delete -o -name '\.*.d' -delete ++ ++FORCE: ++ ++.PHONY: all install uninstall clean FORCE prepare +-- +2.55.0 + diff --git a/0053-Minor-printf-formatting-fixes.patch b/0053-Minor-printf-formatting-fixes.patch new file mode 100644 index 0000000..5bae880 --- /dev/null +++ b/0053-Minor-printf-formatting-fixes.patch @@ -0,0 +1,42 @@ +From ca4a67ede41f896407946c56563d56ad4c136682 Mon Sep 17 00:00:00 2001 +From: Maciej Wieczor-Retman +Date: Tue, 19 May 2026 15:44:01 +0200 +Subject: [PATCH 53/56] Minor printf formatting fixes + +Two small bugs for formatting found by copilot. + +Signed-off-by: Maciej Wieczor-Retman +--- + src/lpmd_helpers.c | 2 +- + src/lpmd_state_machine.c | 2 +- + 2 files changed, 2 insertions(+), 2 deletions(-) + +diff --git a/src/lpmd_helpers.c b/src/lpmd_helpers.c +index 3bcd55a..a90df40 100644 +--- a/src/lpmd_helpers.c ++++ b/src/lpmd_helpers.c +@@ -296,7 +296,7 @@ int lpmd_read_yn(const char *name, int *val, int print_level) + } + + if (print_level >= 0) +- lpmd_log_debug("%sRead \"%c\" from %s\n", prefix, *val, name); ++ lpmd_log_debug("%sRead \"%d\" from %s\n", prefix, *val, name); + + return 0; + } +diff --git a/src/lpmd_state_machine.c b/src/lpmd_state_machine.c +index 833d98d..ed7d4dd 100644 +--- a/src/lpmd_state_machine.c ++++ b/src/lpmd_state_machine.c +@@ -250,7 +250,7 @@ static void dump_state(struct lpmd_config_state_t *state, char *str, int debug) + offset += snprintf(buf + offset, MAX_STR_LENGTH - offset, + "SliderAC [%d] ", state->balance_slider_ac); + offset += snprintf(buf + offset, MAX_STR_LENGTH - offset, +- "SliderDC [%d] ", state->balance_slider_ac); ++ "SliderDC [%d] ", state->balance_slider_dc); + offset += snprintf(buf + offset, MAX_STR_LENGTH - offset, + "OffsetAC [%d] ", state->slider_offset_ac); + offset += snprintf(buf + offset, MAX_STR_LENGTH - offset, +-- +2.55.0 + diff --git a/0054-lpmd_config-Fix-compilation-warning-on-buffer-size.patch b/0054-lpmd_config-Fix-compilation-warning-on-buffer-size.patch new file mode 100644 index 0000000..bab2d56 --- /dev/null +++ b/0054-lpmd_config-Fix-compilation-warning-on-buffer-size.patch @@ -0,0 +1,28 @@ +From 86b4fabadf89ac00d93e179c21ffe8a48c76653e Mon Sep 17 00:00:00 2001 +From: Maciej Wieczor-Retman +Date: Fri, 22 May 2026 11:43:24 +0200 +Subject: [PATCH 54/56] lpmd_config: Fix compilation warning on buffer size + +Fix unnecessary -1 in strncpy() by moving it over to snprintf(). + +Signed-off-by: Maciej Wieczor-Retman +--- + src/lpmd_config.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/src/lpmd_config.c b/src/lpmd_config.c +index b6ae995..444ee98 100644 +--- a/src/lpmd_config.c ++++ b/src/lpmd_config.c +@@ -571,7 +571,7 @@ int lpmd_get_config(struct lpmd_config_t *lpmd_config) + return LPMD_ERROR; + } + +- strncpy(lpmd_config->file_name, file_name, MAX_FILE_NAME_PATH - 1); ++ snprintf(lpmd_config->file_name, MAX_FILE_NAME_PATH, "%s", file_name); + + process_xml: + doc = xmlReadFile(file_name, NULL, 0); +-- +2.55.0 + diff --git a/0055-Fix-cpumask_exclude_copy-destination-population.patch b/0055-Fix-cpumask_exclude_copy-destination-population.patch new file mode 100644 index 0000000..347b137 --- /dev/null +++ b/0055-Fix-cpumask_exclude_copy-destination-population.patch @@ -0,0 +1,34 @@ +From df3a7214656e66972c9bec68fa937fbae4bfb633 Mon Sep 17 00:00:00 2001 +From: Srinivas Pandruvada +Date: Thu, 28 May 2026 16:53:07 -0700 +Subject: [PATCH 55/56] Fix cpumask_exclude_copy destination population + +cpumask_exclude_copy() reset the destination mask and filtered +excluded CPUs, but never added the remaining CPUs to the destination. +That left the result empty for the HFI banned-CPU path. + +Add the missing cpumask_add_cpu() call so CPUMASK_HFI is built as +online CPUs minus banned CPUs, and the resulting mask can be applied +correctly by the HFI state flow. + +Signed-off-by: Srinivas Pandruvada +--- + src/lpmd_cpumask.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/src/lpmd_cpumask.c b/src/lpmd_cpumask.c +index fc87371..6b70fed 100644 +--- a/src/lpmd_cpumask.c ++++ b/src/lpmd_cpumask.c +@@ -357,6 +357,8 @@ void cpumask_exclude_copy(enum cpumask_idx source, enum cpumask_idx dest, enum c + + if (CPU_ISSET_S(i, size_cpumask, cpumasks[exclude].mask)) + continue; ++ ++ cpumask_add_cpu(i, dest); + } + } + +-- +2.55.0 + diff --git a/0056-When-GFX-trigger-is-enabled-don-t-disable-util-calcu.patch b/0056-When-GFX-trigger-is-enabled-don-t-disable-util-calcu.patch new file mode 100644 index 0000000..e0a02fd --- /dev/null +++ b/0056-When-GFX-trigger-is-enabled-don-t-disable-util-calcu.patch @@ -0,0 +1,35 @@ +From 89d706eca1a17f466a5875ff2743dd4decddb536 Mon Sep 17 00:00:00 2001 +From: "Pandruvada, Srinivas" +Date: Mon, 8 Jun 2026 11:54:09 -0700 +Subject: [PATCH 56/56] When GFX trigger is enabled don't disable util + calculation + +When GFX util is used as trigger in a state, it can be used along +with WLT with polling enabled. This is done for Lunar Lake config +file. + +So, don't reset lpmd_config.util_enable = 0 when wlt_polling is +enabled and there is a GFX util trigger in a state. + +Signed-off-by: Pandruvada, Srinivas +--- + src/lpmd_proc.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/src/lpmd_proc.c b/src/lpmd_proc.c +index a459fda..2c4e335 100644 +--- a/src/lpmd_proc.c ++++ b/src/lpmd_proc.c +@@ -475,7 +475,8 @@ int lpmd_main(void) + } + + if (lpmd_config.wlt_hint_enable && !lpmd_config.hfi_lpm_enable) { +- lpmd_config.util_enable = 0; ++ if (!lpmd_config.util_gfx_enable && lpmd_config.wlt_hint_poll_enable) ++ lpmd_config.util_enable = 0; + if (!lpmd_config.wlt_proxy_enable) { + poll_fds[poll_fd_cnt].fd = wlt_init(); + if (poll_fds[poll_fd_cnt].fd > 0) { +-- +2.55.0 + diff --git a/intel-lpmd.spec b/intel-lpmd.spec index a1f8999..a854cd8 100644 --- a/intel-lpmd.spec +++ b/intel-lpmd.spec @@ -1,23 +1,72 @@ %global daemon_name intel_lpmd Name: intel-lpmd -Version: 0.0.9 +Version: 0.1.0 Release: 1%{?dist} + Summary: Intel Low Power Mode Daemon License: GPL-2.0-or-later URL: https://github.com/intel/intel-lpmd Source0: %{url}/archive/v%{version}/%{name}-%{version}.tar.gz -# Drop unused variables https://github.com/intel/intel-lpmd/pull/93 -# https://github.com/intel/intel-lpmd/commit/c2cea33c873146f1b6186c02fe79d1a2bb1c7867.patch -Patch1001: 0001-lpmd_util-Remove-unused-variables.patch -# https://github.com/intel/intel-lpmd/commit/311b7929d4c821630fabf5293ec5b4bec5411162.patch -Patch1002: 0002-wlt_proxy-state_manager-Fix-Werror-switch.patch -# https://github.com/intel/intel-lpmd/commit/4277f3496dc51f89ed0815e0f51659338f7a6ba9.patch -Patch1003: 0003-wlt_proxy-state_util-Remove-unused-variables.patch -# https://github.com/intel/intel-lpmd/commit/af6d8f93a0a1041bd936b8901707e1253c5e5279.patch -Patch1004: 0004-wlt_proxy-state_util-Drop-unused-function-read_tsc_c.patch +# Rebase to the latest commits +Patch1001: 0001-Deprecate-the-dbus-glib-dependency-at-Install-Depend.patch +Patch1002: 0002-lpmd_cpu-Tablets-are-also-a-Mobile-platform.patch +Patch1003: 0003-build-replace-open-coded-if-in-configure.ac-with-AS_.patch +Patch1004: 0004-build-avoid-use-of-test-.-a.patch +Patch1005: 0005-build-fix-spelling-in-error-message-when-libsystemd-.patch +Patch1006: 0006-build-apply-consistent-argument-quoting-in-configure.patch +Patch1007: 0007-lpmd_cgroup-simple-isolation-fix-works-without-inter.patch +Patch1008: 0008-state_machine-Fix-issue-106-incorrect-order-of-polli.patch +Patch1009: 0009-lpmd_state_machine-Fix-deadlock-on-power-profile-swi.patch +Patch1010: 0010-Process-itmt-read-error.patch +Patch1011: 0011-lpmd_misc-Fix-ITMT.patch +Patch1012: 0012-make-itmt_init-to-void.patch +Patch1013: 0013-config-Fix-incorrect-cpu-numbers.patch +Patch1014: 0014-readme-Reformat-long-lines-into-markdown-readable-bl.patch +Patch1015: 0015-readme-Emphasize-expectations-from-the-user.patch +Patch1016: 0016-man-Update-the-main-man-page.patch +Patch1017: 0017-man-Update-lpmd-control-utility-man-page.patch +Patch1018: 0018-man-Generic-updates-to-the-config-man-page.patch +Patch1019: 0019-man-Move-unused-config-options-to-the-unused-section.patch +Patch1020: 0020-Add-Panther-Lake-4P0E4L.patch +Patch1021: 0021-Remove-power-group.patch +Patch1022: 0022-Add-GetState-D-Bus-method-to-query-current-LPM-contr.patch +Patch1023: 0023-fix-restore-systemd-unit-install-path.patch +Patch1024: 0024-fix-prevent-cgroup-isolation-churn-during-WLT-pollin.patch +Patch1025: 0025-Fix-build-breakage-with-the-last-commit.patch +Patch1026: 0026-git-Setup-gitignore.patch +Patch1027: 0027-lpmd_config-Cleanup-code-indentation-in-parse-states.patch +Patch1028: 0028-lpmd_config-Rename-island-number-cores-tags.patch +Patch1029: 0029-lpmd_state_machine-Count-system-of-specifing-active-.patch +Patch1030: 0030-lpmd_cpumask-Dynamic-core-type-cpumask-allocation.patch +Patch1031: 0031-lpmd_config-ALL-keyword-for-active-P-E-L-cores-tag.patch +Patch1032: 0032-config-Simplify-the-M204-configuration.patch +Patch1033: 0033-lpmd_cpu-Fix-incorrect-struct-initialization.patch +Patch1034: 0034-Introduce-WLT-state-mask-and-notification-delay.patch +Patch1035: 0035-Arrow-Lake-enabling.patch +Patch1036: 0036-lpmd_config-Skip-platform-check-if-a-matching-config.patch +Patch1037: 0037-config-Nova-Lake-enabling.patch +Patch1038: 0038-lpmd_cpu-Add-wildcard-for-active_cpus-and-cpu-types.patch +Patch1039: 0039-data-Fix-active-cpu-spelling.patch +Patch1040: 0040-Enable-platform-agnostic-config-fallback-for-unknown.patch +Patch1041: 0041-docs-Clarify-slider-config.patch +Patch1042: 0042-Validate-slider-balance-and-offset-configuration.patch +Patch1043: 0043-lpmd_cpumask-Refactor-get_cgroup_systemd_vals-to-avo.patch +Patch1044: 0044-lpmd_cpu-Add-a-CPU-blacklist-cpumask.patch +Patch1045: 0045-lpmd_cpu-Skip-filling-out-type-cpumasks-if-there-was.patch +Patch1046: 0046-lpmd_cpumask-init-level-complex-isolation-fix-blackl.patch +Patch1047: 0047-lpmd_cpumask-Refresh-cached-data-when-blacklisting-c.patch +Patch1048: 0048-lpmd_cpumask-Refactor-getting-cached-values.patch +Patch1049: 0049-lpmd_proc-Export-the-state-name-when-an-empty-cpumas.patch +Patch1050: 0050-Use-return-value-of-lpmd_read_int.patch +Patch1051: 0051-all-Apply-kernel-formatting.patch +Patch1052: 0052-Add-a-simple-Makefile-to-use-without-autotools.patch +Patch1053: 0053-Minor-printf-formatting-fixes.patch +Patch1054: 0054-lpmd_config-Fix-compilation-warning-on-buffer-size.patch +Patch1055: 0055-Fix-cpumask_exclude_copy-destination-population.patch +Patch1056: 0056-When-GFX-trigger-is-enabled-don-t-disable-util-calcu.patch ExclusiveArch: x86_64 @@ -57,6 +106,8 @@ autoreconf --install --verbose %install %make_install install -D -p -m 644 src/%{daemon_name}_dbus_interface.xml %{buildroot}/%{_datadir}/dbus-1/interfaces/org.freedesktop.%{daemon_name}.xml +# Nova lake config +install -D -p -m 644 data/intel_lpmd_config_F18_M1.xml %{buildroot}/%{_sysconfdir}/%{daemon_name}/intel_lpmd_config_F18_M1.xml %post %systemd_post %{daemon_name}.service @@ -76,6 +127,10 @@ install -D -p -m 644 src/%{daemon_name}_dbus_interface.xml %{buildroot}/%{_datad %config(noreplace) %{_sysconfdir}/%{daemon_name}/%{daemon_name}_config.xml %config(noreplace) %{_sysconfdir}/%{daemon_name}/intel_lpmd_config_F6_M170.xml %config(noreplace) %{_sysconfdir}/%{daemon_name}/intel_lpmd_config_F6_M189.xml +%config(noreplace) %{_sysconfdir}/%{daemon_name}/intel_lpmd_config_F6_M181.xml +%config(noreplace) %{_sysconfdir}/%{daemon_name}/intel_lpmd_config_F6_M204.xml +%config(noreplace) %{_sysconfdir}/%{daemon_name}/intel_lpmd_config_F18_M1.xml + %{_datadir}/dbus-1/interfaces/org.freedesktop.%{daemon_name}.xml %{_datadir}/dbus-1/system.d/org.freedesktop.%{daemon_name}.conf %{_datadir}/dbus-1/system-services/org.freedesktop.%{daemon_name}.service diff --git a/sources b/sources index 201dd6b..f78d4a7 100644 --- a/sources +++ b/sources @@ -1 +1 @@ -SHA512 (intel-lpmd-0.0.9.tar.gz) = ed7977960b9794e0fd9ba46f37f3aaaee4082ad4c884a69855faa75b6b3b2c1ac13992bbc808c88460717455144ef54da89b21de58773283259752ad88f1f03b +SHA512 (intel-lpmd-0.1.0.tar.gz) = 45f18b7c98814af6f56659fcf63d32cfb3df3daa93bb6561b271094d5a2d91d50589a50475ae3b59aaeaca489e76a45879754a74af0dad443686697269f8b51d