* [PATCH 1/4] platform/x86: hp-wmi: fix fan table parsing
2026-04-01 11:17 [PATCH 0/4] platform/x86: hp-wmi: Improve support for some HP boards Krishna Chomal
@ 2026-04-01 11:17 ` Krishna Chomal
2026-04-01 11:23 ` Ilpo Järvinen
2026-04-01 11:17 ` [PATCH 2/4] platform/x86: hp-wmi: Add support for OMEN MAX 16-ak0xxx (8D87) Krishna Chomal
` (2 subsequent siblings)
3 siblings, 1 reply; 7+ messages in thread
From: Krishna Chomal @ 2026-04-01 11:17 UTC (permalink / raw)
To: ilpo.jarvinen, hansg; +Cc: platform-driver-x86, linux-kernel, Krishna Chomal
For Victus S devices, the BIOS fan table header was being incorrectly
parsed as:
struct {
u8 unknown;
u8 num_entries;
}
The first field should be num_fans and the second should be unknown. It
is pure coincidence that interpreting an "unknown" field as "num_entries"
worked on multiple device, however for board 8D87 (in an upcoming patch),
this assumption fails, and the hp-wmi driver fails to load.
We fix this by correcting the header definition and compensating for
num_entries by parsing each entry of the fan table until an all-NULL row
is obtained, mirroring the behavior of OMEN Gaming Hub on Windows.
Fixes: 46be1453e6e6 ("platform/x86: hp-wmi: add manual fan control for Victus S models")
Signed-off-by: Krishna Chomal <krishna.chomal108@gmail.com>
---
drivers/platform/x86/hp/hp-wmi.c | 41 +++++++++++++++++++++++++-------
1 file changed, 33 insertions(+), 8 deletions(-)
diff --git a/drivers/platform/x86/hp/hp-wmi.c b/drivers/platform/x86/hp/hp-wmi.c
index 304d9ac63c8a..d630b7f6e146 100644
--- a/drivers/platform/x86/hp/hp-wmi.c
+++ b/drivers/platform/x86/hp/hp-wmi.c
@@ -433,14 +433,14 @@ struct hp_wmi_hwmon_priv {
};
struct victus_s_fan_table_header {
+ u8 num_fans;
u8 unknown;
- u8 num_entries;
} __packed;
struct victus_s_fan_table_entry {
u8 cpu_rpm;
u8 gpu_rpm;
- u8 unknown;
+ u8 noise_db;
} __packed;
struct victus_s_fan_table {
@@ -2514,7 +2514,9 @@ static int hp_wmi_setup_fan_settings(struct hp_wmi_hwmon_priv *priv)
u8 fan_data[128] = { 0 };
struct victus_s_fan_table *fan_table;
u8 min_rpm, max_rpm, gpu_delta;
- int ret;
+ u8 cpu_rpm, gpu_rpm, noise_db;
+ int ret, num_entries, i;
+ size_t header_size, entry_size;
/* Default behaviour on hwmon init is automatic mode */
priv->mode = PWM_MODE_AUTO;
@@ -2529,13 +2531,36 @@ static int hp_wmi_setup_fan_settings(struct hp_wmi_hwmon_priv *priv)
return ret;
fan_table = (struct victus_s_fan_table *)fan_data;
- if (fan_table->header.num_entries == 0 ||
- sizeof(struct victus_s_fan_table_header) +
- sizeof(struct victus_s_fan_table_entry) * fan_table->header.num_entries > sizeof(fan_data))
+ if (fan_table->header.num_fans == 0)
+ return -EINVAL;
+
+ header_size = sizeof(struct victus_s_fan_table_header);
+ entry_size = sizeof(struct victus_s_fan_table_entry);
+ num_entries = (sizeof(fan_data) - header_size) / entry_size;
+ min_rpm = U8_MAX;
+ max_rpm = 0;
+
+ for (i = 0 ; i < num_entries ; i++) {
+ cpu_rpm = fan_table->entries[i].cpu_rpm;
+ gpu_rpm = fan_table->entries[i].gpu_rpm;
+ noise_db = fan_table->entries[i].noise_db;
+
+ /*
+ * On some devices, the fan table is truncated with an all-zero row,
+ * hence we stop parsing here.
+ */
+ if (cpu_rpm == 0 && gpu_rpm == 0 && noise_db == 0)
+ break;
+
+ if (cpu_rpm < min_rpm)
+ min_rpm = cpu_rpm;
+ if (cpu_rpm > max_rpm)
+ max_rpm = cpu_rpm;
+ }
+
+ if (min_rpm == U8_MAX || max_rpm == 0)
return -EINVAL;
- min_rpm = fan_table->entries[0].cpu_rpm;
- max_rpm = fan_table->entries[fan_table->header.num_entries - 1].cpu_rpm;
gpu_delta = fan_table->entries[0].gpu_rpm - fan_table->entries[0].cpu_rpm;
priv->min_rpm = min_rpm;
priv->max_rpm = max_rpm;
--
2.53.0
^ permalink raw reply related [flat|nested] 7+ messages in thread* Re: [PATCH 1/4] platform/x86: hp-wmi: fix fan table parsing
2026-04-01 11:17 ` [PATCH 1/4] platform/x86: hp-wmi: fix fan table parsing Krishna Chomal
@ 2026-04-01 11:23 ` Ilpo Järvinen
2026-04-01 12:03 ` Krishna Chomal
0 siblings, 1 reply; 7+ messages in thread
From: Ilpo Järvinen @ 2026-04-01 11:23 UTC (permalink / raw)
To: Krishna Chomal; +Cc: Hans de Goede, platform-driver-x86, LKML
On Wed, 1 Apr 2026, Krishna Chomal wrote:
> For Victus S devices, the BIOS fan table header was being incorrectly
> parsed as:
> struct {
> u8 unknown;
> u8 num_entries;
> }
>
> The first field should be num_fans and the second should be unknown. It
> is pure coincidence that interpreting an "unknown" field as "num_entries"
So this coincidence is that both fields happened to contain the same
value? Or (same or) smaller?
--
i.
> worked on multiple device, however for board 8D87 (in an upcoming patch),
> this assumption fails, and the hp-wmi driver fails to load.
>
> We fix this by correcting the header definition and compensating for
> num_entries by parsing each entry of the fan table until an all-NULL row
> is obtained, mirroring the behavior of OMEN Gaming Hub on Windows.
>
> Fixes: 46be1453e6e6 ("platform/x86: hp-wmi: add manual fan control for Victus S models")
> Signed-off-by: Krishna Chomal <krishna.chomal108@gmail.com>
> ---
> drivers/platform/x86/hp/hp-wmi.c | 41 +++++++++++++++++++++++++-------
> 1 file changed, 33 insertions(+), 8 deletions(-)
>
> diff --git a/drivers/platform/x86/hp/hp-wmi.c b/drivers/platform/x86/hp/hp-wmi.c
> index 304d9ac63c8a..d630b7f6e146 100644
> --- a/drivers/platform/x86/hp/hp-wmi.c
> +++ b/drivers/platform/x86/hp/hp-wmi.c
> @@ -433,14 +433,14 @@ struct hp_wmi_hwmon_priv {
> };
>
> struct victus_s_fan_table_header {
> + u8 num_fans;
> u8 unknown;
> - u8 num_entries;
> } __packed;
>
> struct victus_s_fan_table_entry {
> u8 cpu_rpm;
> u8 gpu_rpm;
> - u8 unknown;
> + u8 noise_db;
> } __packed;
>
> struct victus_s_fan_table {
> @@ -2514,7 +2514,9 @@ static int hp_wmi_setup_fan_settings(struct hp_wmi_hwmon_priv *priv)
> u8 fan_data[128] = { 0 };
> struct victus_s_fan_table *fan_table;
> u8 min_rpm, max_rpm, gpu_delta;
> - int ret;
> + u8 cpu_rpm, gpu_rpm, noise_db;
> + int ret, num_entries, i;
> + size_t header_size, entry_size;
>
> /* Default behaviour on hwmon init is automatic mode */
> priv->mode = PWM_MODE_AUTO;
> @@ -2529,13 +2531,36 @@ static int hp_wmi_setup_fan_settings(struct hp_wmi_hwmon_priv *priv)
> return ret;
>
> fan_table = (struct victus_s_fan_table *)fan_data;
> - if (fan_table->header.num_entries == 0 ||
> - sizeof(struct victus_s_fan_table_header) +
> - sizeof(struct victus_s_fan_table_entry) * fan_table->header.num_entries > sizeof(fan_data))
> + if (fan_table->header.num_fans == 0)
> + return -EINVAL;
> +
> + header_size = sizeof(struct victus_s_fan_table_header);
> + entry_size = sizeof(struct victus_s_fan_table_entry);
> + num_entries = (sizeof(fan_data) - header_size) / entry_size;
> + min_rpm = U8_MAX;
> + max_rpm = 0;
> +
> + for (i = 0 ; i < num_entries ; i++) {
> + cpu_rpm = fan_table->entries[i].cpu_rpm;
> + gpu_rpm = fan_table->entries[i].gpu_rpm;
> + noise_db = fan_table->entries[i].noise_db;
> +
> + /*
> + * On some devices, the fan table is truncated with an all-zero row,
> + * hence we stop parsing here.
> + */
> + if (cpu_rpm == 0 && gpu_rpm == 0 && noise_db == 0)
> + break;
> +
> + if (cpu_rpm < min_rpm)
> + min_rpm = cpu_rpm;
> + if (cpu_rpm > max_rpm)
> + max_rpm = cpu_rpm;
> + }
> +
> + if (min_rpm == U8_MAX || max_rpm == 0)
> return -EINVAL;
>
> - min_rpm = fan_table->entries[0].cpu_rpm;
> - max_rpm = fan_table->entries[fan_table->header.num_entries - 1].cpu_rpm;
> gpu_delta = fan_table->entries[0].gpu_rpm - fan_table->entries[0].cpu_rpm;
> priv->min_rpm = min_rpm;
> priv->max_rpm = max_rpm;
>
^ permalink raw reply [flat|nested] 7+ messages in thread* Re: [PATCH 1/4] platform/x86: hp-wmi: fix fan table parsing
2026-04-01 11:23 ` Ilpo Järvinen
@ 2026-04-01 12:03 ` Krishna Chomal
0 siblings, 0 replies; 7+ messages in thread
From: Krishna Chomal @ 2026-04-01 12:03 UTC (permalink / raw)
To: Ilpo Järvinen; +Cc: Hans de Goede, platform-driver-x86, LKML
On Wed, Apr 01, 2026 at 02:23:31PM +0300, Ilpo Järvinen wrote:
>On Wed, 1 Apr 2026, Krishna Chomal wrote:
>
>> For Victus S devices, the BIOS fan table header was being incorrectly
>> parsed as:
>> struct {
>> u8 unknown;
>> u8 num_entries;
>> }
>>
>> The first field should be num_fans and the second should be unknown. It
>> is pure coincidence that interpreting an "unknown" field as "num_entries"
>
>So this coincidence is that both fields happened to contain the same
>value? Or (same or) smaller?
>
Yes, for my board (and for the several recent additions in Victus S list)
the second field in the fan table header happened to match the number of
entries in the table, making the previous implementation appear correct.
However on board 8D87 (and potentially others), the second field contains
a larger value which causes the following check to fail:
if (fan_table->header.num_entries == 0 ||
sizeof(struct victus_s_fan_table_header) +
sizeof(struct victus_s_fan_table_entry) * fan_table->header.num_entries > sizeof(fan_data))
After reverse engineering the Windows implementation, I found that the
official software ignores this second field entirely. Instead it uses
the "stop-at-null" approach implemented in this patch.
>--
> i.
^ permalink raw reply [flat|nested] 7+ messages in thread
* [PATCH 2/4] platform/x86: hp-wmi: Add support for OMEN MAX 16-ak0xxx (8D87)
2026-04-01 11:17 [PATCH 0/4] platform/x86: hp-wmi: Improve support for some HP boards Krishna Chomal
2026-04-01 11:17 ` [PATCH 1/4] platform/x86: hp-wmi: fix fan table parsing Krishna Chomal
@ 2026-04-01 11:17 ` Krishna Chomal
2026-04-01 11:17 ` [PATCH 3/4] platform/x86: hp-wmi: Add support for Omen 16-n0xxx (8A44) Krishna Chomal
2026-04-01 11:17 ` [PATCH 4/4] platform/x86: hp-wmi: Add support for Omen 16-wf1xxx (8C77) Krishna Chomal
3 siblings, 0 replies; 7+ messages in thread
From: Krishna Chomal @ 2026-04-01 11:17 UTC (permalink / raw)
To: ilpo.jarvinen, hansg
Cc: platform-driver-x86, linux-kernel, Krishna Chomal, Jinyang Zhu
The HP OMEN MAX 16-ak0xxx (8D87) requires the same WMI queries as other
Victus S devices, hence it has been added to the corresponding list.
For this reason, platform_profile_victus_s_get_ec() will be called
during thermal_profile_setup() and victus_s_powersource_event() to
obtain hardware state (platform profile) by reading from the Embedded
Controller, however, this particular board's EC does not seem to expose
the platform profile value, unlike other boards. Hence EC readback is
disabled.
Testing on board 8D87 confirmed that platform profile is registered
successfully and fan RPMs are readable and controllable.
Tested-by: Jinyang Zhu <Jakie101@proton.me>
Signed-off-by: Krishna Chomal <krishna.chomal108@gmail.com>
---
drivers/platform/x86/hp/hp-wmi.c | 18 ++++++++++++++++--
1 file changed, 16 insertions(+), 2 deletions(-)
diff --git a/drivers/platform/x86/hp/hp-wmi.c b/drivers/platform/x86/hp/hp-wmi.c
index d630b7f6e146..24164f294420 100644
--- a/drivers/platform/x86/hp/hp-wmi.c
+++ b/drivers/platform/x86/hp/hp-wmi.c
@@ -48,6 +48,7 @@ MODULE_ALIAS("wmi:5FB7F034-2C63-45E9-BE91-3D44E2C707E4");
enum hp_ec_offsets {
HP_EC_OFFSET_UNKNOWN = 0x00,
+ HP_NO_THERMAL_PROFILE_OFFSET = 0x01,
HP_VICTUS_S_EC_THERMAL_PROFILE_OFFSET = 0x59,
HP_OMEN_EC_THERMAL_PROFILE_FLAGS_OFFSET = 0x62,
HP_OMEN_EC_THERMAL_PROFILE_TIMER_OFFSET = 0x63,
@@ -120,6 +121,13 @@ static const struct thermal_profile_params omen_v1_thermal_params = {
.ec_tp_offset = HP_VICTUS_S_EC_THERMAL_PROFILE_OFFSET,
};
+static const struct thermal_profile_params omen_v1_no_ec_thermal_params = {
+ .performance = HP_OMEN_V1_THERMAL_PROFILE_PERFORMANCE,
+ .balanced = HP_OMEN_V1_THERMAL_PROFILE_DEFAULT,
+ .low_power = HP_OMEN_V1_THERMAL_PROFILE_DEFAULT,
+ .ec_tp_offset = HP_NO_THERMAL_PROFILE_OFFSET,
+};
+
/*
* A generic pointer for the currently-active board's thermal profile
* parameters.
@@ -201,6 +209,10 @@ static const struct dmi_system_id victus_s_thermal_profile_boards[] __initconst
.matches = { DMI_MATCH(DMI_BOARD_NAME, "8D41") },
.driver_data = (void *)&victus_s_thermal_params,
},
+ {
+ .matches = { DMI_MATCH(DMI_BOARD_NAME, "8D87") },
+ .driver_data = (void *)&omen_v1_no_ec_thermal_params,
+ },
{},
};
@@ -1801,7 +1813,8 @@ static int platform_profile_victus_s_get_ec(enum platform_profile_option *profil
const struct thermal_profile_params *params;
params = active_thermal_profile_params;
- if (params->ec_tp_offset == HP_EC_OFFSET_UNKNOWN) {
+ if (params->ec_tp_offset == HP_EC_OFFSET_UNKNOWN ||
+ params->ec_tp_offset == HP_NO_THERMAL_PROFILE_OFFSET) {
*profile = active_platform_profile;
return 0;
}
@@ -2156,7 +2169,8 @@ static int thermal_profile_setup(struct platform_device *device)
* behaves like a wrapper around active_platform_profile, to avoid using
* uninitialized data, we default to PLATFORM_PROFILE_BALANCED.
*/
- if (active_thermal_profile_params->ec_tp_offset == HP_EC_OFFSET_UNKNOWN) {
+ if (active_thermal_profile_params->ec_tp_offset == HP_EC_OFFSET_UNKNOWN ||
+ active_thermal_profile_params->ec_tp_offset == HP_NO_THERMAL_PROFILE_OFFSET) {
active_platform_profile = PLATFORM_PROFILE_BALANCED;
} else {
err = platform_profile_victus_s_get_ec(&active_platform_profile);
--
2.53.0
^ permalink raw reply related [flat|nested] 7+ messages in thread* [PATCH 3/4] platform/x86: hp-wmi: Add support for Omen 16-n0xxx (8A44)
2026-04-01 11:17 [PATCH 0/4] platform/x86: hp-wmi: Improve support for some HP boards Krishna Chomal
2026-04-01 11:17 ` [PATCH 1/4] platform/x86: hp-wmi: fix fan table parsing Krishna Chomal
2026-04-01 11:17 ` [PATCH 2/4] platform/x86: hp-wmi: Add support for OMEN MAX 16-ak0xxx (8D87) Krishna Chomal
@ 2026-04-01 11:17 ` Krishna Chomal
2026-04-01 11:17 ` [PATCH 4/4] platform/x86: hp-wmi: Add support for Omen 16-wf1xxx (8C77) Krishna Chomal
3 siblings, 0 replies; 7+ messages in thread
From: Krishna Chomal @ 2026-04-01 11:17 UTC (permalink / raw)
To: ilpo.jarvinen, hansg
Cc: platform-driver-x86, linux-kernel, Krishna Chomal, Prasoon Dev
The HP Omen 16-n0xxx (board ID: 8A44) has the same WMI interface as
other Victus S boards, but requires additional quirks for correctly
switching thermal profile.
Create a new quirk omen_v1_legacy_thermal_params which allows a board to
use Omen V1 thermal values, but rely on the older legacy
HP_OMEN_EC_THERMAL_PROFILE_OFFSET. Add the DMI board name to
victus_s_thermal_profile_boards[] table and map it to the newly added
quirk.
Testing on board 8A44 confirmed that platform profile is registered
successfully and fan RPMs are readable and controllable.
Tested-by: Prasoon Dev <prasoon5050@outlook.com>
Signed-off-by: Krishna Chomal <krishna.chomal108@gmail.com>
---
drivers/platform/x86/hp/hp-wmi.c | 11 +++++++++++
1 file changed, 11 insertions(+)
diff --git a/drivers/platform/x86/hp/hp-wmi.c b/drivers/platform/x86/hp/hp-wmi.c
index 24164f294420..3284cf0d74cb 100644
--- a/drivers/platform/x86/hp/hp-wmi.c
+++ b/drivers/platform/x86/hp/hp-wmi.c
@@ -121,6 +121,13 @@ static const struct thermal_profile_params omen_v1_thermal_params = {
.ec_tp_offset = HP_VICTUS_S_EC_THERMAL_PROFILE_OFFSET,
};
+static const struct thermal_profile_params omen_v1_legacy_thermal_params = {
+ .performance = HP_OMEN_V1_THERMAL_PROFILE_PERFORMANCE,
+ .balanced = HP_OMEN_V1_THERMAL_PROFILE_DEFAULT,
+ .low_power = HP_OMEN_V1_THERMAL_PROFILE_DEFAULT,
+ .ec_tp_offset = HP_OMEN_EC_THERMAL_PROFILE_OFFSET,
+};
+
static const struct thermal_profile_params omen_v1_no_ec_thermal_params = {
.performance = HP_OMEN_V1_THERMAL_PROFILE_PERFORMANCE,
.balanced = HP_OMEN_V1_THERMAL_PROFILE_DEFAULT,
@@ -181,6 +188,10 @@ static const char * const victus_thermal_profile_boards[] = {
/* DMI Board names of Victus 16-r and Victus 16-s laptops */
static const struct dmi_system_id victus_s_thermal_profile_boards[] __initconst = {
+ {
+ .matches = { DMI_MATCH(DMI_BOARD_NAME, "8A44") },
+ .driver_data = (void *)&omen_v1_legacy_thermal_params,
+ },
{
.matches = { DMI_MATCH(DMI_BOARD_NAME, "8BBE") },
.driver_data = (void *)&victus_s_thermal_params,
--
2.53.0
^ permalink raw reply related [flat|nested] 7+ messages in thread* [PATCH 4/4] platform/x86: hp-wmi: Add support for Omen 16-wf1xxx (8C77)
2026-04-01 11:17 [PATCH 0/4] platform/x86: hp-wmi: Improve support for some HP boards Krishna Chomal
` (2 preceding siblings ...)
2026-04-01 11:17 ` [PATCH 3/4] platform/x86: hp-wmi: Add support for Omen 16-n0xxx (8A44) Krishna Chomal
@ 2026-04-01 11:17 ` Krishna Chomal
3 siblings, 0 replies; 7+ messages in thread
From: Krishna Chomal @ 2026-04-01 11:17 UTC (permalink / raw)
To: ilpo.jarvinen, hansg
Cc: platform-driver-x86, linux-kernel, Krishna Chomal, Thomas Arici
The HP Omen 16-wf1xxx (board ID: 8C77) has the same WMI interface as
other Victus S boards, but requires quirks for correctly switching
thermal profile.
Add the DMI board name to victus_s_thermal_profile_boards[] table and
map it to omen_v1_thermal_params.
Testing on board 8C77 confirmed that platform profile is registered
successfully and fan RPMs are readable and controllable.
Tested-by: Thomas Arici <absolute3d86@gmail.com>
Reported-by: Thomas Arici <absolute3d86@gmail.com>
Closes: https://bugzilla.kernel.org/show_bug.cgi?id=221300
Signed-off-by: Krishna Chomal <krishna.chomal108@gmail.com>
---
drivers/platform/x86/hp/hp-wmi.c | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/drivers/platform/x86/hp/hp-wmi.c b/drivers/platform/x86/hp/hp-wmi.c
index 3284cf0d74cb..fc1eaf6c3e24 100644
--- a/drivers/platform/x86/hp/hp-wmi.c
+++ b/drivers/platform/x86/hp/hp-wmi.c
@@ -204,6 +204,10 @@ static const struct dmi_system_id victus_s_thermal_profile_boards[] __initconst
.matches = { DMI_MATCH(DMI_BOARD_NAME, "8BD5") },
.driver_data = (void *)&victus_s_thermal_params,
},
+ {
+ .matches = { DMI_MATCH(DMI_BOARD_NAME, "8C77") },
+ .driver_data = (void *)&omen_v1_thermal_params,
+ },
{
.matches = { DMI_MATCH(DMI_BOARD_NAME, "8C78") },
.driver_data = (void *)&omen_v1_thermal_params,
--
2.53.0
^ permalink raw reply related [flat|nested] 7+ messages in thread