Hi, On 6/30/23 07:35, Luke D. Jones wrote: > Expose various CPU and dGPU tunables that are available on many ASUS > ROG laptops. The tunables shown in sysfs will vary depending on the CPU > and dGPU vendor. > > All of these variables are write only and there is no easy way to find > what the defaults are. In general they seem to default to the max value > the vendor sets for the CPU and dGPU package - this is not the same as > the min/max writable value. Values written to these variables that are > beyond the capabilities of the CPU are ignored by the laptop. > > Signed-off-by: Luke D. Jones <luke@xxxxxxxxxx> Thanks, patch looks good to me: Reviewed-by: Hans de Goede <hdegoede@xxxxxxxxxx> (I'll fix the make htmldocs warning lkp spotted while merging this). Regards, Hans > --- > .../ABI/testing/sysfs-platform-asus-wmi | 58 ++++ > drivers/platform/x86/asus-wmi.c | 285 ++++++++++++++++++ > include/linux/platform_data/x86/asus-wmi.h | 9 + > 3 files changed, 352 insertions(+) > > diff --git a/Documentation/ABI/testing/sysfs-platform-asus-wmi b/Documentation/ABI/testing/sysfs-platform-asus-wmi > index 5624bdef49cb..caaccd28fabf 100644 > --- a/Documentation/ABI/testing/sysfs-platform-asus-wmi > +++ b/Documentation/ABI/testing/sysfs-platform-asus-wmi > @@ -126,3 +126,61 @@ Description: > Change the mini-LED mode: > * 0 - Single-zone, > * 1 - Multi-zone > + > +What: /sys/devices/platform/<platform>/ppt_pl1_spl > +Date: Jun 2023 > +KernelVersion: 6.5 > +Contact: "Luke Jones" <luke@xxxxxxxxxx> > +Description: > + Set the Package Power Target total of CPU: PL1 on Intel, SPL on AMD. > + Shown on Intel+Nvidia or AMD+Nvidia based systems. > + * min=5, max=250 > + > +What: /sys/devices/platform/<platform>/ppt_pl2_sppt > +Date: Jun 2023 > +KernelVersion: 6.5 > +Contact: "Luke Jones" <luke@xxxxxxxxxx> > +Description: > + Set the Slow Package Power Tracking Limit of CPU: PL2 on Intel, SPPT, > + on AMD. Shown on Intel+Nvidia or AMD+Nvidia based systems. > + * min=5, max=250 > + > +What: /sys/devices/platform/<platform>/ppt_fppt > +Date: Jun 2023 > +KernelVersion: 6.5 > +Contact: "Luke Jones" <luke@xxxxxxxxxx> > +Description: > + Set the Fast Package Power Tracking Limit of CPU. AMD+Nvidia only. > + * min=5, max=250 > + > +What: /sys/devices/platform/<platform>/ppt_apu_sppt > +Date: Jun 2023 > +KernelVersion: 6.5 > +Contact: "Luke Jones" <luke@xxxxxxxxxx> > +Description: > + Set the APU SPPT limit. Shown on full AMD systems only. > + * min=5, max=130 > + > +What: /sys/devices/platform/<platform>/ppt_platform_sppt > +Date: Jun 2023 > +KernelVersion: 6.5 > +Contact: "Luke Jones" <luke@xxxxxxxxxx> > +Description: > + Set the platform SPPT limit. Shown on full AMD systems only. > + * min=5, max=130 > + > +What: /sys/devices/platform/<platform>/nv_dynamic_boost > +Date: Jun 2023 > +KernelVersion: 6.5 > +Contact: "Luke Jones" <luke@xxxxxxxxxx> > +Description: > + Set the dynamic boost limit of the Nvidia dGPU: > + * min=5, max=25 > + > +What: /sys/devices/platform/<platform>/nv_temp_target > +Date: Jun 2023 > +KernelVersion: 6.5 > +Contact: "Luke Jones" <luke@xxxxxxxxxx> > +Description: > + Set the target temperature limit of the Nvidia dGPU: > + * min=75, max=87 > diff --git a/drivers/platform/x86/asus-wmi.c b/drivers/platform/x86/asus-wmi.c > index 1fc9e8afc2f3..d9a353081f91 100644 > --- a/drivers/platform/x86/asus-wmi.c > +++ b/drivers/platform/x86/asus-wmi.c > @@ -117,6 +117,16 @@ module_param(fnlock_default, bool, 0444); > /* Mask to determine if setting temperature or percentage */ > #define FAN_CURVE_PWM_MASK 0x04 > > +/* Limits for tunables available on ASUS ROG laptops */ > +#define PPT_TOTAL_MIN 5 > +#define PPT_TOTAL_MAX 250 > +#define PPT_CPU_MIN 5 > +#define PPT_CPU_MAX 130 > +#define NVIDIA_BOOST_MIN 5 > +#define NVIDIA_BOOST_MAX 25 > +#define NVIDIA_TEMP_MIN 75 > +#define NVIDIA_TEMP_MAX 87 > + > static const char * const ashs_ids[] = { "ATK4001", "ATK4002", NULL }; > > static int throttle_thermal_policy_write(struct asus_wmi *); > @@ -247,6 +257,15 @@ struct asus_wmi { > bool dgpu_disable_available; > bool gpu_mux_mode_available; > > + /* Tunables provided by ASUS for gaming laptops */ > + bool ppt_pl2_sppt_available; > + bool ppt_pl1_spl_available; > + bool ppt_apu_sppt_available; > + bool ppt_plat_sppt_available; > + bool ppt_fppt_available; > + bool nv_dyn_boost_available; > + bool nv_temp_tgt_available; > + > bool kbd_rgb_mode_available; > bool kbd_rgb_state_available; > > @@ -946,6 +965,244 @@ static const struct attribute_group *kbd_rgb_mode_groups[] = { > NULL, > }; > > +/* Tunable: PPT: Intel=PL1, AMD=SPPT *****************************************/ > +static ssize_t ppt_pl2_sppt_store(struct device *dev, > + struct device_attribute *attr, > + const char *buf, size_t count) > +{ > + int result, err; > + u32 value; > + > + struct asus_wmi *asus = dev_get_drvdata(dev); > + > + result = kstrtou32(buf, 10, &value); > + if (result) > + return result; > + > + if (value < PPT_TOTAL_MIN || value > PPT_TOTAL_MAX) > + return -EINVAL; > + > + err = asus_wmi_set_devstate(ASUS_WMI_DEVID_PPT_PL2_SPPT, value, &result); > + if (err) { > + pr_warn("Failed to set ppt_pl2_sppt: %d\n", err); > + return err; > + } > + > + if (result > 1) { > + pr_warn("Failed to set ppt_pl2_sppt (result): 0x%x\n", result); > + return -EIO; > + } > + > + sysfs_notify(&asus->platform_device->dev.kobj, NULL, "ppt_pl2_sppt"); > + > + return count; > +} > +static DEVICE_ATTR_WO(ppt_pl2_sppt); > + > +/* Tunable: PPT, Intel=PL1, AMD=SPL ******************************************/ > +static ssize_t ppt_pl1_spl_store(struct device *dev, > + struct device_attribute *attr, > + const char *buf, size_t count) > +{ > + int result, err; > + u32 value; > + > + struct asus_wmi *asus = dev_get_drvdata(dev); > + > + result = kstrtou32(buf, 10, &value); > + if (result) > + return result; > + > + if (value < PPT_TOTAL_MIN || value > PPT_TOTAL_MAX) > + return -EINVAL; > + > + err = asus_wmi_set_devstate(ASUS_WMI_DEVID_PPT_PL1_SPL, value, &result); > + if (err) { > + pr_warn("Failed to set ppt_pl1_spl: %d\n", err); > + return err; > + } > + > + if (result > 1) { > + pr_warn("Failed to set ppt_pl1_spl (result): 0x%x\n", result); > + return -EIO; > + } > + > + sysfs_notify(&asus->platform_device->dev.kobj, NULL, "ppt_pl1_spl"); > + > + return count; > +} > +static DEVICE_ATTR_WO(ppt_pl1_spl); > + > +/* Tunable: PPT APU FPPT ******************************************************/ > +static ssize_t ppt_fppt_store(struct device *dev, > + struct device_attribute *attr, > + const char *buf, size_t count) > +{ > + int result, err; > + u32 value; > + > + struct asus_wmi *asus = dev_get_drvdata(dev); > + > + result = kstrtou32(buf, 10, &value); > + if (result) > + return result; > + > + if (value < PPT_TOTAL_MIN || value > PPT_TOTAL_MAX) > + return -EINVAL; > + > + err = asus_wmi_set_devstate(ASUS_WMI_DEVID_PPT_FPPT, value, &result); > + if (err) { > + pr_warn("Failed to set ppt_fppt: %d\n", err); > + return err; > + } > + > + if (result > 1) { > + pr_warn("Failed to set ppt_fppt (result): 0x%x\n", result); > + return -EIO; > + } > + > + sysfs_notify(&asus->platform_device->dev.kobj, NULL, "ppt_fpu_sppt"); > + > + return count; > +} > +static DEVICE_ATTR_WO(ppt_fppt); > + > +/* Tunable: PPT APU SPPT *****************************************************/ > +static ssize_t ppt_apu_sppt_store(struct device *dev, > + struct device_attribute *attr, > + const char *buf, size_t count) > +{ > + int result, err; > + u32 value; > + > + struct asus_wmi *asus = dev_get_drvdata(dev); > + > + result = kstrtou32(buf, 10, &value); > + if (result) > + return result; > + > + if (value < PPT_CPU_MIN || value > PPT_CPU_MAX) > + return -EINVAL; > + > + err = asus_wmi_set_devstate(ASUS_WMI_DEVID_PPT_APU_SPPT, value, &result); > + if (err) { > + pr_warn("Failed to set ppt_apu_sppt: %d\n", err); > + return err; > + } > + > + if (result > 1) { > + pr_warn("Failed to set ppt_apu_sppt (result): 0x%x\n", result); > + return -EIO; > + } > + > + sysfs_notify(&asus->platform_device->dev.kobj, NULL, "ppt_apu_sppt"); > + > + return count; > +} > +static DEVICE_ATTR_WO(ppt_apu_sppt); > + > +/* Tunable: PPT platform SPPT ************************************************/ > +static ssize_t ppt_platform_sppt_store(struct device *dev, > + struct device_attribute *attr, > + const char *buf, size_t count) > +{ > + int result, err; > + u32 value; > + > + struct asus_wmi *asus = dev_get_drvdata(dev); > + > + result = kstrtou32(buf, 10, &value); > + if (result) > + return result; > + > + if (value < PPT_CPU_MIN || value > PPT_CPU_MAX) > + return -EINVAL; > + > + err = asus_wmi_set_devstate(ASUS_WMI_DEVID_PPT_PLAT_SPPT, value, &result); > + if (err) { > + pr_warn("Failed to set ppt_platform_sppt: %d\n", err); > + return err; > + } > + > + if (result > 1) { > + pr_warn("Failed to set ppt_platform_sppt (result): 0x%x\n", result); > + return -EIO; > + } > + > + sysfs_notify(&asus->platform_device->dev.kobj, NULL, "ppt_platform_sppt"); > + > + return count; > +} > +static DEVICE_ATTR_WO(ppt_platform_sppt); > + > +/* Tunable: NVIDIA dynamic boost *********************************************/ > +static ssize_t nv_dynamic_boost_store(struct device *dev, > + struct device_attribute *attr, > + const char *buf, size_t count) > +{ > + int result, err; > + u32 value; > + > + struct asus_wmi *asus = dev_get_drvdata(dev); > + > + result = kstrtou32(buf, 10, &value); > + if (result) > + return result; > + > + if (value < NVIDIA_BOOST_MIN || value > NVIDIA_BOOST_MAX) > + return -EINVAL; > + > + err = asus_wmi_set_devstate(ASUS_WMI_DEVID_NV_DYN_BOOST, value, &result); > + if (err) { > + pr_warn("Failed to set nv_dynamic_boost: %d\n", err); > + return err; > + } > + > + if (result > 1) { > + pr_warn("Failed to set nv_dynamic_boost (result): 0x%x\n", result); > + return -EIO; > + } > + > + sysfs_notify(&asus->platform_device->dev.kobj, NULL, "nv_dynamic_boost"); > + > + return count; > +} > +static DEVICE_ATTR_WO(nv_dynamic_boost); > + > +/* Tunable: NVIDIA temperature target ****************************************/ > +static ssize_t nv_temp_target_store(struct device *dev, > + struct device_attribute *attr, > + const char *buf, size_t count) > +{ > + int result, err; > + u32 value; > + > + struct asus_wmi *asus = dev_get_drvdata(dev); > + > + result = kstrtou32(buf, 10, &value); > + if (result) > + return result; > + > + if (value < NVIDIA_TEMP_MIN || value > NVIDIA_TEMP_MAX) > + return -EINVAL; > + > + err = asus_wmi_set_devstate(ASUS_WMI_DEVID_NV_THERM_TARGET, value, &result); > + if (err) { > + pr_warn("Failed to set nv_temp_target: %d\n", err); > + return err; > + } > + > + if (result > 1) { > + pr_warn("Failed to set nv_temp_target (result): 0x%x\n", result); > + return -EIO; > + } > + > + sysfs_notify(&asus->platform_device->dev.kobj, NULL, "nv_temp_target"); > + > + return count; > +} > +static DEVICE_ATTR_WO(nv_temp_target); > + > /* Battery ********************************************************************/ > > /* The battery maximum charging percentage */ > @@ -3775,6 +4032,13 @@ static struct attribute *platform_attributes[] = { > &dev_attr_als_enable.attr, > &dev_attr_fan_boost_mode.attr, > &dev_attr_throttle_thermal_policy.attr, > + &dev_attr_ppt_pl2_sppt.attr, > + &dev_attr_ppt_pl1_spl.attr, > + &dev_attr_ppt_fppt.attr, > + &dev_attr_ppt_apu_sppt.attr, > + &dev_attr_ppt_platform_sppt.attr, > + &dev_attr_nv_dynamic_boost.attr, > + &dev_attr_nv_temp_target.attr, > &dev_attr_panel_od.attr, > &dev_attr_mini_led_mode.attr, > NULL > @@ -3812,6 +4076,20 @@ static umode_t asus_sysfs_is_visible(struct kobject *kobj, > ok = asus->fan_boost_mode_available; > else if (attr == &dev_attr_throttle_thermal_policy.attr) > ok = asus->throttle_thermal_policy_available; > + else if (attr == &dev_attr_ppt_pl2_sppt.attr) > + ok = asus->ppt_pl2_sppt_available; > + else if (attr == &dev_attr_ppt_pl1_spl.attr) > + ok = asus->ppt_pl1_spl_available; > + else if (attr == &dev_attr_ppt_fppt.attr) > + ok = asus->ppt_fppt_available; > + else if (attr == &dev_attr_ppt_apu_sppt.attr) > + ok = asus->ppt_apu_sppt_available; > + else if (attr == &dev_attr_ppt_platform_sppt.attr) > + ok = asus->ppt_plat_sppt_available; > + else if (attr == &dev_attr_nv_dynamic_boost.attr) > + ok = asus->nv_dyn_boost_available; > + else if (attr == &dev_attr_nv_temp_target.attr) > + ok = asus->nv_temp_tgt_available; > else if (attr == &dev_attr_panel_od.attr) > ok = asus->panel_overdrive_available; > else if (attr == &dev_attr_mini_led_mode.attr) > @@ -4077,6 +4355,13 @@ static int asus_wmi_add(struct platform_device *pdev) > asus->gpu_mux_mode_available = asus_wmi_dev_is_present(asus, ASUS_WMI_DEVID_GPU_MUX); > asus->kbd_rgb_mode_available = asus_wmi_dev_is_present(asus, ASUS_WMI_DEVID_TUF_RGB_MODE); > asus->kbd_rgb_state_available = asus_wmi_dev_is_present(asus, ASUS_WMI_DEVID_TUF_RGB_STATE); > + asus->ppt_pl2_sppt_available = asus_wmi_dev_is_present(asus, ASUS_WMI_DEVID_PPT_PL2_SPPT); > + asus->ppt_pl1_spl_available = asus_wmi_dev_is_present(asus, ASUS_WMI_DEVID_PPT_PL1_SPL); > + asus->ppt_fppt_available = asus_wmi_dev_is_present(asus, ASUS_WMI_DEVID_PPT_FPPT); > + asus->ppt_apu_sppt_available = asus_wmi_dev_is_present(asus, ASUS_WMI_DEVID_PPT_APU_SPPT); > + asus->ppt_plat_sppt_available = asus_wmi_dev_is_present(asus, ASUS_WMI_DEVID_PPT_PLAT_SPPT); > + asus->nv_dyn_boost_available = asus_wmi_dev_is_present(asus, ASUS_WMI_DEVID_NV_DYN_BOOST); > + asus->nv_temp_tgt_available = asus_wmi_dev_is_present(asus, ASUS_WMI_DEVID_NV_THERM_TARGET); > asus->panel_overdrive_available = asus_wmi_dev_is_present(asus, ASUS_WMI_DEVID_PANEL_OD); > asus->mini_led_mode_available = asus_wmi_dev_is_present(asus, ASUS_WMI_DEVID_MINI_LED_MODE); > > diff --git a/include/linux/platform_data/x86/asus-wmi.h b/include/linux/platform_data/x86/asus-wmi.h > index ea80361ac6c7..16e99a1c37fc 100644 > --- a/include/linux/platform_data/x86/asus-wmi.h > +++ b/include/linux/platform_data/x86/asus-wmi.h > @@ -86,6 +86,15 @@ > #define ASUS_WMI_DEVID_GPU_FAN_CURVE 0x00110025 > #define ASUS_WMI_DEVID_MID_FAN_CURVE 0x00110032 > > +/* Tunables for AUS ROG laptops */ > +#define ASUS_WMI_DEVID_PPT_PL2_SPPT 0x001200A0 > +#define ASUS_WMI_DEVID_PPT_PL1_SPL 0x001200A3 > +#define ASUS_WMI_DEVID_PPT_APU_SPPT 0x001200B0 > +#define ASUS_WMI_DEVID_PPT_PLAT_SPPT 0x001200B1 > +#define ASUS_WMI_DEVID_PPT_FPPT 0x001200C1 > +#define ASUS_WMI_DEVID_NV_DYN_BOOST 0x001200C0 > +#define ASUS_WMI_DEVID_NV_THERM_TARGET 0x001200C2 > + > /* Power */ > #define ASUS_WMI_DEVID_PROCESSOR_STATE 0x00120012 >