Skip to content

Commit 9d317a5

Browse files
VulnXij-intel
authored andcommitted
platform/x86: hp-wmi: fix fan table parsing
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: 46be145 ("platform/x86: hp-wmi: add manual fan control for Victus S models") Signed-off-by: Krishna Chomal <[email protected]> Link: https://patch.msgid.link/[email protected] Reviewed-by: Ilpo Järvinen <[email protected]> Signed-off-by: Ilpo Järvinen <[email protected]>
1 parent 92c36b6 commit 9d317a5

1 file changed

Lines changed: 33 additions & 8 deletions

File tree

drivers/platform/x86/hp/hp-wmi.c

Lines changed: 33 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -469,14 +469,14 @@ struct hp_wmi_hwmon_priv {
469469
};
470470

471471
struct victus_s_fan_table_header {
472+
u8 num_fans;
472473
u8 unknown;
473-
u8 num_entries;
474474
} __packed;
475475

476476
struct victus_s_fan_table_entry {
477477
u8 cpu_rpm;
478478
u8 gpu_rpm;
479-
u8 unknown;
479+
u8 noise_db;
480480
} __packed;
481481

482482
struct victus_s_fan_table {
@@ -2563,7 +2563,9 @@ static int hp_wmi_setup_fan_settings(struct hp_wmi_hwmon_priv *priv)
25632563
u8 fan_data[128] = { 0 };
25642564
struct victus_s_fan_table *fan_table;
25652565
u8 min_rpm, max_rpm;
2566-
int gpu_delta, ret;
2566+
u8 cpu_rpm, gpu_rpm, noise_db;
2567+
int gpu_delta, i, num_entries, ret;
2568+
size_t header_size, entry_size;
25672569

25682570
/* Default behaviour on hwmon init is automatic mode */
25692571
priv->mode = PWM_MODE_AUTO;
@@ -2578,13 +2580,36 @@ static int hp_wmi_setup_fan_settings(struct hp_wmi_hwmon_priv *priv)
25782580
return ret;
25792581

25802582
fan_table = (struct victus_s_fan_table *)fan_data;
2581-
if (fan_table->header.num_entries == 0 ||
2582-
sizeof(struct victus_s_fan_table_header) +
2583-
sizeof(struct victus_s_fan_table_entry) * fan_table->header.num_entries > sizeof(fan_data))
2583+
if (fan_table->header.num_fans == 0)
2584+
return -EINVAL;
2585+
2586+
header_size = sizeof(struct victus_s_fan_table_header);
2587+
entry_size = sizeof(struct victus_s_fan_table_entry);
2588+
num_entries = (sizeof(fan_data) - header_size) / entry_size;
2589+
min_rpm = U8_MAX;
2590+
max_rpm = 0;
2591+
2592+
for (i = 0 ; i < num_entries ; i++) {
2593+
cpu_rpm = fan_table->entries[i].cpu_rpm;
2594+
gpu_rpm = fan_table->entries[i].gpu_rpm;
2595+
noise_db = fan_table->entries[i].noise_db;
2596+
2597+
/*
2598+
* On some devices, the fan table is truncated with an all-zero row,
2599+
* hence we stop parsing here.
2600+
*/
2601+
if (cpu_rpm == 0 && gpu_rpm == 0 && noise_db == 0)
2602+
break;
2603+
2604+
if (cpu_rpm < min_rpm)
2605+
min_rpm = cpu_rpm;
2606+
if (cpu_rpm > max_rpm)
2607+
max_rpm = cpu_rpm;
2608+
}
2609+
2610+
if (min_rpm == U8_MAX || max_rpm == 0)
25842611
return -EINVAL;
25852612

2586-
min_rpm = fan_table->entries[0].cpu_rpm;
2587-
max_rpm = fan_table->entries[fan_table->header.num_entries - 1].cpu_rpm;
25882613
gpu_delta = fan_table->entries[0].gpu_rpm - fan_table->entries[0].cpu_rpm;
25892614
priv->min_rpm = min_rpm;
25902615
priv->max_rpm = max_rpm;

0 commit comments

Comments
 (0)