Skip to content

Commit 5bfffe3

Browse files
Ghoul4500KyleGospo
authored andcommitted
[FROM-ML] platform/x86: asus-armoury: gate PPT writes behind active fan curve
On models flagged with requires_fan_curve in the DMI power_data table (28 entries), the BIOS ACPI method SPLX only writes PPT values to the EC when the fan mode is set to Manual (FANM=4). FANM is set to 4 by the DEFC method when a custom fan curve is written. Without an active custom fan curve, the WMI DEVS call returns success but the firmware silently ignores the PPT value, so userspace observes no effect from its write. Gate writes to ASUS_WMI_DEVID_PPT_{PL1_SPL,PL2_SPPT,PL3_FPPT,APU_SPPT, PLAT_SPPT} on a check of asus_wmi_custom_fan_curve_is_enabled(), and return -EBUSY with a pr_warn() when no fan curve is active on an affected model. Export the helper from asus-wmi so asus-armoury can call it across module boundaries. Signed-off-by: Ahmed Yaseen <yaseen@ghoul.dev>
1 parent fadf982 commit 5bfffe3

3 files changed

Lines changed: 53 additions & 0 deletions

File tree

drivers/platform/x86/asus-armoury.c

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,8 @@ struct asus_armoury_priv {
9393

9494
u32 mini_led_dev_id;
9595
u32 gpu_mux_dev_id;
96+
97+
bool requires_fan_curve;
9698
};
9799

98100
static struct asus_armoury_priv asus_armoury = {
@@ -216,6 +218,22 @@ static int armoury_set_devstate(struct kobj_attribute *attr,
216218
u32 result;
217219
int err;
218220

221+
/* On some models, PPT changes require an active fan curve */
222+
if (asus_armoury.requires_fan_curve) {
223+
switch (dev_id) {
224+
case ASUS_WMI_DEVID_PPT_PL1_SPL:
225+
case ASUS_WMI_DEVID_PPT_PL2_SPPT:
226+
case ASUS_WMI_DEVID_PPT_PL3_FPPT:
227+
case ASUS_WMI_DEVID_PPT_APU_SPPT:
228+
case ASUS_WMI_DEVID_PPT_PLAT_SPPT:
229+
if (!asus_wmi_custom_fan_curve_is_enabled()) {
230+
pr_warn("PPT change requires an active fan curve on this model. Enable a custom fan curve first.\n");
231+
return -EBUSY;
232+
}
233+
break;
234+
}
235+
}
236+
219237
/*
220238
* Prevent developers from bricking devices or issuing dangerous
221239
* commands that can be difficult or impossible to recover from.
@@ -1002,6 +1020,8 @@ static void init_rog_tunables(void)
10021020
return;
10031021
}
10041022

1023+
asus_armoury.requires_fan_curve = power_data->requires_fan_curve;
1024+
10051025
/* Initialize AC power tunables */
10061026
ac_limits = power_data->ac_data;
10071027
if (ac_limits) {

drivers/platform/x86/asus-wmi.c

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -342,6 +342,9 @@ struct asus_wmi {
342342
/* Global to allow setting externally without requiring driver data */
343343
static enum asus_ally_mcu_hack use_ally_mcu_hack = ASUS_WMI_ALLY_MCU_HACK_INIT;
344344

345+
/* Global asus_wmi instance for use by exported functions */
346+
static struct asus_wmi *asus_wmi_instance;
347+
345348
#if IS_ENABLED(CONFIG_ASUS_WMI_DEPRECATED_ATTRS)
346349
static void asus_wmi_show_deprecated(void)
347350
{
@@ -3999,6 +4002,28 @@ static int asus_wmi_custom_fan_curve_init(struct asus_wmi *asus)
39994002
return 0;
40004003
}
40014004

4005+
/*
4006+
* Returns true if at least one custom fan curve is active
4007+
*
4008+
* Used by asus-armoury to check if PPT writes will be accepted by the BIOS
4009+
* on models that require an active fan curve for TDP changes.
4010+
*/
4011+
bool asus_wmi_custom_fan_curve_is_enabled(void)
4012+
{
4013+
struct asus_wmi *asus = asus_wmi_instance;
4014+
struct fan_curve_data *curves;
4015+
4016+
if (!asus)
4017+
return false;
4018+
4019+
curves = asus->custom_fan_curves;
4020+
4021+
return (asus->cpu_fan_curve_available && curves[FAN_CURVE_DEV_CPU].enabled) ||
4022+
(asus->gpu_fan_curve_available && curves[FAN_CURVE_DEV_GPU].enabled) ||
4023+
(asus->mid_fan_curve_available && curves[FAN_CURVE_DEV_MID].enabled);
4024+
}
4025+
EXPORT_SYMBOL_NS_GPL(asus_wmi_custom_fan_curve_is_enabled, "ASUS_WMI");
4026+
40024027
/* Throttle thermal policy ****************************************************/
40034028
static int throttle_thermal_policy_write(struct asus_wmi *asus)
40044029
{
@@ -5165,6 +5190,8 @@ static int asus_wmi_add(struct platform_device *pdev)
51655190

51665191
asus_wmi_debugfs_init(asus);
51675192

5193+
asus_wmi_instance = asus;
5194+
51685195
return 0;
51695196

51705197
fail_wmi_handler:
@@ -5208,6 +5235,7 @@ static void asus_wmi_remove(struct platform_device *device)
52085235
throttle_thermal_policy_set_default(asus);
52095236
asus_wmi_battery_exit(asus);
52105237

5238+
asus_wmi_instance = NULL;
52115239
kfree(asus);
52125240
}
52135241

include/linux/platform_data/x86/asus-wmi.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -196,6 +196,7 @@ int asus_wmi_evaluate_method(u32 method_id, u32 arg0, u32 arg1, u32 *retval);
196196
int asus_hid_register_listener(struct asus_hid_listener *cdev);
197197
void asus_hid_unregister_listener(struct asus_hid_listener *cdev);
198198
int asus_hid_event(enum asus_hid_event event);
199+
bool asus_wmi_custom_fan_curve_is_enabled(void);
199200
#else
200201
static inline void set_ally_mcu_hack(enum asus_ally_mcu_hack status)
201202
{
@@ -227,6 +228,10 @@ static inline int asus_hid_event(enum asus_hid_event event)
227228
{
228229
return -ENODEV;
229230
}
231+
static inline bool asus_wmi_custom_fan_curve_is_enabled(void)
232+
{
233+
return false;
234+
}
230235
#endif
231236

232237
#endif /* __PLATFORM_DATA_X86_ASUS_WMI_H */

0 commit comments

Comments
 (0)