Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 20 additions & 0 deletions drivers/platform/x86/asus-armoury.c
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,8 @@ struct asus_armoury_priv {

u32 mini_led_dev_id;
u32 gpu_mux_dev_id;

bool requires_fan_curve;
};

static struct asus_armoury_priv asus_armoury = {
Expand Down Expand Up @@ -216,6 +218,22 @@ static int armoury_set_devstate(struct kobj_attribute *attr,
u32 result;
int err;

/* On some models, PPT changes require an active fan curve */
if (asus_armoury.requires_fan_curve) {
switch (dev_id) {
case ASUS_WMI_DEVID_PPT_PL1_SPL:
case ASUS_WMI_DEVID_PPT_PL2_SPPT:
case ASUS_WMI_DEVID_PPT_PL3_FPPT:
case ASUS_WMI_DEVID_PPT_APU_SPPT:
case ASUS_WMI_DEVID_PPT_PLAT_SPPT:
if (!asus_wmi_custom_fan_curve_is_enabled()) {
pr_warn_once("PPT change requires an active fan curve on this model. Enable a custom fan curve first.\n");
return -EBUSY;
}
break;
}
}

/*
* Prevent developers from bricking devices or issuing dangerous
* commands that can be difficult or impossible to recover from.
Expand Down Expand Up @@ -1002,6 +1020,8 @@ static void init_rog_tunables(void)
return;
}

asus_armoury.requires_fan_curve = power_data->requires_fan_curve;

/* Initialize AC power tunables */
ac_limits = power_data->ac_data;
if (ac_limits) {
Expand Down
24 changes: 24 additions & 0 deletions drivers/platform/x86/asus-wmi.c
Original file line number Diff line number Diff line change
Expand Up @@ -3999,6 +3999,30 @@ static int asus_wmi_custom_fan_curve_init(struct asus_wmi *asus)
return 0;
}

/*
* Returns true if at least one custom fan curve is active
*
* Used by asus-armoury to check if PPT writes will be accepted by the BIOS
* on models that require an active fan curve for TDP changes.
*/
bool asus_wmi_custom_fan_curve_is_enabled(void)
{
struct fan_curve_data *curves;
struct asus_wmi *asus;

guard(spinlock_irqsave)(&asus_ref.lock);
asus = asus_ref.asus;
if (!asus)
return false;

curves = asus->custom_fan_curves;

return (asus->cpu_fan_curve_available && curves[FAN_CURVE_DEV_CPU].enabled) ||
(asus->gpu_fan_curve_available && curves[FAN_CURVE_DEV_GPU].enabled) ||
(asus->mid_fan_curve_available && curves[FAN_CURVE_DEV_MID].enabled);
}
EXPORT_SYMBOL_NS_GPL(asus_wmi_custom_fan_curve_is_enabled, "ASUS_WMI");

/* Throttle thermal policy ****************************************************/
static int throttle_thermal_policy_write(struct asus_wmi *asus)
{
Expand Down
5 changes: 5 additions & 0 deletions include/linux/platform_data/x86/asus-wmi.h
Original file line number Diff line number Diff line change
Expand Up @@ -196,6 +196,7 @@ int asus_wmi_evaluate_method(u32 method_id, u32 arg0, u32 arg1, u32 *retval);
int asus_hid_register_listener(struct asus_hid_listener *cdev);
void asus_hid_unregister_listener(struct asus_hid_listener *cdev);
int asus_hid_event(enum asus_hid_event event);
bool asus_wmi_custom_fan_curve_is_enabled(void);
#else
static inline void set_ally_mcu_hack(enum asus_ally_mcu_hack status)
{
Expand Down Expand Up @@ -227,6 +228,10 @@ static inline int asus_hid_event(enum asus_hid_event event)
{
return -ENODEV;
}
static inline bool asus_wmi_custom_fan_curve_is_enabled(void)
{
return false;
}
#endif

#endif /* __PLATFORM_DATA_X86_ASUS_WMI_H */