[PATCH v2 2/2] platform/x86: asus-armoury: expose requires_fan_curve via sysfs
From: Ahmed Yaseen
Date: Wed May 13 2026 - 12:08:46 EST
Expose the per-model requires_fan_curve flag as a read-only sysfs
attribute so userspace tools (asusctl, rogcc) can discover whether
the system requires an active custom fan curve for PPT changes to
take effect, and warn the user before issuing such writes.
The attribute appears at:
/sys/class/firmware-attributes/asus-armoury/attributes/requires_fan_curve
Document the attribute in
Documentation/ABI/testing/sysfs-class-firmware-attributes.
Signed-off-by: Ahmed Yaseen <yaseen@xxxxxxxxx>
---
.../testing/sysfs-class-firmware-attributes | 25 +++++++++++++++++++
drivers/platform/x86/asus-armoury.c | 15 +++++++++++
2 files changed, 40 insertions(+)
diff --git a/Documentation/ABI/testing/sysfs-class-firmware-attributes b/Documentation/ABI/testing/sysfs-class-firmware-attributes
index 2713efa509b4..12700a077f43 100644
--- a/Documentation/ABI/testing/sysfs-class-firmware-attributes
+++ b/Documentation/ABI/testing/sysfs-class-firmware-attributes
@@ -492,3 +492,28 @@ Description:
log entry size identifies audit log size for the current BIOS version.
The current size is 16 bytes but it can be up to 128 bytes long in future BIOS
versions.
+
+What: /sys/class/firmware-attributes/asus-armoury/attributes/requires_fan_curve
+Date: May 2026
+KernelVersion: 7.1
+Contact: platform-driver-x86@xxxxxxxxxxxxxxx
+Description:
+ A read-only attribute that reads 1 on ASUS ROG models where the
+ BIOS requires a custom fan curve to be active before Package
+ Power Tracking (PPT) writes take effect. On affected models, the
+ BIOS silently ignores writes to ppt_pl1_spl, ppt_pl2_sppt,
+ ppt_pl3_fppt, ppt_apu_sppt and ppt_platform_sppt unless a custom
+ fan curve has been written via the asus_custom_fan_curve hwmon
+ device.
+
+ The kernel rejects PPT writes with -EBUSY on these models when
+ no fan curve is active. Userspace tools can read this attribute
+ to surface a clear prerequisite to the user instead of letting
+ the write appear to succeed at the firmware-attribute layer
+ while the BIOS discards it.
+
+ == ==============================================
+ 0 No fan curve prerequisite for PPT writes.
+ 1 A custom fan curve must be active; PPT writes
+ return -EBUSY otherwise.
+ == ==============================================
diff --git a/drivers/platform/x86/asus-armoury.c b/drivers/platform/x86/asus-armoury.c
index 9b1c41a25b38..9b483d7e9855 100644
--- a/drivers/platform/x86/asus-armoury.c
+++ b/drivers/platform/x86/asus-armoury.c
@@ -127,6 +127,13 @@ static ssize_t pending_reboot_show(struct kobject *kobj, struct kobj_attribute *
static struct kobj_attribute pending_reboot = __ATTR_RO(pending_reboot);
+static ssize_t requires_fan_curve_show(struct kobject *kobj, struct kobj_attribute *attr, char *buf)
+{
+ return sysfs_emit(buf, "%d\n", asus_armoury.requires_fan_curve);
+}
+
+static struct kobj_attribute requires_fan_curve = __ATTR_RO(requires_fan_curve);
+
static bool asus_bios_requires_reboot(struct kobj_attribute *attr)
{
return !strcmp(attr->attr.name, "gpu_mux_mode") ||
@@ -914,6 +921,12 @@ static int asus_fw_attr_add(void)
goto err_destroy_kset;
}
+ err = sysfs_create_file(&asus_armoury.fw_attr_kset->kobj, &requires_fan_curve.attr);
+ if (err) {
+ pr_err("Failed to create requires_fan_curve attribute\n");
+ goto err_destroy_kset;
+ }
+
asus_armoury.mini_led_dev_id = 0;
if (armoury_has_devstate(ASUS_WMI_DEVID_MINI_LED_MODE))
asus_armoury.mini_led_dev_id = ASUS_WMI_DEVID_MINI_LED_MODE;
@@ -987,6 +1000,7 @@ static int asus_fw_attr_add(void)
if (asus_armoury.mini_led_dev_id)
sysfs_remove_group(&asus_armoury.fw_attr_kset->kobj, &mini_led_mode_attr_group);
err_remove_file:
+ sysfs_remove_file(&asus_armoury.fw_attr_kset->kobj, &requires_fan_curve.attr);
sysfs_remove_file(&asus_armoury.fw_attr_kset->kobj, &pending_reboot.attr);
err_destroy_kset:
kset_unregister(asus_armoury.fw_attr_kset);
@@ -1161,6 +1175,7 @@ static void __exit asus_fw_exit(void)
if (asus_armoury.mini_led_dev_id)
sysfs_remove_group(&asus_armoury.fw_attr_kset->kobj, &mini_led_mode_attr_group);
+ sysfs_remove_file(&asus_armoury.fw_attr_kset->kobj, &requires_fan_curve.attr);
sysfs_remove_file(&asus_armoury.fw_attr_kset->kobj, &pending_reboot.attr);
kset_unregister(asus_armoury.fw_attr_kset);
device_destroy(&firmware_attributes_class, MKDEV(0, 0));
--
2.54.0