diff mbox series

platform/x86: asus-wmi: Support setting AIPT modes

Message ID 20241020065051.1724435-1-srinivas.pandruvada@linux.intel.com (mailing list archive)
State Changes Requested, archived
Headers show
Series platform/x86: asus-wmi: Support setting AIPT modes | expand

Commit Message

srinivas pandruvada Oct. 20, 2024, 6:50 a.m. UTC
Some recent Asus laptops are supporting ASUS Intelligent Performance
Technology (AIPT). This solution allows users to have maximized CPU
performance in models with a chassis providing more thermal head room.
Refer to [1].

There are major performance issues when Linux is installed on these
laptops compared to Windows install. One such report is published for
Graphics benchmarks on Asus ASUS Zenbook S 14 with Lunar Lake
processors [2].

By default, these laptops are booting in "Whisper Mode" till OS power
management or tools change this to other AIPT mode. This "Whisper" mode
calls to set lower maximum and minimum RAPL (Running Average Power Limit)
via thermal tables. On Linux this leads to lower performance even when
platform power profile is "balanced". This "Whisper" mode should
correspond to "quiet" mode.

So, when AIPT is present change the default mode to "Standard" during
boot. Map the three platform power profile modes as follows:

Power Profile Mode      AIPT mode
-----------------------------------
quiet			Whisper
balanced		Standard
performance		Performance
------------------------------------

Here AIPT mode can be detected by checking presese of "FANL" method under
PNP HID "PNP0C14" and UID "ATK". If AIPT mode is present, this takes
precedence over the existing VIVO thermal policy. These modes are set
using "FANL" method.

Although this “FANL” method is not used in the Asus WMI driver, users
have used this method from user space [3] to set AIPT modes. Used this
as a reference.

Link: https://www.asus.com/content/laptop-asus-intelligent-performance-technology-aipt/ # [1]
Reported-by: Michael Larabel <Michael@phoronix.com>
Closes: https://www.phoronix.com/review/lunar-lake-xe2/5 # [2]
Link: https://github.com/dominiksalvet/asus-fan-control/issues/151 # [3]
Tested-by: Casey Bowman <casey.g.bowman@intel.com>
Signed-off-by: Srinivas Pandruvada <srinivas.pandruvada@linux.intel.com>
---
 drivers/platform/x86/asus-wmi.c | 93 +++++++++++++++++++++++++++++++--
 1 file changed, 89 insertions(+), 4 deletions(-)

Comments

Armin Wolf Oct. 20, 2024, 7:05 p.m. UTC | #1
Am 20.10.24 um 08:50 schrieb Srinivas Pandruvada:

> Some recent Asus laptops are supporting ASUS Intelligent Performance
> Technology (AIPT). This solution allows users to have maximized CPU
> performance in models with a chassis providing more thermal head room.
> Refer to [1].
>
> There are major performance issues when Linux is installed on these
> laptops compared to Windows install. One such report is published for
> Graphics benchmarks on Asus ASUS Zenbook S 14 with Lunar Lake
> processors [2].
>
> By default, these laptops are booting in "Whisper Mode" till OS power
> management or tools change this to other AIPT mode. This "Whisper" mode
> calls to set lower maximum and minimum RAPL (Running Average Power Limit)
> via thermal tables. On Linux this leads to lower performance even when
> platform power profile is "balanced". This "Whisper" mode should
> correspond to "quiet" mode.
>
> So, when AIPT is present change the default mode to "Standard" during
> boot. Map the three platform power profile modes as follows:
>
> Power Profile Mode      AIPT mode
> -----------------------------------
> quiet			Whisper
> balanced		Standard
> performance		Performance
> ------------------------------------
>
> Here AIPT mode can be detected by checking presese of "FANL" method under
> PNP HID "PNP0C14" and UID "ATK". If AIPT mode is present, this takes
> precedence over the existing VIVO thermal policy. These modes are set
> using "FANL" method.
>
> Although this “FANL” method is not used in the Asus WMI driver, users
> have used this method from user space [3] to set AIPT modes. Used this
> as a reference.
>
> Link: https://www.asus.com/content/laptop-asus-intelligent-performance-technology-aipt/ # [1]
> Reported-by: Michael Larabel <Michael@phoronix.com>
> Closes: https://www.phoronix.com/review/lunar-lake-xe2/5 # [2]
> Link: https://github.com/dominiksalvet/asus-fan-control/issues/151 # [3]
> Tested-by: Casey Bowman <casey.g.bowman@intel.com>
> Signed-off-by: Srinivas Pandruvada <srinivas.pandruvada@linux.intel.com>
> ---
>   drivers/platform/x86/asus-wmi.c | 93 +++++++++++++++++++++++++++++++--
>   1 file changed, 89 insertions(+), 4 deletions(-)
>
> diff --git a/drivers/platform/x86/asus-wmi.c b/drivers/platform/x86/asus-wmi.c
> index 7a48220b4f5a..06689d0f98c7 100644
> --- a/drivers/platform/x86/asus-wmi.c
> +++ b/drivers/platform/x86/asus-wmi.c
> @@ -100,6 +100,11 @@ module_param(fnlock_default, bool, 0444);
>   #define ASUS_THROTTLE_THERMAL_POLICY_SILENT_VIVO	1
>   #define ASUS_THROTTLE_THERMAL_POLICY_OVERBOOST_VIVO	2
>
> +#define AIPT_STANDARD				0
> +#define AIPT_WHISPER				1
> +#define AIPT_PERFORMANCE			2
> +#define AIPT_FULL_SPEED				3
> +
>   #define PLATFORM_PROFILE_MAX 2
>
>   #define USB_INTEL_XUSB2PR		0xD0
> @@ -333,6 +338,9 @@ struct asus_wmi {
>   	struct asus_wmi_debug debug;
>
>   	struct asus_wmi_driver *driver;
> +	acpi_handle acpi_mgmt_handle;
> +	int asus_aipt_mode;
> +	bool asus_aipt_present;
>   };
>
>   /* WMI ************************************************************************/
> @@ -3804,6 +3812,19 @@ static ssize_t throttle_thermal_policy_store(struct device *dev,
>   static DEVICE_ATTR_RW(throttle_thermal_policy);
>
>   /* Platform profile ***********************************************************/
> +static int asus_wmi_write_aipt_mode(struct asus_wmi *asus, int aipt_mode)
> +{
> +	int status;
> +
> +	status = acpi_execute_simple_method(asus->acpi_mgmt_handle, "FANL", aipt_mode);
> +	if (ACPI_FAILURE(status)) {
> +		acpi_handle_info(asus->acpi_mgmt_handle, "FANL execute failed\n");
> +		return -EIO;
> +	}
> +
> +	return 0;
> +}
> +
>   static int asus_wmi_platform_profile_to_vivo(struct asus_wmi *asus, int mode)
>   {
>   	bool vivo;
> @@ -3844,6 +3865,26 @@ static int asus_wmi_platform_profile_mode_from_vivo(struct asus_wmi *asus, int m
>   	return mode;
>   }
>
> +static int asus_wmi_aipt_platform_profile_get(struct asus_wmi *asus,
> +					      enum platform_profile_option *profile)
> +{
> +	switch (asus->asus_aipt_mode) {
> +	case AIPT_STANDARD:
> +		*profile = PLATFORM_PROFILE_BALANCED;
> +		break;
> +	case AIPT_PERFORMANCE:
> +		*profile = PLATFORM_PROFILE_PERFORMANCE;
> +		break;
> +	case AIPT_WHISPER:
> +		*profile = PLATFORM_PROFILE_QUIET;
> +		break;
> +	default:
> +		return -EINVAL;
> +	}
> +
> +	return 0;
> +}
> +
>   static int asus_wmi_platform_profile_get(struct platform_profile_handler *pprof,
>   					enum platform_profile_option *profile)
>   {
> @@ -3851,6 +3892,10 @@ static int asus_wmi_platform_profile_get(struct platform_profile_handler *pprof,
>   	int tp;
>
>   	asus = container_of(pprof, struct asus_wmi, platform_profile_handler);
> +
> +	if (asus->asus_aipt_present)
> +		return asus_wmi_aipt_platform_profile_get(asus, profile);
> +
>   	tp = asus->throttle_thermal_policy_mode;
>
>   	switch (asus_wmi_platform_profile_mode_from_vivo(asus, tp)) {
> @@ -3874,26 +3919,42 @@ static int asus_wmi_platform_profile_set(struct platform_profile_handler *pprof,
>   					enum platform_profile_option profile)
>   {
>   	struct asus_wmi *asus;
> -	int tp;
> +	int ret = 0, tp, aipt_mode;
>
>   	asus = container_of(pprof, struct asus_wmi, platform_profile_handler);
>
>   	switch (profile) {
>   	case PLATFORM_PROFILE_PERFORMANCE:
>   		tp = ASUS_THROTTLE_THERMAL_POLICY_OVERBOOST;
> +		aipt_mode = AIPT_PERFORMANCE;
>   		break;
>   	case PLATFORM_PROFILE_BALANCED:
>   		tp = ASUS_THROTTLE_THERMAL_POLICY_DEFAULT;
> +		aipt_mode = AIPT_STANDARD;
>   		break;
>   	case PLATFORM_PROFILE_QUIET:
>   		tp = ASUS_THROTTLE_THERMAL_POLICY_SILENT;
> +		aipt_mode = AIPT_WHISPER;
>   		break;
>   	default:
>   		return -EOPNOTSUPP;
>   	}
>
> -	asus->throttle_thermal_policy_mode = asus_wmi_platform_profile_to_vivo(asus, tp);
> -	return throttle_thermal_policy_write(asus);
> +	if (asus->asus_aipt_present) {
> +		ret = asus_wmi_write_aipt_mode(asus, aipt_mode);
> +		if (!ret) {
> +			asus->asus_aipt_mode = aipt_mode;
> +			goto skip_vivo;
> +		}
> +	}
> +
> +	if (asus->throttle_thermal_policy_dev) {
> +		asus->throttle_thermal_policy_mode = asus_wmi_platform_profile_to_vivo(asus, tp);
> +		ret = throttle_thermal_policy_write(asus);
> +	}
> +
> +skip_vivo:
> +	return ret;
>   }
>
>   static int platform_profile_setup(struct asus_wmi *asus)
> @@ -3905,7 +3966,7 @@ static int platform_profile_setup(struct asus_wmi *asus)
>   	 * Not an error if a component platform_profile relies on is unavailable
>   	 * so early return, skipping the setup of platform_profile.
>   	 */
> -	if (!asus->throttle_thermal_policy_dev)
> +	if (!asus->throttle_thermal_policy_dev && !asus->asus_aipt_present)
>   		return 0;
>
>   	dev_info(dev, "Using throttle_thermal_policy for platform_profile support\n");
> @@ -4538,6 +4599,7 @@ static int asus_wmi_sysfs_init(struct platform_device *device)
>   static int asus_wmi_platform_init(struct asus_wmi *asus)
>   {
>   	struct device *dev = &asus->platform_device->dev;
> +	struct acpi_device *adev;
>   	char *wmi_uid;
>   	int rv;
>
> @@ -4593,6 +4655,29 @@ static int asus_wmi_platform_init(struct asus_wmi *asus)
>   		asus_wmi_set_devstate(ASUS_WMI_DEVID_CWAP,
>   				      asus->driver->quirks->wapf, NULL);
>
> +	/*
> +	 * Check presence of Intelligent Performance Technology (AIPT).
> +	 * If present store acpi handle and set asus_aipt_present to true.
> +	 */
> +	adev = acpi_dev_get_first_match_dev("PNP0C14", "ATK", -1);

Is there really no way of changing the AIPT mode through the WMI interface?
I would prefer using the WMI interface if available, since the firmware might
assume that FANL is only called through the WMI interface.

Do you have a acpidump from a affected device?

Thanks,
Armin Wolf

> +	if (adev) {
> +		acpi_handle handle = acpi_device_handle(adev);
> +
> +		acpi_dev_put(adev);
> +
> +		if (!acpi_has_method(handle, "FANL"))
> +			return 0;
> +
> +		asus->acpi_mgmt_handle = handle;
> +		asus->asus_aipt_present = true;
> +		dev_info(dev, "ASUS Intelligent Performance Technology (AIPT) is present\n");
> +		/*
> +		 * Set the mode corresponding to default Linux platform power
> +		 * profile Balanced
> +		 */
> +		asus_wmi_write_aipt_mode(asus, AIPT_STANDARD);
> +	}
> +
>   	return 0;
>   }
>
srinivas pandruvada Oct. 20, 2024, 7:27 p.m. UTC | #2
> > 

[...]

> > +	adev = acpi_dev_get_first_match_dev("PNP0C14", "ATK", -1);
> 
> Is there really no way of changing the AIPT mode through the WMI
> interface?
> I would prefer using the WMI interface if available, since the
> firmware might
> assume that FANL is only called through the WMI interface.
> 
I wish the same. Didn't find any. Asus is aware of this change which I
submitted, they didn't suggest that there is alternative. 

> Do you have a acpidump from a affected device?
> 
Will send you.

Thanks,
Srinivas

> Thanks,
> Armin Wolf
> 
> > +	if (adev) {
> > +		acpi_handle handle = acpi_device_handle(adev);
> > +
> > +		acpi_dev_put(adev);
> > +
> > +		if (!acpi_has_method(handle, "FANL"))
> > +			return 0;
> > +
> > +		asus->acpi_mgmt_handle = handle;
> > +		asus->asus_aipt_present = true;
> > +		dev_info(dev, "ASUS Intelligent Performance
> > Technology (AIPT) is present\n");
> > +		/*
> > +		 * Set the mode corresponding to default Linux
> > platform power
> > +		 * profile Balanced
> > +		 */
> > +		asus_wmi_write_aipt_mode(asus, AIPT_STANDARD);
> > +	}
> > +
> >   	return 0;
> >   }
> >
Armin Wolf Oct. 20, 2024, 7:42 p.m. UTC | #3
Am 20.10.24 um 21:05 schrieb Armin Wolf:

> Am 20.10.24 um 08:50 schrieb Srinivas Pandruvada:
>
>> Some recent Asus laptops are supporting ASUS Intelligent Performance
>> Technology (AIPT). This solution allows users to have maximized CPU
>> performance in models with a chassis providing more thermal head room.
>> Refer to [1].
>>
>> There are major performance issues when Linux is installed on these
>> laptops compared to Windows install. One such report is published for
>> Graphics benchmarks on Asus ASUS Zenbook S 14 with Lunar Lake
>> processors [2].
>>
>> By default, these laptops are booting in "Whisper Mode" till OS power
>> management or tools change this to other AIPT mode. This "Whisper" mode
>> calls to set lower maximum and minimum RAPL (Running Average Power
>> Limit)
>> via thermal tables. On Linux this leads to lower performance even when
>> platform power profile is "balanced". This "Whisper" mode should
>> correspond to "quiet" mode.
>>
>> So, when AIPT is present change the default mode to "Standard" during
>> boot. Map the three platform power profile modes as follows:
>>
>> Power Profile Mode      AIPT mode
>> -----------------------------------
>> quiet            Whisper
>> balanced        Standard
>> performance        Performance
>> ------------------------------------
>>
>> Here AIPT mode can be detected by checking presese of "FANL" method
>> under
>> PNP HID "PNP0C14" and UID "ATK". If AIPT mode is present, this takes
>> precedence over the existing VIVO thermal policy. These modes are set
>> using "FANL" method.
>>
>> Although this “FANL” method is not used in the Asus WMI driver, users
>> have used this method from user space [3] to set AIPT modes. Used this
>> as a reference.
>>
>> Link:
>> https://www.asus.com/content/laptop-asus-intelligent-performance-technology-aipt/
>> # [1]
>> Reported-by: Michael Larabel <Michael@phoronix.com>
>> Closes: https://www.phoronix.com/review/lunar-lake-xe2/5 # [2]
>> Link: https://github.com/dominiksalvet/asus-fan-control/issues/151 # [3]
>> Tested-by: Casey Bowman <casey.g.bowman@intel.com>
>> Signed-off-by: Srinivas Pandruvada <srinivas.pandruvada@linux.intel.com>
>> ---
>>   drivers/platform/x86/asus-wmi.c | 93 +++++++++++++++++++++++++++++++--
>>   1 file changed, 89 insertions(+), 4 deletions(-)
>>
>> diff --git a/drivers/platform/x86/asus-wmi.c
>> b/drivers/platform/x86/asus-wmi.c
>> index 7a48220b4f5a..06689d0f98c7 100644
>> --- a/drivers/platform/x86/asus-wmi.c
>> +++ b/drivers/platform/x86/asus-wmi.c
>> @@ -100,6 +100,11 @@ module_param(fnlock_default, bool, 0444);
>>   #define ASUS_THROTTLE_THERMAL_POLICY_SILENT_VIVO    1
>>   #define ASUS_THROTTLE_THERMAL_POLICY_OVERBOOST_VIVO    2
>>
>> +#define AIPT_STANDARD                0
>> +#define AIPT_WHISPER                1
>> +#define AIPT_PERFORMANCE            2
>> +#define AIPT_FULL_SPEED                3
>> +
>>   #define PLATFORM_PROFILE_MAX 2
>>
>>   #define USB_INTEL_XUSB2PR        0xD0
>> @@ -333,6 +338,9 @@ struct asus_wmi {
>>       struct asus_wmi_debug debug;
>>
>>       struct asus_wmi_driver *driver;
>> +    acpi_handle acpi_mgmt_handle;
>> +    int asus_aipt_mode;
>> +    bool asus_aipt_present;
>>   };
>>
>>   /* WMI
>> ************************************************************************/
>> @@ -3804,6 +3812,19 @@ static ssize_t
>> throttle_thermal_policy_store(struct device *dev,
>>   static DEVICE_ATTR_RW(throttle_thermal_policy);
>>
>>   /* Platform profile
>> ***********************************************************/
>> +static int asus_wmi_write_aipt_mode(struct asus_wmi *asus, int
>> aipt_mode)
>> +{
>> +    int status;
>> +
>> +    status = acpi_execute_simple_method(asus->acpi_mgmt_handle,
>> "FANL", aipt_mode);
>> +    if (ACPI_FAILURE(status)) {
>> +        acpi_handle_info(asus->acpi_mgmt_handle, "FANL execute
>> failed\n");
>> +        return -EIO;
>> +    }
>> +
>> +    return 0;
>> +}
>> +
>>   static int asus_wmi_platform_profile_to_vivo(struct asus_wmi *asus,
>> int mode)
>>   {
>>       bool vivo;
>> @@ -3844,6 +3865,26 @@ static int
>> asus_wmi_platform_profile_mode_from_vivo(struct asus_wmi *asus, int m
>>       return mode;
>>   }
>>
>> +static int asus_wmi_aipt_platform_profile_get(struct asus_wmi *asus,
>> +                          enum platform_profile_option *profile)
>> +{
>> +    switch (asus->asus_aipt_mode) {
>> +    case AIPT_STANDARD:
>> +        *profile = PLATFORM_PROFILE_BALANCED;
>> +        break;
>> +    case AIPT_PERFORMANCE:
>> +        *profile = PLATFORM_PROFILE_PERFORMANCE;
>> +        break;
>> +    case AIPT_WHISPER:
>> +        *profile = PLATFORM_PROFILE_QUIET;
>> +        break;
>> +    default:
>> +        return -EINVAL;
>> +    }
>> +
>> +    return 0;
>> +}
>> +
>>   static int asus_wmi_platform_profile_get(struct
>> platform_profile_handler *pprof,
>>                       enum platform_profile_option *profile)
>>   {
>> @@ -3851,6 +3892,10 @@ static int
>> asus_wmi_platform_profile_get(struct platform_profile_handler *pprof,
>>       int tp;
>>
>>       asus = container_of(pprof, struct asus_wmi,
>> platform_profile_handler);
>> +
>> +    if (asus->asus_aipt_present)
>> +        return asus_wmi_aipt_platform_profile_get(asus, profile);
>> +
>>       tp = asus->throttle_thermal_policy_mode;
>>
>>       switch (asus_wmi_platform_profile_mode_from_vivo(asus, tp)) {
>> @@ -3874,26 +3919,42 @@ static int
>> asus_wmi_platform_profile_set(struct platform_profile_handler *pprof,
>>                       enum platform_profile_option profile)
>>   {
>>       struct asus_wmi *asus;
>> -    int tp;
>> +    int ret = 0, tp, aipt_mode;
>>
>>       asus = container_of(pprof, struct asus_wmi,
>> platform_profile_handler);
>>
>>       switch (profile) {
>>       case PLATFORM_PROFILE_PERFORMANCE:
>>           tp = ASUS_THROTTLE_THERMAL_POLICY_OVERBOOST;
>> +        aipt_mode = AIPT_PERFORMANCE;
>>           break;
>>       case PLATFORM_PROFILE_BALANCED:
>>           tp = ASUS_THROTTLE_THERMAL_POLICY_DEFAULT;
>> +        aipt_mode = AIPT_STANDARD;
>>           break;
>>       case PLATFORM_PROFILE_QUIET:
>>           tp = ASUS_THROTTLE_THERMAL_POLICY_SILENT;
>> +        aipt_mode = AIPT_WHISPER;
>>           break;
>>       default:
>>           return -EOPNOTSUPP;
>>       }
>>
>> -    asus->throttle_thermal_policy_mode =
>> asus_wmi_platform_profile_to_vivo(asus, tp);
>> -    return throttle_thermal_policy_write(asus);
>> +    if (asus->asus_aipt_present) {
>> +        ret = asus_wmi_write_aipt_mode(asus, aipt_mode);
>> +        if (!ret) {
>> +            asus->asus_aipt_mode = aipt_mode;
>> +            goto skip_vivo;
>> +        }
>> +    }
>> +
>> +    if (asus->throttle_thermal_policy_dev) {
>> +        asus->throttle_thermal_policy_mode =
>> asus_wmi_platform_profile_to_vivo(asus, tp);
>> +        ret = throttle_thermal_policy_write(asus);
>> +    }
>> +
>> +skip_vivo:
>> +    return ret;
>>   }
>>
>>   static int platform_profile_setup(struct asus_wmi *asus)
>> @@ -3905,7 +3966,7 @@ static int platform_profile_setup(struct
>> asus_wmi *asus)
>>        * Not an error if a component platform_profile relies on is
>> unavailable
>>        * so early return, skipping the setup of platform_profile.
>>        */
>> -    if (!asus->throttle_thermal_policy_dev)
>> +    if (!asus->throttle_thermal_policy_dev && !asus->asus_aipt_present)
>>           return 0;
>>
>>       dev_info(dev, "Using throttle_thermal_policy for
>> platform_profile support\n");
>> @@ -4538,6 +4599,7 @@ static int asus_wmi_sysfs_init(struct
>> platform_device *device)
>>   static int asus_wmi_platform_init(struct asus_wmi *asus)
>>   {
>>       struct device *dev = &asus->platform_device->dev;
>> +    struct acpi_device *adev;
>>       char *wmi_uid;
>>       int rv;
>>
>> @@ -4593,6 +4655,29 @@ static int asus_wmi_platform_init(struct
>> asus_wmi *asus)
>>           asus_wmi_set_devstate(ASUS_WMI_DEVID_CWAP,
>>                         asus->driver->quirks->wapf, NULL);
>>
>> +    /*
>> +     * Check presence of Intelligent Performance Technology (AIPT).
>> +     * If present store acpi handle and set asus_aipt_present to true.
>> +     */
>> +    adev = acpi_dev_get_first_match_dev("PNP0C14", "ATK", -1);
>
> Is there really no way of changing the AIPT mode through the WMI
> interface?
> I would prefer using the WMI interface if available, since the
> firmware might
> assume that FANL is only called through the WMI interface.
>
> Do you have a acpidump from a affected device?
>
> Thanks,
> Armin Wolf
>
I found a acpidump from a ASUS device with a matching FANL method. It seems that this method
can indeed be called using the WMI interface using the DEVS() WMI method:

[WmiMethodId(1398162756), Implemented] void DEVS([in] uint32 Device_ID, [in] uint32 Control_status, [out] uint32 result);

If Device_ID is 0x00110019, then Control_status is passed to the FANL ACPI method.

It also seems that support for AIPT can be queried using the DSTS() WMI method:

[WmiMethodId(1398035268), Implemented] void DSTS([in] uint32 Device_ID, [out] uint32 device_status);

Using Device_ID 0x00110019, the returned device status seems to contain the following information:

- 16-bit current AIPT mode
- 4-bit unknown value (possible values 2, 3 and 7, maybe number of supported modes or some kind of bitmap?)
- 1-bit with is set when (GGIV (0x0907000C) == One) is true

Maybe you can figure out the meaning of the 4-bit value so that the number of supported states can be
detected automatically. For interacting with the DEVS() and DSTS() WMI method, please use the driver-provided
helper methods if suitable.

Thanks,
Armin Wolf

>> +    if (adev) {
>> +        acpi_handle handle = acpi_device_handle(adev);
>> +
>> +        acpi_dev_put(adev);
>> +
>> +        if (!acpi_has_method(handle, "FANL"))
>> +            return 0;
>> +
>> +        asus->acpi_mgmt_handle = handle;
>> +        asus->asus_aipt_present = true;
>> +        dev_info(dev, "ASUS Intelligent Performance Technology
>> (AIPT) is present\n");
>> +        /*
>> +         * Set the mode corresponding to default Linux platform power
>> +         * profile Balanced
>> +         */
>> +        asus_wmi_write_aipt_mode(asus, AIPT_STANDARD);
>> +    }
>> +
>>       return 0;
>>   }
>>
>
Armin Wolf Oct. 20, 2024, 7:54 p.m. UTC | #4
Am 20.10.24 um 21:27 schrieb srinivas pandruvada:

> [...]
>
>>> +	adev = acpi_dev_get_first_match_dev("PNP0C14", "ATK", -1);
>> Is there really no way of changing the AIPT mode through the WMI
>> interface?
>> I would prefer using the WMI interface if available, since the
>> firmware might
>> assume that FANL is only called through the WMI interface.
>>
> I wish the same. Didn't find any. Asus is aware of this change which I
> submitted, they didn't suggest that there is alternative.
>
>> Do you have a acpidump from a affected device?
>>
> Will send you.
>
> Thanks,
> Srinivas

Thanks,

the return value of DSTS() on your device contains:

- 8-bit current AIPT mode
- 8-bit nothing
- 8-bit constant 0x07
- 8-bit constant 0x0a

Maybe you can try to find out more about the unknown constants. For the rest, you can use
the helper functions provided by the driver.

Thanks,
Armin Wolf

>> Thanks,
>> Armin Wolf
>>
>>> +	if (adev) {
>>> +		acpi_handle handle = acpi_device_handle(adev);
>>> +
>>> +		acpi_dev_put(adev);
>>> +
>>> +		if (!acpi_has_method(handle, "FANL"))
>>> +			return 0;
>>> +
>>> +		asus->acpi_mgmt_handle = handle;
>>> +		asus->asus_aipt_present = true;
>>> +		dev_info(dev, "ASUS Intelligent Performance
>>> Technology (AIPT) is present\n");
>>> +		/*
>>> +		 * Set the mode corresponding to default Linux
>>> platform power
>>> +		 * profile Balanced
>>> +		 */
>>> +		asus_wmi_write_aipt_mode(asus, AIPT_STANDARD);
>>> +	}
>>> +
>>>    	return 0;
>>>    }
>>>
>
srinivas pandruvada Oct. 20, 2024, 10:10 p.m. UTC | #5
On Sun, 2024-10-20 at 21:54 +0200, Armin Wolf wrote:
> Am 20.10.24 um 21:27 schrieb srinivas pandruvada:
> 
> > [...]
> > 
> > > > +	adev = acpi_dev_get_first_match_dev("PNP0C14", "ATK",
> > > > -1);
> > > Is there really no way of changing the AIPT mode through the WMI
> > > interface?
> > > I would prefer using the WMI interface if available, since the
> > > firmware might
> > > assume that FANL is only called through the WMI interface.
> > > 
> > I wish the same. Didn't find any. Asus is aware of this change
> > which I
> > submitted, they didn't suggest that there is alternative.
> > 
> > > Do you have a acpidump from a affected device?
> > > 
> > Will send you.
> > 
> > Thanks,
> > Srinivas
> 
> Thanks,
> 
> the return value of DSTS() on your device contains:
> 
> - 8-bit current AIPT mode
> - 8-bit nothing
> - 8-bit constant 0x07
> - 8-bit constant 0x0a
> 
> Maybe you can try to find out more about the unknown constants. For
> the rest, you can use
> the helper functions provided by the driver.

Thanks for looking into this. I will get help from Asus.

-Srinivas

> 
> Thanks,
> Armin Wolf
> 
> > > Thanks,
> > > Armin Wolf
> > > 
> > > > +	if (adev) {
> > > > +		acpi_handle handle = acpi_device_handle(adev);
> > > > +
> > > > +		acpi_dev_put(adev);
> > > > +
> > > > +		if (!acpi_has_method(handle, "FANL"))
> > > > +			return 0;
> > > > +
> > > > +		asus->acpi_mgmt_handle = handle;
> > > > +		asus->asus_aipt_present = true;
> > > > +		dev_info(dev, "ASUS Intelligent Performance
> > > > Technology (AIPT) is present\n");
> > > > +		/*
> > > > +		 * Set the mode corresponding to default Linux
> > > > platform power
> > > > +		 * profile Balanced
> > > > +		 */
> > > > +		asus_wmi_write_aipt_mode(asus, AIPT_STANDARD);
> > > > +	}
> > > > +
> > > >    	return 0;
> > > >    }
> > > > 
> >
Luke Jones Oct. 23, 2024, 8:15 a.m. UTC | #6
On Sun, 20 Oct 2024, at 9:05 PM, Armin Wolf wrote:
> Am 20.10.24 um 08:50 schrieb Srinivas Pandruvada:
>
>> Some recent Asus laptops are supporting ASUS Intelligent Performance
>> Technology (AIPT). This solution allows users to have maximized CPU
>> performance in models with a chassis providing more thermal head room.
>> Refer to [1].
>>
>> There are major performance issues when Linux is installed on these
>> laptops compared to Windows install. One such report is published for
>> Graphics benchmarks on Asus ASUS Zenbook S 14 with Lunar Lake
>> processors [2].
>>
>> By default, these laptops are booting in "Whisper Mode" till OS power
>> management or tools change this to other AIPT mode. This "Whisper" mode
>> calls to set lower maximum and minimum RAPL (Running Average Power Limit)
>> via thermal tables. On Linux this leads to lower performance even when
>> platform power profile is "balanced". This "Whisper" mode should
>> correspond to "quiet" mode.
>>
>> So, when AIPT is present change the default mode to "Standard" during
>> boot. Map the three platform power profile modes as follows:
>>
>> Power Profile Mode      AIPT mode
>> -----------------------------------
>> quiet			Whisper
>> balanced		Standard
>> performance		Performance
>> ------------------------------------
>>
>> Here AIPT mode can be detected by checking presese of "FANL" method under
>> PNP HID "PNP0C14" and UID "ATK". If AIPT mode is present, this takes
>> precedence over the existing VIVO thermal policy. These modes are set
>> using "FANL" method.
>>
>> Although this “FANL” method is not used in the Asus WMI driver, users
>> have used this method from user space [3] to set AIPT modes. Used this
>> as a reference.
>>
>> Link: https://www.asus.com/content/laptop-asus-intelligent-performance-technology-aipt/ # [1]
>> Reported-by: Michael Larabel <Michael@phoronix.com>
>> Closes: https://www.phoronix.com/review/lunar-lake-xe2/5 # [2]
>> Link: https://github.com/dominiksalvet/asus-fan-control/issues/151 # [3]
>> Tested-by: Casey Bowman <casey.g.bowman@intel.com>
>> Signed-off-by: Srinivas Pandruvada <srinivas.pandruvada@linux.intel.com>
>> ---
>>   drivers/platform/x86/asus-wmi.c | 93 +++++++++++++++++++++++++++++++--
>>   1 file changed, 89 insertions(+), 4 deletions(-)
>>
>> diff --git a/drivers/platform/x86/asus-wmi.c b/drivers/platform/x86/asus-wmi.c
>> index 7a48220b4f5a..06689d0f98c7 100644
>> --- a/drivers/platform/x86/asus-wmi.c
>> +++ b/drivers/platform/x86/asus-wmi.c
>> @@ -100,6 +100,11 @@ module_param(fnlock_default, bool, 0444);
>>   #define ASUS_THROTTLE_THERMAL_POLICY_SILENT_VIVO	1
>>   #define ASUS_THROTTLE_THERMAL_POLICY_OVERBOOST_VIVO	2
>>
>> +#define AIPT_STANDARD				0
>> +#define AIPT_WHISPER				1
>> +#define AIPT_PERFORMANCE			2
>> +#define AIPT_FULL_SPEED				3
>> +
>>   #define PLATFORM_PROFILE_MAX 2
>>
>>   #define USB_INTEL_XUSB2PR		0xD0
>> @@ -333,6 +338,9 @@ struct asus_wmi {
>>   	struct asus_wmi_debug debug;
>>
>>   	struct asus_wmi_driver *driver;
>> +	acpi_handle acpi_mgmt_handle;
>> +	int asus_aipt_mode;
>> +	bool asus_aipt_present;
>>   };
>>
>>   /* WMI ************************************************************************/
>> @@ -3804,6 +3812,19 @@ static ssize_t throttle_thermal_policy_store(struct device *dev,
>>   static DEVICE_ATTR_RW(throttle_thermal_policy);
>>
>>   /* Platform profile ***********************************************************/
>> +static int asus_wmi_write_aipt_mode(struct asus_wmi *asus, int aipt_mode)
>> +{
>> +	int status;
>> +
>> +	status = acpi_execute_simple_method(asus->acpi_mgmt_handle, "FANL", aipt_mode);
>> +	if (ACPI_FAILURE(status)) {
>> +		acpi_handle_info(asus->acpi_mgmt_handle, "FANL execute failed\n");
>> +		return -EIO;
>> +	}
>> +
>> +	return 0;
>> +}
>> +
>>   static int asus_wmi_platform_profile_to_vivo(struct asus_wmi *asus, int mode)
>>   {
>>   	bool vivo;
>> @@ -3844,6 +3865,26 @@ static int asus_wmi_platform_profile_mode_from_vivo(struct asus_wmi *asus, int m
>>   	return mode;
>>   }
>>
>> +static int asus_wmi_aipt_platform_profile_get(struct asus_wmi *asus,
>> +					      enum platform_profile_option *profile)
>> +{
>> +	switch (asus->asus_aipt_mode) {
>> +	case AIPT_STANDARD:
>> +		*profile = PLATFORM_PROFILE_BALANCED;
>> +		break;
>> +	case AIPT_PERFORMANCE:
>> +		*profile = PLATFORM_PROFILE_PERFORMANCE;
>> +		break;
>> +	case AIPT_WHISPER:
>> +		*profile = PLATFORM_PROFILE_QUIET;
>> +		break;
>> +	default:
>> +		return -EINVAL;
>> +	}
>> +
>> +	return 0;
>> +}
>> +
>>   static int asus_wmi_platform_profile_get(struct platform_profile_handler *pprof,
>>   					enum platform_profile_option *profile)
>>   {
>> @@ -3851,6 +3892,10 @@ static int asus_wmi_platform_profile_get(struct platform_profile_handler *pprof,
>>   	int tp;
>>
>>   	asus = container_of(pprof, struct asus_wmi, platform_profile_handler);
>> +
>> +	if (asus->asus_aipt_present)
>> +		return asus_wmi_aipt_platform_profile_get(asus, profile);
>> +
>>   	tp = asus->throttle_thermal_policy_mode;
>>
>>   	switch (asus_wmi_platform_profile_mode_from_vivo(asus, tp)) {
>> @@ -3874,26 +3919,42 @@ static int asus_wmi_platform_profile_set(struct platform_profile_handler *pprof,
>>   					enum platform_profile_option profile)
>>   {
>>   	struct asus_wmi *asus;
>> -	int tp;
>> +	int ret = 0, tp, aipt_mode;
>>
>>   	asus = container_of(pprof, struct asus_wmi, platform_profile_handler);
>>
>>   	switch (profile) {
>>   	case PLATFORM_PROFILE_PERFORMANCE:
>>   		tp = ASUS_THROTTLE_THERMAL_POLICY_OVERBOOST;
>> +		aipt_mode = AIPT_PERFORMANCE;
>>   		break;
>>   	case PLATFORM_PROFILE_BALANCED:
>>   		tp = ASUS_THROTTLE_THERMAL_POLICY_DEFAULT;
>> +		aipt_mode = AIPT_STANDARD;
>>   		break;
>>   	case PLATFORM_PROFILE_QUIET:
>>   		tp = ASUS_THROTTLE_THERMAL_POLICY_SILENT;
>> +		aipt_mode = AIPT_WHISPER;
>>   		break;
>>   	default:
>>   		return -EOPNOTSUPP;
>>   	}
>>
>> -	asus->throttle_thermal_policy_mode = asus_wmi_platform_profile_to_vivo(asus, tp);
>> -	return throttle_thermal_policy_write(asus);
>> +	if (asus->asus_aipt_present) {
>> +		ret = asus_wmi_write_aipt_mode(asus, aipt_mode);
>> +		if (!ret) {
>> +			asus->asus_aipt_mode = aipt_mode;
>> +			goto skip_vivo;
>> +		}
>> +	}
>> +
>> +	if (asus->throttle_thermal_policy_dev) {
>> +		asus->throttle_thermal_policy_mode = asus_wmi_platform_profile_to_vivo(asus, tp);
>> +		ret = throttle_thermal_policy_write(asus);
>> +	}
>> +
>> +skip_vivo:
>> +	return ret;
>>   }
>>
>>   static int platform_profile_setup(struct asus_wmi *asus)
>> @@ -3905,7 +3966,7 @@ static int platform_profile_setup(struct asus_wmi *asus)
>>   	 * Not an error if a component platform_profile relies on is unavailable
>>   	 * so early return, skipping the setup of platform_profile.
>>   	 */
>> -	if (!asus->throttle_thermal_policy_dev)
>> +	if (!asus->throttle_thermal_policy_dev && !asus->asus_aipt_present)
>>   		return 0;
>>
>>   	dev_info(dev, "Using throttle_thermal_policy for platform_profile support\n");
>> @@ -4538,6 +4599,7 @@ static int asus_wmi_sysfs_init(struct platform_device *device)
>>   static int asus_wmi_platform_init(struct asus_wmi *asus)
>>   {
>>   	struct device *dev = &asus->platform_device->dev;
>> +	struct acpi_device *adev;
>>   	char *wmi_uid;
>>   	int rv;
>>
>> @@ -4593,6 +4655,29 @@ static int asus_wmi_platform_init(struct asus_wmi *asus)
>>   		asus_wmi_set_devstate(ASUS_WMI_DEVID_CWAP,
>>   				      asus->driver->quirks->wapf, NULL);
>>
>> +	/*
>> +	 * Check presence of Intelligent Performance Technology (AIPT).
>> +	 * If present store acpi handle and set asus_aipt_present to true.
>> +	 */
>> +	adev = acpi_dev_get_first_match_dev("PNP0C14", "ATK", -1);
>
> Is there really no way of changing the AIPT mode through the WMI interface?
> I would prefer using the WMI interface if available, since the firmware might
> assume that FANL is only called through the WMI interface.
>
> Do you have a acpidump from a affected device?
>
> Thanks,
> Armin Wolf
>
>> +	if (adev) {
>> +		acpi_handle handle = acpi_device_handle(adev);
>> +
>> +		acpi_dev_put(adev);
>> +
>> +		if (!acpi_has_method(handle, "FANL"))
>> +			return 0;

Quite a few laptops have this method available, but may not actually do anything. Such as the following:

FX517ZM-dsdt.dsl
92885:        Method (FANL, 1, Serialized)
92886-        {
92887-            Return (One)
92888-        }

While this one does (zenbook duo):

UX8402.dsl
88837:                Method (FANL, 1, Serialized)
88838-                {
88839-                    ODV0 = Arg0
88840-                    If ((^^PC00.PEG1.PXP._STA == One))
--
89041:                    Return (FANL (IIA0))
89042-                }
89043-
89044-                If ((Local0 == 0x4647574D))
--
89604:                        FANL (IIA1)
89605-                        Return (One)
89606-                    }
89607-

I've discovered the majority of WMI methods, you can see them here: https://gitlab.com/asus-linux/reverse-engineering/-/blob/master/WMI_SPEC.md?ref_type=heads

There is a "whisper mode" WMI  method, but I've not done much around it.

I also have a large collection of DSL if that is helpful https://gitlab.com/asus-linux/reverse-engineering/-/tree/master/dsl-collection?ref_type=heads

It seems that because I have access only to the ROG dlls at this time I may have missed the WMI method: 0x00110019, this is likely what you need as it gets FANF, and sets FANL

❯ rg 0x00110019 -B3 -A3 UX8402.dsl 
89281-                        Return (0x00010000)
89282-                    }
89283-
89284:                    If ((IIA0 == 0x00110019))
89285-                    {
89286-                        Local0 = FANF /* \_SB_.FANF */
89287-                        Local1 = 0x00070000
--
89599-                        Return (One)
89600-                    }
89601-
89602:                    If ((IIA0 == 0x00110019))
89603-                    {
89604-                        FANL (IIA1)
89605-                        Return (One)

Hopefully this is helpful,

Regards,
Luke.

P.S: If any info is discovered that I am lacking in my repo it would be highly appreciated if a PR added it.

>> +		asus->acpi_mgmt_handle = handle;
>> +		asus->asus_aipt_present = true;
>> +		dev_info(dev, "ASUS Intelligent Performance Technology (AIPT) is present\n");
>> +		/*
>> +		 * Set the mode corresponding to default Linux platform power
>> +		 * profile Balanced
>> +		 */
>> +		asus_wmi_write_aipt_mode(asus, AIPT_STANDARD);
>> +	}
>> +
>>   	return 0;
>>   }
>>
Mohamed Ghanmi Oct. 23, 2024, 2:44 p.m. UTC | #7
Hello !
On Sun, Oct 20, 2024 at 09:42:45PM +0200, Armin Wolf wrote:
> Am 20.10.24 um 21:05 schrieb Armin Wolf:
> 
> > Am 20.10.24 um 08:50 schrieb Srinivas Pandruvada:
> > 
> > > Some recent Asus laptops are supporting ASUS Intelligent Performance
> > > Technology (AIPT). This solution allows users to have maximized CPU
> > > performance in models with a chassis providing more thermal head room.
> > > Refer to [1].
> > > 
> > > There are major performance issues when Linux is installed on these
> > > laptops compared to Windows install. One such report is published for
> > > Graphics benchmarks on Asus ASUS Zenbook S 14 with Lunar Lake
> > > processors [2].
> > > 
> > > By default, these laptops are booting in "Whisper Mode" till OS power
> > > management or tools change this to other AIPT mode. This "Whisper" mode
> > > calls to set lower maximum and minimum RAPL (Running Average Power
> > > Limit)
> > > via thermal tables. On Linux this leads to lower performance even when
> > > platform power profile is "balanced". This "Whisper" mode should
> > > correspond to "quiet" mode.
> > > 
> > > So, when AIPT is present change the default mode to "Standard" during
> > > boot. Map the three platform power profile modes as follows:
> > > 
> > > Power Profile Mode      AIPT mode
> > > -----------------------------------
> > > quiet            Whisper
> > > balanced        Standard
> > > performance        Performance
> > > ------------------------------------
> > > 
> > > Here AIPT mode can be detected by checking presese of "FANL" method
> > > under
> > > PNP HID "PNP0C14" and UID "ATK". If AIPT mode is present, this takes
> > > precedence over the existing VIVO thermal policy. These modes are set
> > > using "FANL" method.
> > > 
> > > Although this “FANL” method is not used in the Asus WMI driver, users
> > > have used this method from user space [3] to set AIPT modes. Used this
> > > as a reference.
> > > 
> > > Link:
> > > https://www.asus.com/content/laptop-asus-intelligent-performance-technology-aipt/
> > > # [1]
> > > Reported-by: Michael Larabel <Michael@phoronix.com>
> > > Closes: https://www.phoronix.com/review/lunar-lake-xe2/5 # [2]
> > > Link: https://github.com/dominiksalvet/asus-fan-control/issues/151 # [3]
> > > Tested-by: Casey Bowman <casey.g.bowman@intel.com>
> > > Signed-off-by: Srinivas Pandruvada <srinivas.pandruvada@linux.intel.com>
> > > ---
> > >   drivers/platform/x86/asus-wmi.c | 93 +++++++++++++++++++++++++++++++--
> > >   1 file changed, 89 insertions(+), 4 deletions(-)
> > > 
> > > diff --git a/drivers/platform/x86/asus-wmi.c
> > > b/drivers/platform/x86/asus-wmi.c
> > > index 7a48220b4f5a..06689d0f98c7 100644
> > > --- a/drivers/platform/x86/asus-wmi.c
> > > +++ b/drivers/platform/x86/asus-wmi.c
> > > @@ -100,6 +100,11 @@ module_param(fnlock_default, bool, 0444);
> > >   #define ASUS_THROTTLE_THERMAL_POLICY_SILENT_VIVO    1
> > >   #define ASUS_THROTTLE_THERMAL_POLICY_OVERBOOST_VIVO    2
> > > 
> > > +#define AIPT_STANDARD                0
> > > +#define AIPT_WHISPER                1
> > > +#define AIPT_PERFORMANCE            2
> > > +#define AIPT_FULL_SPEED                3
> > > +
> > >   #define PLATFORM_PROFILE_MAX 2
> > > 
> > >   #define USB_INTEL_XUSB2PR        0xD0
> > > @@ -333,6 +338,9 @@ struct asus_wmi {
> > >       struct asus_wmi_debug debug;
> > > 
> > >       struct asus_wmi_driver *driver;
> > > +    acpi_handle acpi_mgmt_handle;
> > > +    int asus_aipt_mode;
> > > +    bool asus_aipt_present;
> > >   };
> > > 
> > >   /* WMI
> > > ************************************************************************/
> > > @@ -3804,6 +3812,19 @@ static ssize_t
> > > throttle_thermal_policy_store(struct device *dev,
> > >   static DEVICE_ATTR_RW(throttle_thermal_policy);
> > > 
> > >   /* Platform profile
> > > ***********************************************************/
> > > +static int asus_wmi_write_aipt_mode(struct asus_wmi *asus, int
> > > aipt_mode)
> > > +{
> > > +    int status;
> > > +
> > > +    status = acpi_execute_simple_method(asus->acpi_mgmt_handle,
> > > "FANL", aipt_mode);
> > > +    if (ACPI_FAILURE(status)) {
> > > +        acpi_handle_info(asus->acpi_mgmt_handle, "FANL execute
> > > failed\n");
> > > +        return -EIO;
> > > +    }
> > > +
> > > +    return 0;
> > > +}
> > > +
> > >   static int asus_wmi_platform_profile_to_vivo(struct asus_wmi *asus,
> > > int mode)
> > >   {
> > >       bool vivo;
> > > @@ -3844,6 +3865,26 @@ static int
> > > asus_wmi_platform_profile_mode_from_vivo(struct asus_wmi *asus, int m
> > >       return mode;
> > >   }
> > > 
> > > +static int asus_wmi_aipt_platform_profile_get(struct asus_wmi *asus,
> > > +                          enum platform_profile_option *profile)
> > > +{
> > > +    switch (asus->asus_aipt_mode) {
> > > +    case AIPT_STANDARD:
> > > +        *profile = PLATFORM_PROFILE_BALANCED;
> > > +        break;
> > > +    case AIPT_PERFORMANCE:
> > > +        *profile = PLATFORM_PROFILE_PERFORMANCE;
> > > +        break;
> > > +    case AIPT_WHISPER:
> > > +        *profile = PLATFORM_PROFILE_QUIET;
> > > +        break;
> > > +    default:
> > > +        return -EINVAL;
> > > +    }
> > > +
> > > +    return 0;
> > > +}
> > > +
> > >   static int asus_wmi_platform_profile_get(struct
> > > platform_profile_handler *pprof,
> > >                       enum platform_profile_option *profile)
> > >   {
> > > @@ -3851,6 +3892,10 @@ static int
> > > asus_wmi_platform_profile_get(struct platform_profile_handler *pprof,
> > >       int tp;
> > > 
> > >       asus = container_of(pprof, struct asus_wmi,
> > > platform_profile_handler);
> > > +
> > > +    if (asus->asus_aipt_present)
> > > +        return asus_wmi_aipt_platform_profile_get(asus, profile);
> > > +
> > >       tp = asus->throttle_thermal_policy_mode;
> > > 
> > >       switch (asus_wmi_platform_profile_mode_from_vivo(asus, tp)) {
> > > @@ -3874,26 +3919,42 @@ static int
> > > asus_wmi_platform_profile_set(struct platform_profile_handler *pprof,
> > >                       enum platform_profile_option profile)
> > >   {
> > >       struct asus_wmi *asus;
> > > -    int tp;
> > > +    int ret = 0, tp, aipt_mode;
> > > 
> > >       asus = container_of(pprof, struct asus_wmi,
> > > platform_profile_handler);
> > > 
> > >       switch (profile) {
> > >       case PLATFORM_PROFILE_PERFORMANCE:
> > >           tp = ASUS_THROTTLE_THERMAL_POLICY_OVERBOOST;
> > > +        aipt_mode = AIPT_PERFORMANCE;
> > >           break;
> > >       case PLATFORM_PROFILE_BALANCED:
> > >           tp = ASUS_THROTTLE_THERMAL_POLICY_DEFAULT;
> > > +        aipt_mode = AIPT_STANDARD;
> > >           break;
> > >       case PLATFORM_PROFILE_QUIET:
> > >           tp = ASUS_THROTTLE_THERMAL_POLICY_SILENT;
> > > +        aipt_mode = AIPT_WHISPER;
> > >           break;
> > >       default:
> > >           return -EOPNOTSUPP;
> > >       }
> > > 
> > > -    asus->throttle_thermal_policy_mode =
> > > asus_wmi_platform_profile_to_vivo(asus, tp);
> > > -    return throttle_thermal_policy_write(asus);
> > > +    if (asus->asus_aipt_present) {
> > > +        ret = asus_wmi_write_aipt_mode(asus, aipt_mode);
> > > +        if (!ret) {
> > > +            asus->asus_aipt_mode = aipt_mode;
> > > +            goto skip_vivo;
> > > +        }
> > > +    }
> > > +
> > > +    if (asus->throttle_thermal_policy_dev) {
> > > +        asus->throttle_thermal_policy_mode =
> > > asus_wmi_platform_profile_to_vivo(asus, tp);
> > > +        ret = throttle_thermal_policy_write(asus);
> > > +    }
> > > +
> > > +skip_vivo:
> > > +    return ret;
> > >   }
> > > 
> > >   static int platform_profile_setup(struct asus_wmi *asus)
> > > @@ -3905,7 +3966,7 @@ static int platform_profile_setup(struct
> > > asus_wmi *asus)
> > >        * Not an error if a component platform_profile relies on is
> > > unavailable
> > >        * so early return, skipping the setup of platform_profile.
> > >        */
> > > -    if (!asus->throttle_thermal_policy_dev)
> > > +    if (!asus->throttle_thermal_policy_dev && !asus->asus_aipt_present)
> > >           return 0;
> > > 
> > >       dev_info(dev, "Using throttle_thermal_policy for
> > > platform_profile support\n");
> > > @@ -4538,6 +4599,7 @@ static int asus_wmi_sysfs_init(struct
> > > platform_device *device)
> > >   static int asus_wmi_platform_init(struct asus_wmi *asus)
> > >   {
> > >       struct device *dev = &asus->platform_device->dev;
> > > +    struct acpi_device *adev;
> > >       char *wmi_uid;
> > >       int rv;
> > > 
> > > @@ -4593,6 +4655,29 @@ static int asus_wmi_platform_init(struct
> > > asus_wmi *asus)
> > >           asus_wmi_set_devstate(ASUS_WMI_DEVID_CWAP,
> > >                         asus->driver->quirks->wapf, NULL);
> > > 
> > > +    /*
> > > +     * Check presence of Intelligent Performance Technology (AIPT).
> > > +     * If present store acpi handle and set asus_aipt_present to true.
> > > +     */
> > > +    adev = acpi_dev_get_first_match_dev("PNP0C14", "ATK", -1);
> > 
> > Is there really no way of changing the AIPT mode through the WMI
> > interface?
> > I would prefer using the WMI interface if available, since the
> > firmware might
> > assume that FANL is only called through the WMI interface.
> > 
> > Do you have a acpidump from a affected device?
> > 
> > Thanks,
> > Armin Wolf
> > 
> I found a acpidump from a ASUS device with a matching FANL method. It seems that this method
> can indeed be called using the WMI interface using the DEVS() WMI method:
> 
> [WmiMethodId(1398162756), Implemented] void DEVS([in] uint32 Device_ID, [in] uint32 Control_status, [out] uint32 result);
> 
> If Device_ID is 0x00110019, then Control_status is passed to the FANL ACPI method.
> 
> It also seems that support for AIPT can be queried using the DSTS() WMI method:
> 
> [WmiMethodId(1398035268), Implemented] void DSTS([in] uint32 Device_ID, [out] uint32 device_status);
> 
> Using Device_ID 0x00110019, the returned device status seems to contain the following information:
> 
> - 16-bit current AIPT mode
> - 4-bit unknown value (possible values 2, 3 and 7, maybe number of supported modes or some kind of bitmap?)
> - 1-bit with is set when (GGIV (0x0907000C) == One) is true

I just saw this conversation and i think that the behaviour this
patch will implement in the driver was already implemented in this patch
that got added to kernel v6.12-rc3:
https://lore.kernel.org/platform-driver-x86/20240609144849.2532-2-mohamed.ghanmi@supcom.tn/

this patch introduced ASUS_WMI_DEVID_THROTTLE_THERMAL_POLICY_VIVO
0x00110019 which is the device_id that changes the fan profiles. the
naming is not clear because it was initially intended to add support for
fan profiles for vivobook laptops but it ended up adding support
for a lot of modern laptops.


a point that Srinivas Pandruvada mentioned about RAPL (Running Average Power Limit)
is valid for a lot of modern vivobook and zenbook laptops but i think
it's unrelated to fan profiles.

a lot of asus laptops that have intel cpus suffer from power throttling.
for exemple in my case using windows, changing fan profiles will lead to max power
changing to the values indicated in the table below (asus vivobook 16x
pro k6604) which leads to higher performance than linux

fan Profile		power limit
-----------------------------------
Whisper			50watts
Standard                120watts
Performance		149watts
------------------------------------

However in linux, even after changing to the appropriate fan profile,
the power is still capped at 50watts and i found the reason why

here is the results of using the powercap-info command:

intel-rapl-mmio
  enabled: 1
  Zone 0
    name: package-0
    enabled: 1
    max_energy_range_uj: 262143328850
    Constraint 0
      name: long_term
      power_limit_uw: 30000000
      time_window_us: 55967744
      max_power_uw: 55000000
    Constraint 1
      name: short_term
      power_limit_uw: 55000000
      time_window_us: 2440
      max_power_uw: 0
intel-rapl
  enabled: 1
  Zone 0
    name: package-0
    enabled: 1
    max_energy_range_uj: 262143328850
    Constraint 0
      name: long_term
      power_limit_uw: 157000000
      time_window_us: 55967744
      max_power_uw: 55000000
    Constraint 1
      name: short_term
      power_limit_uw: 157000000
      time_window_us: 2440
      max_power_uw: 0
    Constraint 2
      name: peak_power
      power_limit_uw: 200000000
      max_power_uw: 0
    Zone 0:0
      name: core
      enabled: 0
      max_energy_range_uj: 262143328850
      Constraint 0
        name: long_term
        power_limit_uw: 0
        time_window_us: 976
    Zone 0:1
      name: uncore
      enabled: 0
      max_energy_range_uj: 262143328850
      Constraint 0
        name: long_term
        power_limit_uw: 0
        time_window_us: 976
  Zone 1
    name: psys
    enabled: 0
    max_energy_range_uj: 262143328850
    Constraint 0
      name: long_term
      power_limit_uw: 0
      time_window_us: 27983872
    Constraint 1
      name: short_term
      power_limit_uw: 0
      time_window_us: 976


as seen by the output of the command, the intel-rapl-mmio is causing the
throttling as it sets power_limit_uw to 30 watts (readonly). so the current fix
that i'm currently using is disabling the intel-rapl-mmio leaving only
the intel-rapl which sets power_limit_uw to 157watts using this
command: powercap-set -p intel-rapl-mmio -z 0 -e 0

this will lead to the laptop being able to reach it's maximum power
limit.

after doing this, when i change the platform profile through sysfs the
laptop will start behaving as described in the table above exactly like
windows.

in conclusion, the asus-wmi driver already has the platform profiles
(a.k.a fan profiles)
implemented and I think that the power throttling is caused by either
intel Power Capping Framework or asus bios.

I also think that redoing the above benchmarks linked by Srinivas after
using a kernel version higher than v6.12-rc3 and disabling the
intel-rapl-mmio would be a great idea

Best Regards,
Armin Wolf Oct. 23, 2024, 4:31 p.m. UTC | #8
Am 23.10.24 um 16:44 schrieb Mohamed Ghanmi:

> Hello !
> On Sun, Oct 20, 2024 at 09:42:45PM +0200, Armin Wolf wrote:
>> Am 20.10.24 um 21:05 schrieb Armin Wolf:
>>
>>> Am 20.10.24 um 08:50 schrieb Srinivas Pandruvada:
>>>
>>>> Some recent Asus laptops are supporting ASUS Intelligent Performance
>>>> Technology (AIPT). This solution allows users to have maximized CPU
>>>> performance in models with a chassis providing more thermal head room.
>>>> Refer to [1].
>>>>
>>>> There are major performance issues when Linux is installed on these
>>>> laptops compared to Windows install. One such report is published for
>>>> Graphics benchmarks on Asus ASUS Zenbook S 14 with Lunar Lake
>>>> processors [2].
>>>>
>>>> By default, these laptops are booting in "Whisper Mode" till OS power
>>>> management or tools change this to other AIPT mode. This "Whisper" mode
>>>> calls to set lower maximum and minimum RAPL (Running Average Power
>>>> Limit)
>>>> via thermal tables. On Linux this leads to lower performance even when
>>>> platform power profile is "balanced". This "Whisper" mode should
>>>> correspond to "quiet" mode.
>>>>
>>>> So, when AIPT is present change the default mode to "Standard" during
>>>> boot. Map the three platform power profile modes as follows:
>>>>
>>>> Power Profile Mode      AIPT mode
>>>> -----------------------------------
>>>> quiet            Whisper
>>>> balanced        Standard
>>>> performance        Performance
>>>> ------------------------------------
>>>>
>>>> Here AIPT mode can be detected by checking presese of "FANL" method
>>>> under
>>>> PNP HID "PNP0C14" and UID "ATK". If AIPT mode is present, this takes
>>>> precedence over the existing VIVO thermal policy. These modes are set
>>>> using "FANL" method.
>>>>
>>>> Although this “FANL” method is not used in the Asus WMI driver, users
>>>> have used this method from user space [3] to set AIPT modes. Used this
>>>> as a reference.
>>>>
>>>> Link:
>>>> https://www.asus.com/content/laptop-asus-intelligent-performance-technology-aipt/
>>>> # [1]
>>>> Reported-by: Michael Larabel <Michael@phoronix.com>
>>>> Closes: https://www.phoronix.com/review/lunar-lake-xe2/5 # [2]
>>>> Link: https://github.com/dominiksalvet/asus-fan-control/issues/151 # [3]
>>>> Tested-by: Casey Bowman <casey.g.bowman@intel.com>
>>>> Signed-off-by: Srinivas Pandruvada <srinivas.pandruvada@linux.intel.com>
>>>> ---
>>>>    drivers/platform/x86/asus-wmi.c | 93 +++++++++++++++++++++++++++++++--
>>>>    1 file changed, 89 insertions(+), 4 deletions(-)
>>>>
>>>> diff --git a/drivers/platform/x86/asus-wmi.c
>>>> b/drivers/platform/x86/asus-wmi.c
>>>> index 7a48220b4f5a..06689d0f98c7 100644
>>>> --- a/drivers/platform/x86/asus-wmi.c
>>>> +++ b/drivers/platform/x86/asus-wmi.c
>>>> @@ -100,6 +100,11 @@ module_param(fnlock_default, bool, 0444);
>>>>    #define ASUS_THROTTLE_THERMAL_POLICY_SILENT_VIVO    1
>>>>    #define ASUS_THROTTLE_THERMAL_POLICY_OVERBOOST_VIVO    2
>>>>
>>>> +#define AIPT_STANDARD                0
>>>> +#define AIPT_WHISPER                1
>>>> +#define AIPT_PERFORMANCE            2
>>>> +#define AIPT_FULL_SPEED                3
>>>> +
>>>>    #define PLATFORM_PROFILE_MAX 2
>>>>
>>>>    #define USB_INTEL_XUSB2PR        0xD0
>>>> @@ -333,6 +338,9 @@ struct asus_wmi {
>>>>        struct asus_wmi_debug debug;
>>>>
>>>>        struct asus_wmi_driver *driver;
>>>> +    acpi_handle acpi_mgmt_handle;
>>>> +    int asus_aipt_mode;
>>>> +    bool asus_aipt_present;
>>>>    };
>>>>
>>>>    /* WMI
>>>> ************************************************************************/
>>>> @@ -3804,6 +3812,19 @@ static ssize_t
>>>> throttle_thermal_policy_store(struct device *dev,
>>>>    static DEVICE_ATTR_RW(throttle_thermal_policy);
>>>>
>>>>    /* Platform profile
>>>> ***********************************************************/
>>>> +static int asus_wmi_write_aipt_mode(struct asus_wmi *asus, int
>>>> aipt_mode)
>>>> +{
>>>> +    int status;
>>>> +
>>>> +    status = acpi_execute_simple_method(asus->acpi_mgmt_handle,
>>>> "FANL", aipt_mode);
>>>> +    if (ACPI_FAILURE(status)) {
>>>> +        acpi_handle_info(asus->acpi_mgmt_handle, "FANL execute
>>>> failed\n");
>>>> +        return -EIO;
>>>> +    }
>>>> +
>>>> +    return 0;
>>>> +}
>>>> +
>>>>    static int asus_wmi_platform_profile_to_vivo(struct asus_wmi *asus,
>>>> int mode)
>>>>    {
>>>>        bool vivo;
>>>> @@ -3844,6 +3865,26 @@ static int
>>>> asus_wmi_platform_profile_mode_from_vivo(struct asus_wmi *asus, int m
>>>>        return mode;
>>>>    }
>>>>
>>>> +static int asus_wmi_aipt_platform_profile_get(struct asus_wmi *asus,
>>>> +                          enum platform_profile_option *profile)
>>>> +{
>>>> +    switch (asus->asus_aipt_mode) {
>>>> +    case AIPT_STANDARD:
>>>> +        *profile = PLATFORM_PROFILE_BALANCED;
>>>> +        break;
>>>> +    case AIPT_PERFORMANCE:
>>>> +        *profile = PLATFORM_PROFILE_PERFORMANCE;
>>>> +        break;
>>>> +    case AIPT_WHISPER:
>>>> +        *profile = PLATFORM_PROFILE_QUIET;
>>>> +        break;
>>>> +    default:
>>>> +        return -EINVAL;
>>>> +    }
>>>> +
>>>> +    return 0;
>>>> +}
>>>> +
>>>>    static int asus_wmi_platform_profile_get(struct
>>>> platform_profile_handler *pprof,
>>>>                        enum platform_profile_option *profile)
>>>>    {
>>>> @@ -3851,6 +3892,10 @@ static int
>>>> asus_wmi_platform_profile_get(struct platform_profile_handler *pprof,
>>>>        int tp;
>>>>
>>>>        asus = container_of(pprof, struct asus_wmi,
>>>> platform_profile_handler);
>>>> +
>>>> +    if (asus->asus_aipt_present)
>>>> +        return asus_wmi_aipt_platform_profile_get(asus, profile);
>>>> +
>>>>        tp = asus->throttle_thermal_policy_mode;
>>>>
>>>>        switch (asus_wmi_platform_profile_mode_from_vivo(asus, tp)) {
>>>> @@ -3874,26 +3919,42 @@ static int
>>>> asus_wmi_platform_profile_set(struct platform_profile_handler *pprof,
>>>>                        enum platform_profile_option profile)
>>>>    {
>>>>        struct asus_wmi *asus;
>>>> -    int tp;
>>>> +    int ret = 0, tp, aipt_mode;
>>>>
>>>>        asus = container_of(pprof, struct asus_wmi,
>>>> platform_profile_handler);
>>>>
>>>>        switch (profile) {
>>>>        case PLATFORM_PROFILE_PERFORMANCE:
>>>>            tp = ASUS_THROTTLE_THERMAL_POLICY_OVERBOOST;
>>>> +        aipt_mode = AIPT_PERFORMANCE;
>>>>            break;
>>>>        case PLATFORM_PROFILE_BALANCED:
>>>>            tp = ASUS_THROTTLE_THERMAL_POLICY_DEFAULT;
>>>> +        aipt_mode = AIPT_STANDARD;
>>>>            break;
>>>>        case PLATFORM_PROFILE_QUIET:
>>>>            tp = ASUS_THROTTLE_THERMAL_POLICY_SILENT;
>>>> +        aipt_mode = AIPT_WHISPER;
>>>>            break;
>>>>        default:
>>>>            return -EOPNOTSUPP;
>>>>        }
>>>>
>>>> -    asus->throttle_thermal_policy_mode =
>>>> asus_wmi_platform_profile_to_vivo(asus, tp);
>>>> -    return throttle_thermal_policy_write(asus);
>>>> +    if (asus->asus_aipt_present) {
>>>> +        ret = asus_wmi_write_aipt_mode(asus, aipt_mode);
>>>> +        if (!ret) {
>>>> +            asus->asus_aipt_mode = aipt_mode;
>>>> +            goto skip_vivo;
>>>> +        }
>>>> +    }
>>>> +
>>>> +    if (asus->throttle_thermal_policy_dev) {
>>>> +        asus->throttle_thermal_policy_mode =
>>>> asus_wmi_platform_profile_to_vivo(asus, tp);
>>>> +        ret = throttle_thermal_policy_write(asus);
>>>> +    }
>>>> +
>>>> +skip_vivo:
>>>> +    return ret;
>>>>    }
>>>>
>>>>    static int platform_profile_setup(struct asus_wmi *asus)
>>>> @@ -3905,7 +3966,7 @@ static int platform_profile_setup(struct
>>>> asus_wmi *asus)
>>>>         * Not an error if a component platform_profile relies on is
>>>> unavailable
>>>>         * so early return, skipping the setup of platform_profile.
>>>>         */
>>>> -    if (!asus->throttle_thermal_policy_dev)
>>>> +    if (!asus->throttle_thermal_policy_dev && !asus->asus_aipt_present)
>>>>            return 0;
>>>>
>>>>        dev_info(dev, "Using throttle_thermal_policy for
>>>> platform_profile support\n");
>>>> @@ -4538,6 +4599,7 @@ static int asus_wmi_sysfs_init(struct
>>>> platform_device *device)
>>>>    static int asus_wmi_platform_init(struct asus_wmi *asus)
>>>>    {
>>>>        struct device *dev = &asus->platform_device->dev;
>>>> +    struct acpi_device *adev;
>>>>        char *wmi_uid;
>>>>        int rv;
>>>>
>>>> @@ -4593,6 +4655,29 @@ static int asus_wmi_platform_init(struct
>>>> asus_wmi *asus)
>>>>            asus_wmi_set_devstate(ASUS_WMI_DEVID_CWAP,
>>>>                          asus->driver->quirks->wapf, NULL);
>>>>
>>>> +    /*
>>>> +     * Check presence of Intelligent Performance Technology (AIPT).
>>>> +     * If present store acpi handle and set asus_aipt_present to true.
>>>> +     */
>>>> +    adev = acpi_dev_get_first_match_dev("PNP0C14", "ATK", -1);
>>> Is there really no way of changing the AIPT mode through the WMI
>>> interface?
>>> I would prefer using the WMI interface if available, since the
>>> firmware might
>>> assume that FANL is only called through the WMI interface.
>>>
>>> Do you have a acpidump from a affected device?
>>>
>>> Thanks,
>>> Armin Wolf
>>>
>> I found a acpidump from a ASUS device with a matching FANL method. It seems that this method
>> can indeed be called using the WMI interface using the DEVS() WMI method:
>>
>> [WmiMethodId(1398162756), Implemented] void DEVS([in] uint32 Device_ID, [in] uint32 Control_status, [out] uint32 result);
>>
>> If Device_ID is 0x00110019, then Control_status is passed to the FANL ACPI method.
>>
>> It also seems that support for AIPT can be queried using the DSTS() WMI method:
>>
>> [WmiMethodId(1398035268), Implemented] void DSTS([in] uint32 Device_ID, [out] uint32 device_status);
>>
>> Using Device_ID 0x00110019, the returned device status seems to contain the following information:
>>
>> - 16-bit current AIPT mode
>> - 4-bit unknown value (possible values 2, 3 and 7, maybe number of supported modes or some kind of bitmap?)
>> - 1-bit with is set when (GGIV (0x0907000C) == One) is true
> I just saw this conversation and i think that the behaviour this
> patch will implement in the driver was already implemented in this patch
> that got added to kernel v6.12-rc3:
> https://lore.kernel.org/platform-driver-x86/20240609144849.2532-2-mohamed.ghanmi@supcom.tn/
>
> this patch introduced ASUS_WMI_DEVID_THROTTLE_THERMAL_POLICY_VIVO
> 0x00110019 which is the device_id that changes the fan profiles. the
> naming is not clear because it was initially intended to add support for
> fan profiles for vivobook laptops but it ended up adding support
> for a lot of modern laptops.

Nice, you are absolutely right.

So this patch series is effectively already upstream, very good. I did some research and found out
that the status of this device id contains the following data:

Status		Supported Modes
-------------------------------
0x00[1]300[xx]	0 1 2
0x000700[xx]	0 1 2
0x000200[xx]	??? (ODV0)
0x000700[xx]	0 1 2
0x0a0700[xx]	??? (ODV0)

While i have no clue about the meaning of the remaining bits, i can report that the first 8 Bits
contain the current thermal mode. Maybe adding support for this would be nice, so the current
thermal mode can be read directly from the hardware.

I also found out that on some models the thermal mode actually modifies the ODV0 variable which
is consumed by int3400_thermal and exposed to the Intel Thermal Daemon. So maybe the lackluster
performance also has something to do with it.

> a point that Srinivas Pandruvada mentioned about RAPL (Running Average Power Limit)
> is valid for a lot of modern vivobook and zenbook laptops but i think
> it's unrelated to fan profiles.
>
> a lot of asus laptops that have intel cpus suffer from power throttling.
> for exemple in my case using windows, changing fan profiles will lead to max power
> changing to the values indicated in the table below (asus vivobook 16x
> pro k6604) which leads to higher performance than linux
>
> fan Profile		power limit
> -----------------------------------
> Whisper			50watts
> Standard                120watts
> Performance		149watts
> ------------------------------------
>
> However in linux, even after changing to the appropriate fan profile,
> the power is still capped at 50watts and i found the reason why
>
> here is the results of using the powercap-info command:
>
> intel-rapl-mmio
>    enabled: 1
>    Zone 0
>      name: package-0
>      enabled: 1
>      max_energy_range_uj: 262143328850
>      Constraint 0
>        name: long_term
>        power_limit_uw: 30000000
>        time_window_us: 55967744
>        max_power_uw: 55000000
>      Constraint 1
>        name: short_term
>        power_limit_uw: 55000000
>        time_window_us: 2440
>        max_power_uw: 0
> intel-rapl
>    enabled: 1
>    Zone 0
>      name: package-0
>      enabled: 1
>      max_energy_range_uj: 262143328850
>      Constraint 0
>        name: long_term
>        power_limit_uw: 157000000
>        time_window_us: 55967744
>        max_power_uw: 55000000
>      Constraint 1
>        name: short_term
>        power_limit_uw: 157000000
>        time_window_us: 2440
>        max_power_uw: 0
>      Constraint 2
>        name: peak_power
>        power_limit_uw: 200000000
>        max_power_uw: 0
>      Zone 0:0
>        name: core
>        enabled: 0
>        max_energy_range_uj: 262143328850
>        Constraint 0
>          name: long_term
>          power_limit_uw: 0
>          time_window_us: 976
>      Zone 0:1
>        name: uncore
>        enabled: 0
>        max_energy_range_uj: 262143328850
>        Constraint 0
>          name: long_term
>          power_limit_uw: 0
>          time_window_us: 976
>    Zone 1
>      name: psys
>      enabled: 0
>      max_energy_range_uj: 262143328850
>      Constraint 0
>        name: long_term
>        power_limit_uw: 0
>        time_window_us: 27983872
>      Constraint 1
>        name: short_term
>        power_limit_uw: 0
>        time_window_us: 976
>
>
> as seen by the output of the command, the intel-rapl-mmio is causing the
> throttling as it sets power_limit_uw to 30 watts (readonly). so the current fix
> that i'm currently using is disabling the intel-rapl-mmio leaving only
> the intel-rapl which sets power_limit_uw to 157watts using this
> command: powercap-set -p intel-rapl-mmio -z 0 -e 0
>
> this will lead to the laptop being able to reach it's maximum power
> limit.
>
> after doing this, when i change the platform profile through sysfs the
> laptop will start behaving as described in the table above exactly like
> windows.
>
> in conclusion, the asus-wmi driver already has the platform profiles
> (a.k.a fan profiles)
> implemented and I think that the power throttling is caused by either
> intel Power Capping Framework or asus bios.

Or the Intel Thermal Daemon somehow does not properly support intel-rapl-mmio
or is not installed.

Thanks,
Armin Wolf

>
> I also think that redoing the above benchmarks linked by Srinivas after
> using a kernel version higher than v6.12-rc3 and disabling the
> intel-rapl-mmio would be a great idea
>
> Best Regards,
Mohamed Ghanmi Oct. 23, 2024, 5:59 p.m. UTC | #9
On Wed, Oct 23, 2024 at 06:31:17PM +0200, Armin Wolf wrote:
> Am 23.10.24 um 16:44 schrieb Mohamed Ghanmi:
> 
> > Hello !
> > On Sun, Oct 20, 2024 at 09:42:45PM +0200, Armin Wolf wrote:
> > > Am 20.10.24 um 21:05 schrieb Armin Wolf:
> > > 
> > > > Am 20.10.24 um 08:50 schrieb Srinivas Pandruvada:
> > > > 
> > > > > Some recent Asus laptops are supporting ASUS Intelligent Performance
> > > > > Technology (AIPT). This solution allows users to have maximized CPU
> > > > > performance in models with a chassis providing more thermal head room.
> > > > > Refer to [1].
> > > > > 
> > > > > There are major performance issues when Linux is installed on these
> > > > > laptops compared to Windows install. One such report is published for
> > > > > Graphics benchmarks on Asus ASUS Zenbook S 14 with Lunar Lake
> > > > > processors [2].
> > > > > 
> > > > > By default, these laptops are booting in "Whisper Mode" till OS power
> > > > > management or tools change this to other AIPT mode. This "Whisper" mode
> > > > > calls to set lower maximum and minimum RAPL (Running Average Power
> > > > > Limit)
> > > > > via thermal tables. On Linux this leads to lower performance even when
> > > > > platform power profile is "balanced". This "Whisper" mode should
> > > > > correspond to "quiet" mode.
> > > > > 
> > > > > So, when AIPT is present change the default mode to "Standard" during
> > > > > boot. Map the three platform power profile modes as follows:
> > > > > 
> > > > > Power Profile Mode      AIPT mode
> > > > > -----------------------------------
> > > > > quiet            Whisper
> > > > > balanced        Standard
> > > > > performance        Performance
> > > > > ------------------------------------
> > > > > 
> > > > > Here AIPT mode can be detected by checking presese of "FANL" method
> > > > > under
> > > > > PNP HID "PNP0C14" and UID "ATK". If AIPT mode is present, this takes
> > > > > precedence over the existing VIVO thermal policy. These modes are set
> > > > > using "FANL" method.
> > > > > 
> > > > > Although this “FANL” method is not used in the Asus WMI driver, users
> > > > > have used this method from user space [3] to set AIPT modes. Used this
> > > > > as a reference.
> > > > > 
> > > > > Link:
> > > > > https://www.asus.com/content/laptop-asus-intelligent-performance-technology-aipt/
> > > > > # [1]
> > > > > Reported-by: Michael Larabel <Michael@phoronix.com>
> > > > > Closes: https://www.phoronix.com/review/lunar-lake-xe2/5 # [2]
> > > > > Link: https://github.com/dominiksalvet/asus-fan-control/issues/151 # [3]
> > > > > Tested-by: Casey Bowman <casey.g.bowman@intel.com>
> > > > > Signed-off-by: Srinivas Pandruvada <srinivas.pandruvada@linux.intel.com>
> > > > > ---
> > > > >    drivers/platform/x86/asus-wmi.c | 93 +++++++++++++++++++++++++++++++--
> > > > >    1 file changed, 89 insertions(+), 4 deletions(-)
> > > > > 
> > > > > diff --git a/drivers/platform/x86/asus-wmi.c
> > > > > b/drivers/platform/x86/asus-wmi.c
> > > > > index 7a48220b4f5a..06689d0f98c7 100644
> > > > > --- a/drivers/platform/x86/asus-wmi.c
> > > > > +++ b/drivers/platform/x86/asus-wmi.c
> > > > > @@ -100,6 +100,11 @@ module_param(fnlock_default, bool, 0444);
> > > > >    #define ASUS_THROTTLE_THERMAL_POLICY_SILENT_VIVO    1
> > > > >    #define ASUS_THROTTLE_THERMAL_POLICY_OVERBOOST_VIVO    2
> > > > > 
> > > > > +#define AIPT_STANDARD                0
> > > > > +#define AIPT_WHISPER                1
> > > > > +#define AIPT_PERFORMANCE            2
> > > > > +#define AIPT_FULL_SPEED                3
> > > > > +
> > > > >    #define PLATFORM_PROFILE_MAX 2
> > > > > 
> > > > >    #define USB_INTEL_XUSB2PR        0xD0
> > > > > @@ -333,6 +338,9 @@ struct asus_wmi {
> > > > >        struct asus_wmi_debug debug;
> > > > > 
> > > > >        struct asus_wmi_driver *driver;
> > > > > +    acpi_handle acpi_mgmt_handle;
> > > > > +    int asus_aipt_mode;
> > > > > +    bool asus_aipt_present;
> > > > >    };
> > > > > 
> > > > >    /* WMI
> > > > > ************************************************************************/
> > > > > @@ -3804,6 +3812,19 @@ static ssize_t
> > > > > throttle_thermal_policy_store(struct device *dev,
> > > > >    static DEVICE_ATTR_RW(throttle_thermal_policy);
> > > > > 
> > > > >    /* Platform profile
> > > > > ***********************************************************/
> > > > > +static int asus_wmi_write_aipt_mode(struct asus_wmi *asus, int
> > > > > aipt_mode)
> > > > > +{
> > > > > +    int status;
> > > > > +
> > > > > +    status = acpi_execute_simple_method(asus->acpi_mgmt_handle,
> > > > > "FANL", aipt_mode);
> > > > > +    if (ACPI_FAILURE(status)) {
> > > > > +        acpi_handle_info(asus->acpi_mgmt_handle, "FANL execute
> > > > > failed\n");
> > > > > +        return -EIO;
> > > > > +    }
> > > > > +
> > > > > +    return 0;
> > > > > +}
> > > > > +
> > > > >    static int asus_wmi_platform_profile_to_vivo(struct asus_wmi *asus,
> > > > > int mode)
> > > > >    {
> > > > >        bool vivo;
> > > > > @@ -3844,6 +3865,26 @@ static int
> > > > > asus_wmi_platform_profile_mode_from_vivo(struct asus_wmi *asus, int m
> > > > >        return mode;
> > > > >    }
> > > > > 
> > > > > +static int asus_wmi_aipt_platform_profile_get(struct asus_wmi *asus,
> > > > > +                          enum platform_profile_option *profile)
> > > > > +{
> > > > > +    switch (asus->asus_aipt_mode) {
> > > > > +    case AIPT_STANDARD:
> > > > > +        *profile = PLATFORM_PROFILE_BALANCED;
> > > > > +        break;
> > > > > +    case AIPT_PERFORMANCE:
> > > > > +        *profile = PLATFORM_PROFILE_PERFORMANCE;
> > > > > +        break;
> > > > > +    case AIPT_WHISPER:
> > > > > +        *profile = PLATFORM_PROFILE_QUIET;
> > > > > +        break;
> > > > > +    default:
> > > > > +        return -EINVAL;
> > > > > +    }
> > > > > +
> > > > > +    return 0;
> > > > > +}
> > > > > +
> > > > >    static int asus_wmi_platform_profile_get(struct
> > > > > platform_profile_handler *pprof,
> > > > >                        enum platform_profile_option *profile)
> > > > >    {
> > > > > @@ -3851,6 +3892,10 @@ static int
> > > > > asus_wmi_platform_profile_get(struct platform_profile_handler *pprof,
> > > > >        int tp;
> > > > > 
> > > > >        asus = container_of(pprof, struct asus_wmi,
> > > > > platform_profile_handler);
> > > > > +
> > > > > +    if (asus->asus_aipt_present)
> > > > > +        return asus_wmi_aipt_platform_profile_get(asus, profile);
> > > > > +
> > > > >        tp = asus->throttle_thermal_policy_mode;
> > > > > 
> > > > >        switch (asus_wmi_platform_profile_mode_from_vivo(asus, tp)) {
> > > > > @@ -3874,26 +3919,42 @@ static int
> > > > > asus_wmi_platform_profile_set(struct platform_profile_handler *pprof,
> > > > >                        enum platform_profile_option profile)
> > > > >    {
> > > > >        struct asus_wmi *asus;
> > > > > -    int tp;
> > > > > +    int ret = 0, tp, aipt_mode;
> > > > > 
> > > > >        asus = container_of(pprof, struct asus_wmi,
> > > > > platform_profile_handler);
> > > > > 
> > > > >        switch (profile) {
> > > > >        case PLATFORM_PROFILE_PERFORMANCE:
> > > > >            tp = ASUS_THROTTLE_THERMAL_POLICY_OVERBOOST;
> > > > > +        aipt_mode = AIPT_PERFORMANCE;
> > > > >            break;
> > > > >        case PLATFORM_PROFILE_BALANCED:
> > > > >            tp = ASUS_THROTTLE_THERMAL_POLICY_DEFAULT;
> > > > > +        aipt_mode = AIPT_STANDARD;
> > > > >            break;
> > > > >        case PLATFORM_PROFILE_QUIET:
> > > > >            tp = ASUS_THROTTLE_THERMAL_POLICY_SILENT;
> > > > > +        aipt_mode = AIPT_WHISPER;
> > > > >            break;
> > > > >        default:
> > > > >            return -EOPNOTSUPP;
> > > > >        }
> > > > > 
> > > > > -    asus->throttle_thermal_policy_mode =
> > > > > asus_wmi_platform_profile_to_vivo(asus, tp);
> > > > > -    return throttle_thermal_policy_write(asus);
> > > > > +    if (asus->asus_aipt_present) {
> > > > > +        ret = asus_wmi_write_aipt_mode(asus, aipt_mode);
> > > > > +        if (!ret) {
> > > > > +            asus->asus_aipt_mode = aipt_mode;
> > > > > +            goto skip_vivo;
> > > > > +        }
> > > > > +    }
> > > > > +
> > > > > +    if (asus->throttle_thermal_policy_dev) {
> > > > > +        asus->throttle_thermal_policy_mode =
> > > > > asus_wmi_platform_profile_to_vivo(asus, tp);
> > > > > +        ret = throttle_thermal_policy_write(asus);
> > > > > +    }
> > > > > +
> > > > > +skip_vivo:
> > > > > +    return ret;
> > > > >    }
> > > > > 
> > > > >    static int platform_profile_setup(struct asus_wmi *asus)
> > > > > @@ -3905,7 +3966,7 @@ static int platform_profile_setup(struct
> > > > > asus_wmi *asus)
> > > > >         * Not an error if a component platform_profile relies on is
> > > > > unavailable
> > > > >         * so early return, skipping the setup of platform_profile.
> > > > >         */
> > > > > -    if (!asus->throttle_thermal_policy_dev)
> > > > > +    if (!asus->throttle_thermal_policy_dev && !asus->asus_aipt_present)
> > > > >            return 0;
> > > > > 
> > > > >        dev_info(dev, "Using throttle_thermal_policy for
> > > > > platform_profile support\n");
> > > > > @@ -4538,6 +4599,7 @@ static int asus_wmi_sysfs_init(struct
> > > > > platform_device *device)
> > > > >    static int asus_wmi_platform_init(struct asus_wmi *asus)
> > > > >    {
> > > > >        struct device *dev = &asus->platform_device->dev;
> > > > > +    struct acpi_device *adev;
> > > > >        char *wmi_uid;
> > > > >        int rv;
> > > > > 
> > > > > @@ -4593,6 +4655,29 @@ static int asus_wmi_platform_init(struct
> > > > > asus_wmi *asus)
> > > > >            asus_wmi_set_devstate(ASUS_WMI_DEVID_CWAP,
> > > > >                          asus->driver->quirks->wapf, NULL);
> > > > > 
> > > > > +    /*
> > > > > +     * Check presence of Intelligent Performance Technology (AIPT).
> > > > > +     * If present store acpi handle and set asus_aipt_present to true.
> > > > > +     */
> > > > > +    adev = acpi_dev_get_first_match_dev("PNP0C14", "ATK", -1);
> > > > Is there really no way of changing the AIPT mode through the WMI
> > > > interface?
> > > > I would prefer using the WMI interface if available, since the
> > > > firmware might
> > > > assume that FANL is only called through the WMI interface.
> > > > 
> > > > Do you have a acpidump from a affected device?
> > > > 
> > > > Thanks,
> > > > Armin Wolf
> > > > 
> > > I found a acpidump from a ASUS device with a matching FANL method. It seems that this method
> > > can indeed be called using the WMI interface using the DEVS() WMI method:
> > > 
> > > [WmiMethodId(1398162756), Implemented] void DEVS([in] uint32 Device_ID, [in] uint32 Control_status, [out] uint32 result);
> > > 
> > > If Device_ID is 0x00110019, then Control_status is passed to the FANL ACPI method.
> > > 
> > > It also seems that support for AIPT can be queried using the DSTS() WMI method:
> > > 
> > > [WmiMethodId(1398035268), Implemented] void DSTS([in] uint32 Device_ID, [out] uint32 device_status);
> > > 
> > > Using Device_ID 0x00110019, the returned device status seems to contain the following information:
> > > 
> > > - 16-bit current AIPT mode
> > > - 4-bit unknown value (possible values 2, 3 and 7, maybe number of supported modes or some kind of bitmap?)
> > > - 1-bit with is set when (GGIV (0x0907000C) == One) is true
> > I just saw this conversation and i think that the behaviour this
> > patch will implement in the driver was already implemented in this patch
> > that got added to kernel v6.12-rc3:
> > https://lore.kernel.org/platform-driver-x86/20240609144849.2532-2-mohamed.ghanmi@supcom.tn/
> > 
> > this patch introduced ASUS_WMI_DEVID_THROTTLE_THERMAL_POLICY_VIVO
> > 0x00110019 which is the device_id that changes the fan profiles. the
> > naming is not clear because it was initially intended to add support for
> > fan profiles for vivobook laptops but it ended up adding support
> > for a lot of modern laptops.
> 
> Nice, you are absolutely right.
> 
> So this patch series is effectively already upstream, very good. I did some research and found out
> that the status of this device id contains the following data:
> 
> Status		Supported Modes
> -------------------------------
> 0x00[1]300[xx]	0 1 2
> 0x000700[xx]	0 1 2
> 0x000200[xx]	??? (ODV0)
> 0x000700[xx]	0 1 2
> 0x0a0700[xx]	??? (ODV0)
> 
> While i have no clue about the meaning of the remaining bits, i can report that the first 8 Bits
> contain the current thermal mode. Maybe adding support for this would be nice, so the current
> thermal mode can be read directly from the hardware.
> 
> I also found out that on some models the thermal mode actually modifies the ODV0 variable which
> is consumed by int3400_thermal and exposed to the Intel Thermal Daemon. So maybe the lackluster
> performance also has something to do with it.
> 
> > a point that Srinivas Pandruvada mentioned about RAPL (Running Average Power Limit)
> > is valid for a lot of modern vivobook and zenbook laptops but i think
> > it's unrelated to fan profiles.
> > 
> > a lot of asus laptops that have intel cpus suffer from power throttling.
> > for exemple in my case using windows, changing fan profiles will lead to max power
> > changing to the values indicated in the table below (asus vivobook 16x
> > pro k6604) which leads to higher performance than linux
> > 
> > fan Profile		power limit
> > -----------------------------------
> > Whisper			50watts
> > Standard                120watts
> > Performance		149watts
> > ------------------------------------
> > 
> > However in linux, even after changing to the appropriate fan profile,
> > the power is still capped at 50watts and i found the reason why
> > 
> > here is the results of using the powercap-info command:
> > 
> > intel-rapl-mmio
> >    enabled: 1
> >    Zone 0
> >      name: package-0
> >      enabled: 1
> >      max_energy_range_uj: 262143328850
> >      Constraint 0
> >        name: long_term
> >        power_limit_uw: 30000000
> >        time_window_us: 55967744
> >        max_power_uw: 55000000
> >      Constraint 1
> >        name: short_term
> >        power_limit_uw: 55000000
> >        time_window_us: 2440
> >        max_power_uw: 0
> > intel-rapl
> >    enabled: 1
> >    Zone 0
> >      name: package-0
> >      enabled: 1
> >      max_energy_range_uj: 262143328850
> >      Constraint 0
> >        name: long_term
> >        power_limit_uw: 157000000
> >        time_window_us: 55967744
> >        max_power_uw: 55000000
> >      Constraint 1
> >        name: short_term
> >        power_limit_uw: 157000000
> >        time_window_us: 2440
> >        max_power_uw: 0
> >      Constraint 2
> >        name: peak_power
> >        power_limit_uw: 200000000
> >        max_power_uw: 0
> >      Zone 0:0
> >        name: core
> >        enabled: 0
> >        max_energy_range_uj: 262143328850
> >        Constraint 0
> >          name: long_term
> >          power_limit_uw: 0
> >          time_window_us: 976
> >      Zone 0:1
> >        name: uncore
> >        enabled: 0
> >        max_energy_range_uj: 262143328850
> >        Constraint 0
> >          name: long_term
> >          power_limit_uw: 0
> >          time_window_us: 976
> >    Zone 1
> >      name: psys
> >      enabled: 0
> >      max_energy_range_uj: 262143328850
> >      Constraint 0
> >        name: long_term
> >        power_limit_uw: 0
> >        time_window_us: 27983872
> >      Constraint 1
> >        name: short_term
> >        power_limit_uw: 0
> >        time_window_us: 976
> > 
> > 
> > as seen by the output of the command, the intel-rapl-mmio is causing the
> > throttling as it sets power_limit_uw to 30 watts (readonly). so the current fix
> > that i'm currently using is disabling the intel-rapl-mmio leaving only
> > the intel-rapl which sets power_limit_uw to 157watts using this
> > command: powercap-set -p intel-rapl-mmio -z 0 -e 0
> > 
> > this will lead to the laptop being able to reach it's maximum power
> > limit.
> > 
> > after doing this, when i change the platform profile through sysfs the
> > laptop will start behaving as described in the table above exactly like
> > windows.
> > 
> > in conclusion, the asus-wmi driver already has the platform profiles
> > (a.k.a fan profiles)
> > implemented and I think that the power throttling is caused by either
> > intel Power Capping Framework or asus bios.
> 
> Or the Intel Thermal Daemon somehow does not properly support intel-rapl-mmio
> or is not installed.

This was exactly it. the Intel Thermal Daemon wasn't installed. now
everything is working as expected!

Best regards,
Mohamed G.
Armin Wolf Oct. 23, 2024, 6:57 p.m. UTC | #10
Am 23.10.24 um 19:59 schrieb Mohamed Ghanmi:

> On Wed, Oct 23, 2024 at 06:31:17PM +0200, Armin Wolf wrote:
>> Am 23.10.24 um 16:44 schrieb Mohamed Ghanmi:
>>
>>> Hello !
>>> On Sun, Oct 20, 2024 at 09:42:45PM +0200, Armin Wolf wrote:
>>>> Am 20.10.24 um 21:05 schrieb Armin Wolf:
>>>>
>>>>> Am 20.10.24 um 08:50 schrieb Srinivas Pandruvada:
>>>>>
>>>>>> Some recent Asus laptops are supporting ASUS Intelligent Performance
>>>>>> Technology (AIPT). This solution allows users to have maximized CPU
>>>>>> performance in models with a chassis providing more thermal head room.
>>>>>> Refer to [1].
>>>>>>
>>>>>> There are major performance issues when Linux is installed on these
>>>>>> laptops compared to Windows install. One such report is published for
>>>>>> Graphics benchmarks on Asus ASUS Zenbook S 14 with Lunar Lake
>>>>>> processors [2].
>>>>>>
>>>>>> By default, these laptops are booting in "Whisper Mode" till OS power
>>>>>> management or tools change this to other AIPT mode. This "Whisper" mode
>>>>>> calls to set lower maximum and minimum RAPL (Running Average Power
>>>>>> Limit)
>>>>>> via thermal tables. On Linux this leads to lower performance even when
>>>>>> platform power profile is "balanced". This "Whisper" mode should
>>>>>> correspond to "quiet" mode.
>>>>>>
>>>>>> So, when AIPT is present change the default mode to "Standard" during
>>>>>> boot. Map the three platform power profile modes as follows:
>>>>>>
>>>>>> Power Profile Mode      AIPT mode
>>>>>> -----------------------------------
>>>>>> quiet            Whisper
>>>>>> balanced        Standard
>>>>>> performance        Performance
>>>>>> ------------------------------------
>>>>>>
>>>>>> Here AIPT mode can be detected by checking presese of "FANL" method
>>>>>> under
>>>>>> PNP HID "PNP0C14" and UID "ATK". If AIPT mode is present, this takes
>>>>>> precedence over the existing VIVO thermal policy. These modes are set
>>>>>> using "FANL" method.
>>>>>>
>>>>>> Although this “FANL” method is not used in the Asus WMI driver, users
>>>>>> have used this method from user space [3] to set AIPT modes. Used this
>>>>>> as a reference.
>>>>>>
>>>>>> Link:
>>>>>> https://www.asus.com/content/laptop-asus-intelligent-performance-technology-aipt/
>>>>>> # [1]
>>>>>> Reported-by: Michael Larabel <Michael@phoronix.com>
>>>>>> Closes: https://www.phoronix.com/review/lunar-lake-xe2/5 # [2]
>>>>>> Link: https://github.com/dominiksalvet/asus-fan-control/issues/151 # [3]
>>>>>> Tested-by: Casey Bowman <casey.g.bowman@intel.com>
>>>>>> Signed-off-by: Srinivas Pandruvada <srinivas.pandruvada@linux.intel.com>
>>>>>> ---
>>>>>>     drivers/platform/x86/asus-wmi.c | 93 +++++++++++++++++++++++++++++++--
>>>>>>     1 file changed, 89 insertions(+), 4 deletions(-)
>>>>>>
>>>>>> diff --git a/drivers/platform/x86/asus-wmi.c
>>>>>> b/drivers/platform/x86/asus-wmi.c
>>>>>> index 7a48220b4f5a..06689d0f98c7 100644
>>>>>> --- a/drivers/platform/x86/asus-wmi.c
>>>>>> +++ b/drivers/platform/x86/asus-wmi.c
>>>>>> @@ -100,6 +100,11 @@ module_param(fnlock_default, bool, 0444);
>>>>>>     #define ASUS_THROTTLE_THERMAL_POLICY_SILENT_VIVO    1
>>>>>>     #define ASUS_THROTTLE_THERMAL_POLICY_OVERBOOST_VIVO    2
>>>>>>
>>>>>> +#define AIPT_STANDARD                0
>>>>>> +#define AIPT_WHISPER                1
>>>>>> +#define AIPT_PERFORMANCE            2
>>>>>> +#define AIPT_FULL_SPEED                3
>>>>>> +
>>>>>>     #define PLATFORM_PROFILE_MAX 2
>>>>>>
>>>>>>     #define USB_INTEL_XUSB2PR        0xD0
>>>>>> @@ -333,6 +338,9 @@ struct asus_wmi {
>>>>>>         struct asus_wmi_debug debug;
>>>>>>
>>>>>>         struct asus_wmi_driver *driver;
>>>>>> +    acpi_handle acpi_mgmt_handle;
>>>>>> +    int asus_aipt_mode;
>>>>>> +    bool asus_aipt_present;
>>>>>>     };
>>>>>>
>>>>>>     /* WMI
>>>>>> ************************************************************************/
>>>>>> @@ -3804,6 +3812,19 @@ static ssize_t
>>>>>> throttle_thermal_policy_store(struct device *dev,
>>>>>>     static DEVICE_ATTR_RW(throttle_thermal_policy);
>>>>>>
>>>>>>     /* Platform profile
>>>>>> ***********************************************************/
>>>>>> +static int asus_wmi_write_aipt_mode(struct asus_wmi *asus, int
>>>>>> aipt_mode)
>>>>>> +{
>>>>>> +    int status;
>>>>>> +
>>>>>> +    status = acpi_execute_simple_method(asus->acpi_mgmt_handle,
>>>>>> "FANL", aipt_mode);
>>>>>> +    if (ACPI_FAILURE(status)) {
>>>>>> +        acpi_handle_info(asus->acpi_mgmt_handle, "FANL execute
>>>>>> failed\n");
>>>>>> +        return -EIO;
>>>>>> +    }
>>>>>> +
>>>>>> +    return 0;
>>>>>> +}
>>>>>> +
>>>>>>     static int asus_wmi_platform_profile_to_vivo(struct asus_wmi *asus,
>>>>>> int mode)
>>>>>>     {
>>>>>>         bool vivo;
>>>>>> @@ -3844,6 +3865,26 @@ static int
>>>>>> asus_wmi_platform_profile_mode_from_vivo(struct asus_wmi *asus, int m
>>>>>>         return mode;
>>>>>>     }
>>>>>>
>>>>>> +static int asus_wmi_aipt_platform_profile_get(struct asus_wmi *asus,
>>>>>> +                          enum platform_profile_option *profile)
>>>>>> +{
>>>>>> +    switch (asus->asus_aipt_mode) {
>>>>>> +    case AIPT_STANDARD:
>>>>>> +        *profile = PLATFORM_PROFILE_BALANCED;
>>>>>> +        break;
>>>>>> +    case AIPT_PERFORMANCE:
>>>>>> +        *profile = PLATFORM_PROFILE_PERFORMANCE;
>>>>>> +        break;
>>>>>> +    case AIPT_WHISPER:
>>>>>> +        *profile = PLATFORM_PROFILE_QUIET;
>>>>>> +        break;
>>>>>> +    default:
>>>>>> +        return -EINVAL;
>>>>>> +    }
>>>>>> +
>>>>>> +    return 0;
>>>>>> +}
>>>>>> +
>>>>>>     static int asus_wmi_platform_profile_get(struct
>>>>>> platform_profile_handler *pprof,
>>>>>>                         enum platform_profile_option *profile)
>>>>>>     {
>>>>>> @@ -3851,6 +3892,10 @@ static int
>>>>>> asus_wmi_platform_profile_get(struct platform_profile_handler *pprof,
>>>>>>         int tp;
>>>>>>
>>>>>>         asus = container_of(pprof, struct asus_wmi,
>>>>>> platform_profile_handler);
>>>>>> +
>>>>>> +    if (asus->asus_aipt_present)
>>>>>> +        return asus_wmi_aipt_platform_profile_get(asus, profile);
>>>>>> +
>>>>>>         tp = asus->throttle_thermal_policy_mode;
>>>>>>
>>>>>>         switch (asus_wmi_platform_profile_mode_from_vivo(asus, tp)) {
>>>>>> @@ -3874,26 +3919,42 @@ static int
>>>>>> asus_wmi_platform_profile_set(struct platform_profile_handler *pprof,
>>>>>>                         enum platform_profile_option profile)
>>>>>>     {
>>>>>>         struct asus_wmi *asus;
>>>>>> -    int tp;
>>>>>> +    int ret = 0, tp, aipt_mode;
>>>>>>
>>>>>>         asus = container_of(pprof, struct asus_wmi,
>>>>>> platform_profile_handler);
>>>>>>
>>>>>>         switch (profile) {
>>>>>>         case PLATFORM_PROFILE_PERFORMANCE:
>>>>>>             tp = ASUS_THROTTLE_THERMAL_POLICY_OVERBOOST;
>>>>>> +        aipt_mode = AIPT_PERFORMANCE;
>>>>>>             break;
>>>>>>         case PLATFORM_PROFILE_BALANCED:
>>>>>>             tp = ASUS_THROTTLE_THERMAL_POLICY_DEFAULT;
>>>>>> +        aipt_mode = AIPT_STANDARD;
>>>>>>             break;
>>>>>>         case PLATFORM_PROFILE_QUIET:
>>>>>>             tp = ASUS_THROTTLE_THERMAL_POLICY_SILENT;
>>>>>> +        aipt_mode = AIPT_WHISPER;
>>>>>>             break;
>>>>>>         default:
>>>>>>             return -EOPNOTSUPP;
>>>>>>         }
>>>>>>
>>>>>> -    asus->throttle_thermal_policy_mode =
>>>>>> asus_wmi_platform_profile_to_vivo(asus, tp);
>>>>>> -    return throttle_thermal_policy_write(asus);
>>>>>> +    if (asus->asus_aipt_present) {
>>>>>> +        ret = asus_wmi_write_aipt_mode(asus, aipt_mode);
>>>>>> +        if (!ret) {
>>>>>> +            asus->asus_aipt_mode = aipt_mode;
>>>>>> +            goto skip_vivo;
>>>>>> +        }
>>>>>> +    }
>>>>>> +
>>>>>> +    if (asus->throttle_thermal_policy_dev) {
>>>>>> +        asus->throttle_thermal_policy_mode =
>>>>>> asus_wmi_platform_profile_to_vivo(asus, tp);
>>>>>> +        ret = throttle_thermal_policy_write(asus);
>>>>>> +    }
>>>>>> +
>>>>>> +skip_vivo:
>>>>>> +    return ret;
>>>>>>     }
>>>>>>
>>>>>>     static int platform_profile_setup(struct asus_wmi *asus)
>>>>>> @@ -3905,7 +3966,7 @@ static int platform_profile_setup(struct
>>>>>> asus_wmi *asus)
>>>>>>          * Not an error if a component platform_profile relies on is
>>>>>> unavailable
>>>>>>          * so early return, skipping the setup of platform_profile.
>>>>>>          */
>>>>>> -    if (!asus->throttle_thermal_policy_dev)
>>>>>> +    if (!asus->throttle_thermal_policy_dev && !asus->asus_aipt_present)
>>>>>>             return 0;
>>>>>>
>>>>>>         dev_info(dev, "Using throttle_thermal_policy for
>>>>>> platform_profile support\n");
>>>>>> @@ -4538,6 +4599,7 @@ static int asus_wmi_sysfs_init(struct
>>>>>> platform_device *device)
>>>>>>     static int asus_wmi_platform_init(struct asus_wmi *asus)
>>>>>>     {
>>>>>>         struct device *dev = &asus->platform_device->dev;
>>>>>> +    struct acpi_device *adev;
>>>>>>         char *wmi_uid;
>>>>>>         int rv;
>>>>>>
>>>>>> @@ -4593,6 +4655,29 @@ static int asus_wmi_platform_init(struct
>>>>>> asus_wmi *asus)
>>>>>>             asus_wmi_set_devstate(ASUS_WMI_DEVID_CWAP,
>>>>>>                           asus->driver->quirks->wapf, NULL);
>>>>>>
>>>>>> +    /*
>>>>>> +     * Check presence of Intelligent Performance Technology (AIPT).
>>>>>> +     * If present store acpi handle and set asus_aipt_present to true.
>>>>>> +     */
>>>>>> +    adev = acpi_dev_get_first_match_dev("PNP0C14", "ATK", -1);
>>>>> Is there really no way of changing the AIPT mode through the WMI
>>>>> interface?
>>>>> I would prefer using the WMI interface if available, since the
>>>>> firmware might
>>>>> assume that FANL is only called through the WMI interface.
>>>>>
>>>>> Do you have a acpidump from a affected device?
>>>>>
>>>>> Thanks,
>>>>> Armin Wolf
>>>>>
>>>> I found a acpidump from a ASUS device with a matching FANL method. It seems that this method
>>>> can indeed be called using the WMI interface using the DEVS() WMI method:
>>>>
>>>> [WmiMethodId(1398162756), Implemented] void DEVS([in] uint32 Device_ID, [in] uint32 Control_status, [out] uint32 result);
>>>>
>>>> If Device_ID is 0x00110019, then Control_status is passed to the FANL ACPI method.
>>>>
>>>> It also seems that support for AIPT can be queried using the DSTS() WMI method:
>>>>
>>>> [WmiMethodId(1398035268), Implemented] void DSTS([in] uint32 Device_ID, [out] uint32 device_status);
>>>>
>>>> Using Device_ID 0x00110019, the returned device status seems to contain the following information:
>>>>
>>>> - 16-bit current AIPT mode
>>>> - 4-bit unknown value (possible values 2, 3 and 7, maybe number of supported modes or some kind of bitmap?)
>>>> - 1-bit with is set when (GGIV (0x0907000C) == One) is true
>>> I just saw this conversation and i think that the behaviour this
>>> patch will implement in the driver was already implemented in this patch
>>> that got added to kernel v6.12-rc3:
>>> https://lore.kernel.org/platform-driver-x86/20240609144849.2532-2-mohamed.ghanmi@supcom.tn/
>>>
>>> this patch introduced ASUS_WMI_DEVID_THROTTLE_THERMAL_POLICY_VIVO
>>> 0x00110019 which is the device_id that changes the fan profiles. the
>>> naming is not clear because it was initially intended to add support for
>>> fan profiles for vivobook laptops but it ended up adding support
>>> for a lot of modern laptops.
>> Nice, you are absolutely right.
>>
>> So this patch series is effectively already upstream, very good. I did some research and found out
>> that the status of this device id contains the following data:
>>
>> Status		Supported Modes
>> -------------------------------
>> 0x00[1]300[xx]	0 1 2
>> 0x000700[xx]	0 1 2
>> 0x000200[xx]	??? (ODV0)
>> 0x000700[xx]	0 1 2
>> 0x0a0700[xx]	??? (ODV0)
>>
>> While i have no clue about the meaning of the remaining bits, i can report that the first 8 Bits
>> contain the current thermal mode. Maybe adding support for this would be nice, so the current
>> thermal mode can be read directly from the hardware.
>>
>> I also found out that on some models the thermal mode actually modifies the ODV0 variable which
>> is consumed by int3400_thermal and exposed to the Intel Thermal Daemon. So maybe the lackluster
>> performance also has something to do with it.
>>
>>> a point that Srinivas Pandruvada mentioned about RAPL (Running Average Power Limit)
>>> is valid for a lot of modern vivobook and zenbook laptops but i think
>>> it's unrelated to fan profiles.
>>>
>>> a lot of asus laptops that have intel cpus suffer from power throttling.
>>> for exemple in my case using windows, changing fan profiles will lead to max power
>>> changing to the values indicated in the table below (asus vivobook 16x
>>> pro k6604) which leads to higher performance than linux
>>>
>>> fan Profile		power limit
>>> -----------------------------------
>>> Whisper			50watts
>>> Standard                120watts
>>> Performance		149watts
>>> ------------------------------------
>>>
>>> However in linux, even after changing to the appropriate fan profile,
>>> the power is still capped at 50watts and i found the reason why
>>>
>>> here is the results of using the powercap-info command:
>>>
>>> intel-rapl-mmio
>>>     enabled: 1
>>>     Zone 0
>>>       name: package-0
>>>       enabled: 1
>>>       max_energy_range_uj: 262143328850
>>>       Constraint 0
>>>         name: long_term
>>>         power_limit_uw: 30000000
>>>         time_window_us: 55967744
>>>         max_power_uw: 55000000
>>>       Constraint 1
>>>         name: short_term
>>>         power_limit_uw: 55000000
>>>         time_window_us: 2440
>>>         max_power_uw: 0
>>> intel-rapl
>>>     enabled: 1
>>>     Zone 0
>>>       name: package-0
>>>       enabled: 1
>>>       max_energy_range_uj: 262143328850
>>>       Constraint 0
>>>         name: long_term
>>>         power_limit_uw: 157000000
>>>         time_window_us: 55967744
>>>         max_power_uw: 55000000
>>>       Constraint 1
>>>         name: short_term
>>>         power_limit_uw: 157000000
>>>         time_window_us: 2440
>>>         max_power_uw: 0
>>>       Constraint 2
>>>         name: peak_power
>>>         power_limit_uw: 200000000
>>>         max_power_uw: 0
>>>       Zone 0:0
>>>         name: core
>>>         enabled: 0
>>>         max_energy_range_uj: 262143328850
>>>         Constraint 0
>>>           name: long_term
>>>           power_limit_uw: 0
>>>           time_window_us: 976
>>>       Zone 0:1
>>>         name: uncore
>>>         enabled: 0
>>>         max_energy_range_uj: 262143328850
>>>         Constraint 0
>>>           name: long_term
>>>           power_limit_uw: 0
>>>           time_window_us: 976
>>>     Zone 1
>>>       name: psys
>>>       enabled: 0
>>>       max_energy_range_uj: 262143328850
>>>       Constraint 0
>>>         name: long_term
>>>         power_limit_uw: 0
>>>         time_window_us: 27983872
>>>       Constraint 1
>>>         name: short_term
>>>         power_limit_uw: 0
>>>         time_window_us: 976
>>>
>>>
>>> as seen by the output of the command, the intel-rapl-mmio is causing the
>>> throttling as it sets power_limit_uw to 30 watts (readonly). so the current fix
>>> that i'm currently using is disabling the intel-rapl-mmio leaving only
>>> the intel-rapl which sets power_limit_uw to 157watts using this
>>> command: powercap-set -p intel-rapl-mmio -z 0 -e 0
>>>
>>> this will lead to the laptop being able to reach it's maximum power
>>> limit.
>>>
>>> after doing this, when i change the platform profile through sysfs the
>>> laptop will start behaving as described in the table above exactly like
>>> windows.
>>>
>>> in conclusion, the asus-wmi driver already has the platform profiles
>>> (a.k.a fan profiles)
>>> implemented and I think that the power throttling is caused by either
>>> intel Power Capping Framework or asus bios.
>> Or the Intel Thermal Daemon somehow does not properly support intel-rapl-mmio
>> or is not installed.
> This was exactly it. the Intel Thermal Daemon wasn't installed. now
> everything is working as expected!
>
> Best regards,
> Mohamed G.

Interesting.

Srinivas, can you verify that the Intel Thermal Daemon is installed on the affected
Asus machines?

I begin to wonder why this thermal daemon is a userspace component, stuff like thermal
management should use the thermal subsystem inside the kernel.

Thanks,
Armin Wolf
srinivas pandruvada Oct. 23, 2024, 7:34 p.m. UTC | #11
On Wed, 2024-10-23 at 10:15 +0200, Luke Jones wrote:
> On Sun, 20 Oct 2024, at 9:05 PM, Armin Wolf wrote:
> > Am 20.10.24 um 08:50 schrieb Srinivas Pandruvada:
> > > 

[...]

Hi Luke,

> > > +        */
> > > +       adev = acpi_dev_get_first_match_dev("PNP0C14", "ATK", -
> > > 1);
> > 
> > Is there really no way of changing the AIPT mode through the WMI
> > interface?
> > I would prefer using the WMI interface if available, since the
> > firmware might
> > assume that FANL is only called through the WMI interface.
> > 
> > Do you have a acpidump from a affected device?
> > 
> > Thanks,
> > Armin Wolf
> > 
> > > +       if (adev) {
> > > +               acpi_handle handle = acpi_device_handle(adev);
> > > +
> > > +               acpi_dev_put(adev);
> > > +
> > > +               if (!acpi_has_method(handle, "FANL"))
> > > +                       return 0;
> 
> Quite a few laptops have this method available, but may not actually
> do anything. Such as the following:
> 
> FX517ZM-dsdt.dsl
> 92885:        Method (FANL, 1, Serialized)
> 92886-        {
> 92887-            Return (One)
> 92888-        }

Correct. On this laptop my changes will hurt. So we must use WMI.

> 
> 

> While this one does (zenbook duo):
> 
> UX8402.dsl
> 88837:                Method (FANL, 1, Serialized)
> 88838-                {
> 88839-                    ODV0 = Arg0

This will trigger to load a new thermal and power table based on the
condition set.

> 88840-                    If ((^^PC00.PEG1.PXP._STA == One))
> --
> 89041:                    Return (FANL (IIA0))
> 89042-                }
> 89043-
> 89044-                If ((Local0 == 0x4647574D))
> --
> 89604:                        FANL (IIA1)
> 89605-                        Return (One)
> 89606-                    }
> 89607-
> 
> I've discovered the majority of WMI methods, you can see them here:
> https://gitlab.com/asus-linux/reverse-engineering/-/blob/master/WMI_SPEC.md?ref_type=heads
> 
> There is a "whisper mode" WMI  method, but I've not done much around
> it.
> 
> I also have a large collection of DSL if that is helpful
> https://gitlab.com/asus-linux/reverse-engineering/-/tree/master/dsl-collection?ref_type=heads
> 
> It seems that because I have access only to the ROG dlls at this time
> I may have missed the WMI method: 0x00110019, this is likely what you
> need as it gets FANF, and sets FANL
> 
> ❯ rg 0x00110019 -B3 -A3 UX8402.dsl 
> 89281-                        Return (0x00010000)
> 89282-                    }
> 89283-
> 89284:                    If ((IIA0 == 0x00110019))
> 89285-                    {
> 89286-                        Local0 = FANF /* \_SB_.FANF */
> 89287-                        Local1 = 0x00070000
> --
> 89599-                        Return (One)
> 89600-                    }
> 89601-
> 89602:                    If ((IIA0 == 0x00110019))
> 89603-                    {
> 89604-                        FANL (IIA1)
> 89605-                        Return (One)
> 
> Hopefully this is helpful,


You have been very helpful. Thanks for that. I can make work with WMI
methods. Waiting for Asus to give feedback.

Currently on vacation for two weeks. Hope things gets sorted outed out
before I return.

Thanks,
Srinivas



> 
> Regards,
> Luke.
> 
> P.S: If any info is discovered that I am lacking in my repo it would
> be highly appreciated if a PR added it.
> 
> > > +               asus->acpi_mgmt_handle = handle;
> > > +               asus->asus_aipt_present = true;
> > > +               dev_info(dev, "ASUS Intelligent Performance
> > > Technology (AIPT) is present\n");
> > > +               /*
> > > +                * Set the mode corresponding to default Linux
> > > platform power
> > > +                * profile Balanced
> > > +                */
> > > +               asus_wmi_write_aipt_mode(asus, AIPT_STANDARD);
> > > +       }
> > > +
> > >         return 0;
> > >   }
> > >
srinivas pandruvada Oct. 23, 2024, 8:15 p.m. UTC | #12
On Wed, 2024-10-23 at 20:57 +0200, Armin Wolf wrote:
> Am 23.10.24 um 19:59 schrieb Mohamed Ghanmi:
> 
> > On Wed, Oct 23, 2024 at 06:31:17PM +0200, Armin Wolf wrote:
> > > Am 23.10.24 um 16:44 schrieb Mohamed Ghanmi:
> > > 
> > > > Hello !
> > > > On Sun, Oct 20, 2024 at 09:42:45PM +0200, Armin Wolf wrote:
> > > > > Am 20.10.24 um 21:05 schrieb Armin Wolf:
> > > > > 
> > > > > > Am 20.10.24 um 08:50 schrieb Srinivas Pandruvada:
> > > > > > 
> > > > > > > Some recent Asus laptops are supporting ASUS Intelligent
> > > > > > > Performance
> > > > > > > Technology (AIPT). This solution allows users to have
> > > > > > > maximized CPU
> > > > > > > performance in models with a chassis providing more
> > > > > > > thermal head room.
> > > > > > > Refer to [1].
> > > > > > > 
> > > > > > > There are major performance issues when Linux is
> > > > > > > installed on these
> > > > > > > laptops compared to Windows install. One such report is
> > > > > > > published for
> > > > > > > Graphics benchmarks on Asus ASUS Zenbook S 14 with Lunar
> > > > > > > Lake
> > > > > > > processors [2].
> > > > > > > 
> > > > > > > By default, these laptops are booting in "Whisper Mode"
> > > > > > > till OS power
> > > > > > > management or tools change this to other AIPT mode. This
> > > > > > > "Whisper" mode
> > > > > > > calls to set lower maximum and minimum RAPL (Running
> > > > > > > Average Power
> > > > > > > Limit)
> > > > > > > via thermal tables. On Linux this leads to lower
> > > > > > > performance even when
> > > > > > > platform power profile is "balanced". This "Whisper" mode
> > > > > > > should
> > > > > > > correspond to "quiet" mode.
> > > > > > > 
> > > > > > > So, when AIPT is present change the default mode to
> > > > > > > "Standard" during
> > > > > > > boot. Map the three platform power profile modes as
> > > > > > > follows:
> > > > > > > 
> > > > > > > Power Profile Mode      AIPT mode
> > > > > > > -----------------------------------
> > > > > > > quiet            Whisper
> > > > > > > balanced        Standard
> > > > > > > performance        Performance
> > > > > > > ------------------------------------
> > > > > > > 
> > > > > > > Here AIPT mode can be detected by checking presese of
> > > > > > > "FANL" method
> > > > > > > under
> > > > > > > PNP HID "PNP0C14" and UID "ATK". If AIPT mode is present,
> > > > > > > this takes
> > > > > > > precedence over the existing VIVO thermal policy. These
> > > > > > > modes are set
> > > > > > > using "FANL" method.
> > > > > > > 
> > > > > > > Although this “FANL” method is not used in the Asus WMI
> > > > > > > driver, users
> > > > > > > have used this method from user space [3] to set AIPT
> > > > > > > modes. Used this
> > > > > > > as a reference.
> > > > > > > 
> > > > > > > Link:
> > > > > > > https://www.asus.com/content/laptop-asus-intelligent-performance-technology-aipt/
> > > > > > > # [1]
> > > > > > > Reported-by: Michael Larabel <Michael@phoronix.com>
> > > > > > > Closes:
> > > > > > > https://www.phoronix.com/review/lunar-lake-xe2/5 # [2]
> > > > > > > Link:
> > > > > > > https://github.com/dominiksalvet/asus-fan-control/issues/151
> > > > > > >  # [3]
> > > > > > > Tested-by: Casey Bowman <casey.g.bowman@intel.com>
> > > > > > > Signed-off-by: Srinivas Pandruvada
> > > > > > > <srinivas.pandruvada@linux.intel.com>
> > > > > > > ---
> > > > > > >     drivers/platform/x86/asus-wmi.c | 93
> > > > > > > +++++++++++++++++++++++++++++++--
> > > > > > >     1 file changed, 89 insertions(+), 4 deletions(-)
> > > > > > > 
> > > > > > > diff --git a/drivers/platform/x86/asus-wmi.c
> > > > > > > b/drivers/platform/x86/asus-wmi.c
> > > > > > > index 7a48220b4f5a..06689d0f98c7 100644
> > > > > > > --- a/drivers/platform/x86/asus-wmi.c
> > > > > > > +++ b/drivers/platform/x86/asus-wmi.c
> > > > > > > @@ -100,6 +100,11 @@ module_param(fnlock_default, bool,
> > > > > > > 0444);
> > > > > > >     #define ASUS_THROTTLE_THERMAL_POLICY_SILENT_VIVO    1
> > > > > > >     #define
> > > > > > > ASUS_THROTTLE_THERMAL_POLICY_OVERBOOST_VIVO    2
> > > > > > > 
> > > > > > > +#define AIPT_STANDARD                0
> > > > > > > +#define AIPT_WHISPER                1
> > > > > > > +#define AIPT_PERFORMANCE            2
> > > > > > > +#define AIPT_FULL_SPEED                3
> > > > > > > +
> > > > > > >     #define PLATFORM_PROFILE_MAX 2
> > > > > > > 
> > > > > > >     #define USB_INTEL_XUSB2PR        0xD0
> > > > > > > @@ -333,6 +338,9 @@ struct asus_wmi {
> > > > > > >         struct asus_wmi_debug debug;
> > > > > > > 
> > > > > > >         struct asus_wmi_driver *driver;
> > > > > > > +    acpi_handle acpi_mgmt_handle;
> > > > > > > +    int asus_aipt_mode;
> > > > > > > +    bool asus_aipt_present;
> > > > > > >     };
> > > > > > > 
> > > > > > >     /* WMI
> > > > > > > *********************************************************
> > > > > > > ***************/
> > > > > > > @@ -3804,6 +3812,19 @@ static ssize_t
> > > > > > > throttle_thermal_policy_store(struct device *dev,
> > > > > > >     static DEVICE_ATTR_RW(throttle_thermal_policy);
> > > > > > > 
> > > > > > >     /* Platform profile
> > > > > > > *********************************************************
> > > > > > > **/
> > > > > > > +static int asus_wmi_write_aipt_mode(struct asus_wmi
> > > > > > > *asus, int
> > > > > > > aipt_mode)
> > > > > > > +{
> > > > > > > +    int status;
> > > > > > > +
> > > > > > > +    status = acpi_execute_simple_method(asus-
> > > > > > > >acpi_mgmt_handle,
> > > > > > > "FANL", aipt_mode);
> > > > > > > +    if (ACPI_FAILURE(status)) {
> > > > > > > +        acpi_handle_info(asus->acpi_mgmt_handle, "FANL
> > > > > > > execute
> > > > > > > failed\n");
> > > > > > > +        return -EIO;
> > > > > > > +    }
> > > > > > > +
> > > > > > > +    return 0;
> > > > > > > +}
> > > > > > > +
> > > > > > >     static int asus_wmi_platform_profile_to_vivo(struct
> > > > > > > asus_wmi *asus,
> > > > > > > int mode)
> > > > > > >     {
> > > > > > >         bool vivo;
> > > > > > > @@ -3844,6 +3865,26 @@ static int
> > > > > > > asus_wmi_platform_profile_mode_from_vivo(struct asus_wmi
> > > > > > > *asus, int m
> > > > > > >         return mode;
> > > > > > >     }
> > > > > > > 
> > > > > > > +static int asus_wmi_aipt_platform_profile_get(struct
> > > > > > > asus_wmi *asus,
> > > > > > > +                          enum platform_profile_option
> > > > > > > *profile)
> > > > > > > +{
> > > > > > > +    switch (asus->asus_aipt_mode) {
> > > > > > > +    case AIPT_STANDARD:
> > > > > > > +        *profile = PLATFORM_PROFILE_BALANCED;
> > > > > > > +        break;
> > > > > > > +    case AIPT_PERFORMANCE:
> > > > > > > +        *profile = PLATFORM_PROFILE_PERFORMANCE;
> > > > > > > +        break;
> > > > > > > +    case AIPT_WHISPER:
> > > > > > > +        *profile = PLATFORM_PROFILE_QUIET;
> > > > > > > +        break;
> > > > > > > +    default:
> > > > > > > +        return -EINVAL;
> > > > > > > +    }
> > > > > > > +
> > > > > > > +    return 0;
> > > > > > > +}
> > > > > > > +
> > > > > > >     static int asus_wmi_platform_profile_get(struct
> > > > > > > platform_profile_handler *pprof,
> > > > > > >                         enum platform_profile_option
> > > > > > > *profile)
> > > > > > >     {
> > > > > > > @@ -3851,6 +3892,10 @@ static int
> > > > > > > asus_wmi_platform_profile_get(struct
> > > > > > > platform_profile_handler *pprof,
> > > > > > >         int tp;
> > > > > > > 
> > > > > > >         asus = container_of(pprof, struct asus_wmi,
> > > > > > > platform_profile_handler);
> > > > > > > +
> > > > > > > +    if (asus->asus_aipt_present)
> > > > > > > +        return asus_wmi_aipt_platform_profile_get(asus,
> > > > > > > profile);
> > > > > > > +
> > > > > > >         tp = asus->throttle_thermal_policy_mode;
> > > > > > > 
> > > > > > >         switch
> > > > > > > (asus_wmi_platform_profile_mode_from_vivo(asus, tp)) {
> > > > > > > @@ -3874,26 +3919,42 @@ static int
> > > > > > > asus_wmi_platform_profile_set(struct
> > > > > > > platform_profile_handler *pprof,
> > > > > > >                         enum platform_profile_option
> > > > > > > profile)
> > > > > > >     {
> > > > > > >         struct asus_wmi *asus;
> > > > > > > -    int tp;
> > > > > > > +    int ret = 0, tp, aipt_mode;
> > > > > > > 
> > > > > > >         asus = container_of(pprof, struct asus_wmi,
> > > > > > > platform_profile_handler);
> > > > > > > 
> > > > > > >         switch (profile) {
> > > > > > >         case PLATFORM_PROFILE_PERFORMANCE:
> > > > > > >             tp = ASUS_THROTTLE_THERMAL_POLICY_OVERBOOST;
> > > > > > > +        aipt_mode = AIPT_PERFORMANCE;
> > > > > > >             break;
> > > > > > >         case PLATFORM_PROFILE_BALANCED:
> > > > > > >             tp = ASUS_THROTTLE_THERMAL_POLICY_DEFAULT;
> > > > > > > +        aipt_mode = AIPT_STANDARD;
> > > > > > >             break;
> > > > > > >         case PLATFORM_PROFILE_QUIET:
> > > > > > >             tp = ASUS_THROTTLE_THERMAL_POLICY_SILENT;
> > > > > > > +        aipt_mode = AIPT_WHISPER;
> > > > > > >             break;
> > > > > > >         default:
> > > > > > >             return -EOPNOTSUPP;
> > > > > > >         }
> > > > > > > 
> > > > > > > -    asus->throttle_thermal_policy_mode =
> > > > > > > asus_wmi_platform_profile_to_vivo(asus, tp);
> > > > > > > -    return throttle_thermal_policy_write(asus);
> > > > > > > +    if (asus->asus_aipt_present) {
> > > > > > > +        ret = asus_wmi_write_aipt_mode(asus, aipt_mode);
> > > > > > > +        if (!ret) {
> > > > > > > +            asus->asus_aipt_mode = aipt_mode;
> > > > > > > +            goto skip_vivo;
> > > > > > > +        }
> > > > > > > +    }
> > > > > > > +
> > > > > > > +    if (asus->throttle_thermal_policy_dev) {
> > > > > > > +        asus->throttle_thermal_policy_mode =
> > > > > > > asus_wmi_platform_profile_to_vivo(asus, tp);
> > > > > > > +        ret = throttle_thermal_policy_write(asus);
> > > > > > > +    }
> > > > > > > +
> > > > > > > +skip_vivo:
> > > > > > > +    return ret;
> > > > > > >     }
> > > > > > > 
> > > > > > >     static int platform_profile_setup(struct asus_wmi
> > > > > > > *asus)
> > > > > > > @@ -3905,7 +3966,7 @@ static int
> > > > > > > platform_profile_setup(struct
> > > > > > > asus_wmi *asus)
> > > > > > >          * Not an error if a component platform_profile
> > > > > > > relies on is
> > > > > > > unavailable
> > > > > > >          * so early return, skipping the setup of
> > > > > > > platform_profile.
> > > > > > >          */
> > > > > > > -    if (!asus->throttle_thermal_policy_dev)
> > > > > > > +    if (!asus->throttle_thermal_policy_dev && !asus-
> > > > > > > >asus_aipt_present)
> > > > > > >             return 0;
> > > > > > > 
> > > > > > >         dev_info(dev, "Using throttle_thermal_policy for
> > > > > > > platform_profile support\n");
> > > > > > > @@ -4538,6 +4599,7 @@ static int
> > > > > > > asus_wmi_sysfs_init(struct
> > > > > > > platform_device *device)
> > > > > > >     static int asus_wmi_platform_init(struct asus_wmi
> > > > > > > *asus)
> > > > > > >     {
> > > > > > >         struct device *dev = &asus->platform_device->dev;
> > > > > > > +    struct acpi_device *adev;
> > > > > > >         char *wmi_uid;
> > > > > > >         int rv;
> > > > > > > 
> > > > > > > @@ -4593,6 +4655,29 @@ static int
> > > > > > > asus_wmi_platform_init(struct
> > > > > > > asus_wmi *asus)
> > > > > > >             asus_wmi_set_devstate(ASUS_WMI_DEVID_CWAP,
> > > > > > >                           asus->driver->quirks->wapf,
> > > > > > > NULL);
> > > > > > > 
> > > > > > > +    /*
> > > > > > > +     * Check presence of Intelligent Performance
> > > > > > > Technology (AIPT).
> > > > > > > +     * If present store acpi handle and set
> > > > > > > asus_aipt_present to true.
> > > > > > > +     */
> > > > > > > +    adev = acpi_dev_get_first_match_dev("PNP0C14",
> > > > > > > "ATK", -1);
> > > > > > Is there really no way of changing the AIPT mode through
> > > > > > the WMI
> > > > > > interface?
> > > > > > I would prefer using the WMI interface if available, since
> > > > > > the
> > > > > > firmware might
> > > > > > assume that FANL is only called through the WMI interface.
> > > > > > 
> > > > > > Do you have a acpidump from a affected device?
> > > > > > 
> > > > > > Thanks,
> > > > > > Armin Wolf
> > > > > > 
> > > > > I found a acpidump from a ASUS device with a matching FANL
> > > > > method. It seems that this method
> > > > > can indeed be called using the WMI interface using the DEVS()
> > > > > WMI method:
> > > > > 
> > > > > [WmiMethodId(1398162756), Implemented] void DEVS([in] uint32
> > > > > Device_ID, [in] uint32 Control_status, [out] uint32 result);
> > > > > 
> > > > > If Device_ID is 0x00110019, then Control_status is passed to
> > > > > the FANL ACPI method.
> > > > > 
> > > > > It also seems that support for AIPT can be queried using the
> > > > > DSTS() WMI method:
> > > > > 
> > > > > [WmiMethodId(1398035268), Implemented] void DSTS([in] uint32
> > > > > Device_ID, [out] uint32 device_status);
> > > > > 
> > > > > Using Device_ID 0x00110019, the returned device status seems
> > > > > to contain the following information:
> > > > > 
> > > > > - 16-bit current AIPT mode
> > > > > - 4-bit unknown value (possible values 2, 3 and 7, maybe
> > > > > number of supported modes or some kind of bitmap?)
> > > > > - 1-bit with is set when (GGIV (0x0907000C) == One) is true
> > > > I just saw this conversation and i think that the behaviour
> > > > this
> > > > patch will implement in the driver was already implemented in
> > > > this patch
> > > > that got added to kernel v6.12-rc3:
> > > > https://lore.kernel.org/platform-driver-x86/20240609144849.2532-2-mohamed.ghanmi@supcom.tn/
> > > > 
> > > > this patch introduced
> > > > ASUS_WMI_DEVID_THROTTLE_THERMAL_POLICY_VIVO
> > > > 0x00110019 which is the device_id that changes the fan
> > > > profiles. the
> > > > naming is not clear because it was initially intended to add
> > > > support for
> > > > fan profiles for vivobook laptops but it ended up adding
> > > > support
> > > > for a lot of modern laptops.
> > > Nice, you are absolutely right.
> > > 
> > > So this patch series is effectively already upstream, very good.
> > > I did some research and found out
> > > that the status of this device id contains the following data:
> > > 
> > > Status          Supported Modes
> > > -------------------------------
> > > 0x00[1]300[xx]  0 1 2
> > > 0x000700[xx]    0 1 2
> > > 0x000200[xx]    ??? (ODV0)
> > > 0x000700[xx]    0 1 2
> > > 0x0a0700[xx]    ??? (ODV0)
> > > 
> > > While i have no clue about the meaning of the remaining bits, i
> > > can report that the first 8 Bits
> > > contain the current thermal mode. Maybe adding support for this
> > > would be nice, so the current
> > > thermal mode can be read directly from the hardware.
> > > 
> > > I also found out that on some models the thermal mode actually
> > > modifies the ODV0 variable which
> > > is consumed by int3400_thermal and exposed to the Intel Thermal
> > > Daemon. So maybe the lackluster
> > > performance also has something to do with it.
> > > 
> > > > a point that Srinivas Pandruvada mentioned about RAPL (Running
> > > > Average Power Limit)
> > > > is valid for a lot of modern vivobook and zenbook laptops but i
> > > > think
> > > > it's unrelated to fan profiles.
> > > > 
> > > > a lot of asus laptops that have intel cpus suffer from power
> > > > throttling.
> > > > for exemple in my case using windows, changing fan profiles
> > > > will lead to max power
> > > > changing to the values indicated in the table below (asus
> > > > vivobook 16x
> > > > pro k6604) which leads to higher performance than linux
> > > > 
> > > > fan Profile             power limit
> > > > -----------------------------------
> > > > Whisper                 50watts
> > > > Standard                120watts
> > > > Performance             149watts
> > > > ------------------------------------
> > > > 
> > > > However in linux, even after changing to the appropriate fan
> > > > profile,
> > > > the power is still capped at 50watts and i found the reason why
> > > > 
> > > > here is the results of using the powercap-info command:
> > > > 
> > > > intel-rapl-mmio
> > > >     enabled: 1
> > > >     Zone 0
> > > >       name: package-0
> > > >       enabled: 1
> > > >       max_energy_range_uj: 262143328850
> > > >       Constraint 0
> > > >         name: long_term
> > > >         power_limit_uw: 30000000
> > > >         time_window_us: 55967744
> > > >         max_power_uw: 55000000
> > > >       Constraint 1
> > > >         name: short_term
> > > >         power_limit_uw: 55000000
> > > >         time_window_us: 2440
> > > >         max_power_uw: 0
> > > > intel-rapl
> > > >     enabled: 1
> > > >     Zone 0
> > > >       name: package-0
> > > >       enabled: 1
> > > >       max_energy_range_uj: 262143328850
> > > >       Constraint 0
> > > >         name: long_term
> > > >         power_limit_uw: 157000000
> > > >         time_window_us: 55967744
> > > >         max_power_uw: 55000000
> > > >       Constraint 1
> > > >         name: short_term
> > > >         power_limit_uw: 157000000
> > > >         time_window_us: 2440
> > > >         max_power_uw: 0
> > > >       Constraint 2
> > > >         name: peak_power
> > > >         power_limit_uw: 200000000
> > > >         max_power_uw: 0
> > > >       Zone 0:0
> > > >         name: core
> > > >         enabled: 0
> > > >         max_energy_range_uj: 262143328850
> > > >         Constraint 0
> > > >           name: long_term
> > > >           power_limit_uw: 0
> > > >           time_window_us: 976
> > > >       Zone 0:1
> > > >         name: uncore
> > > >         enabled: 0
> > > >         max_energy_range_uj: 262143328850
> > > >         Constraint 0
> > > >           name: long_term
> > > >           power_limit_uw: 0
> > > >           time_window_us: 976
> > > >     Zone 1
> > > >       name: psys
> > > >       enabled: 0
> > > >       max_energy_range_uj: 262143328850
> > > >       Constraint 0
> > > >         name: long_term
> > > >         power_limit_uw: 0
> > > >         time_window_us: 27983872
> > > >       Constraint 1
> > > >         name: short_term
> > > >         power_limit_uw: 0
> > > >         time_window_us: 976
> > > > 
> > > > 
> > > > as seen by the output of the command, the intel-rapl-mmio is
> > > > causing the
> > > > throttling as it sets power_limit_uw to 30 watts (readonly). so
> > > > the current fix
> > > > that i'm currently using is disabling the intel-rapl-mmio
> > > > leaving only
> > > > the intel-rapl which sets power_limit_uw to 157watts using this
> > > > command: powercap-set -p intel-rapl-mmio -z 0 -e 0
> > > > 
> > > > this will lead to the laptop being able to reach it's maximum
> > > > power
> > > > limit.
> > > > 
> > > > after doing this, when i change the platform profile through
> > > > sysfs the
> > > > laptop will start behaving as described in the table above
> > > > exactly like
> > > > windows.
> > > > 
> > > > in conclusion, the asus-wmi driver already has the platform
> > > > profiles
> > > > (a.k.a fan profiles)
> > > > implemented and I think that the power throttling is caused by
> > > > either
> > > > intel Power Capping Framework or asus bios.
> > > Or the Intel Thermal Daemon somehow does not properly support
> > > intel-rapl-mmio
> > > or is not installed.
> > This was exactly it. the Intel Thermal Daemon wasn't installed. now
> > everything is working as expected!
> > 
> > Best regards,
> > Mohamed G.
> 
> Interesting.
> 
> Srinivas, can you verify that the Intel Thermal Daemon is installed
> on the affected
> Asus machines?
> 
> I begin to wonder why this thermal daemon is a userspace component,
> stuff like thermal
> management should use the thermal subsystem inside the kernel.

Thanks for detailed analysis here.

Here the problem is not thermal daemon or INT340x (I am author of
both).

The ODVP variable is input into thermal tables. These thermal tables
are defined by Asus via DTT tables. This results in matching certain
max and min power limits and also various temperature limits.

By default the laptop in question will boot with max limit of 17W,
which is limit for whisper mode match based on ODVP variables. There is
a SEN1 limit of 50C, once the limit reaches to 50C, you need to
throttle upto 12W as per thermal table.

If you stop thermald, yes, you will stay in 17W, so you will not see
throttle but your SEN1 (seems skin limit) limit will be violated.
Also if you remove the rapl_mmio driver, that will also work as no
means to set power limits.

Windows will do exactly same. Meeting thermal limit is a requirement.

But on Windows this ODVP variable will be set to 0 to match standard
mode. This will result in matching rules which will set the max power
to 22W and min to 17W also increase thermal limit to 55C. So
essentially lost 5W of performance.

Here WMI method as you correctly found out matching VIVO thermal
policy. But it will not set ODVP variable unless you call a WMI method
to set the mode via DEVS() on the same device ID. So although platform
power policy will say "balanced" it is actually "Whisper" for thermal
policy. On Windows when system boots the Asus service will set to
standard and will set the ODVP variable to 0 and will match the correct
table.

After Luke's help, I can do a work around from user space to change the
power policy to any other policy than balanced and then again set to
balance. This will result in setting the policy to standard via DEVS()
and also set the correct ODVP variable.

This driver on unload change the vivo thermal policy to default. But
doesn't change that to default on load time to match the default
platform power policy. So rmmod and modprobe of driver should also fix.

Thanks,
Srinivas









> 
> Thanks,
> Armin Wolf
>
Armin Wolf Oct. 23, 2024, 8:32 p.m. UTC | #13
Am 23.10.24 um 22:15 schrieb srinivas pandruvada:

> On Wed, 2024-10-23 at 20:57 +0200, Armin Wolf wrote:
>> Am 23.10.24 um 19:59 schrieb Mohamed Ghanmi:
>>
>>> On Wed, Oct 23, 2024 at 06:31:17PM +0200, Armin Wolf wrote:
>>>> Am 23.10.24 um 16:44 schrieb Mohamed Ghanmi:
>>>>
>>>>> Hello !
>>>>> On Sun, Oct 20, 2024 at 09:42:45PM +0200, Armin Wolf wrote:
>>>>>> Am 20.10.24 um 21:05 schrieb Armin Wolf:
>>>>>>
>>>>>>> Am 20.10.24 um 08:50 schrieb Srinivas Pandruvada:
>>>>>>>
>>>>>>>> Some recent Asus laptops are supporting ASUS Intelligent
>>>>>>>> Performance
>>>>>>>> Technology (AIPT). This solution allows users to have
>>>>>>>> maximized CPU
>>>>>>>> performance in models with a chassis providing more
>>>>>>>> thermal head room.
>>>>>>>> Refer to [1].
>>>>>>>>
>>>>>>>> There are major performance issues when Linux is
>>>>>>>> installed on these
>>>>>>>> laptops compared to Windows install. One such report is
>>>>>>>> published for
>>>>>>>> Graphics benchmarks on Asus ASUS Zenbook S 14 with Lunar
>>>>>>>> Lake
>>>>>>>> processors [2].
>>>>>>>>
>>>>>>>> By default, these laptops are booting in "Whisper Mode"
>>>>>>>> till OS power
>>>>>>>> management or tools change this to other AIPT mode. This
>>>>>>>> "Whisper" mode
>>>>>>>> calls to set lower maximum and minimum RAPL (Running
>>>>>>>> Average Power
>>>>>>>> Limit)
>>>>>>>> via thermal tables. On Linux this leads to lower
>>>>>>>> performance even when
>>>>>>>> platform power profile is "balanced". This "Whisper" mode
>>>>>>>> should
>>>>>>>> correspond to "quiet" mode.
>>>>>>>>
>>>>>>>> So, when AIPT is present change the default mode to
>>>>>>>> "Standard" during
>>>>>>>> boot. Map the three platform power profile modes as
>>>>>>>> follows:
>>>>>>>>
>>>>>>>> Power Profile Mode      AIPT mode
>>>>>>>> -----------------------------------
>>>>>>>> quiet            Whisper
>>>>>>>> balanced        Standard
>>>>>>>> performance        Performance
>>>>>>>> ------------------------------------
>>>>>>>>
>>>>>>>> Here AIPT mode can be detected by checking presese of
>>>>>>>> "FANL" method
>>>>>>>> under
>>>>>>>> PNP HID "PNP0C14" and UID "ATK". If AIPT mode is present,
>>>>>>>> this takes
>>>>>>>> precedence over the existing VIVO thermal policy. These
>>>>>>>> modes are set
>>>>>>>> using "FANL" method.
>>>>>>>>
>>>>>>>> Although this “FANL” method is not used in the Asus WMI
>>>>>>>> driver, users
>>>>>>>> have used this method from user space [3] to set AIPT
>>>>>>>> modes. Used this
>>>>>>>> as a reference.
>>>>>>>>
>>>>>>>> Link:
>>>>>>>> https://www.asus.com/content/laptop-asus-intelligent-performance-technology-aipt/
>>>>>>>> # [1]
>>>>>>>> Reported-by: Michael Larabel <Michael@phoronix.com>
>>>>>>>> Closes:
>>>>>>>> https://www.phoronix.com/review/lunar-lake-xe2/5 # [2]
>>>>>>>> Link:
>>>>>>>> https://github.com/dominiksalvet/asus-fan-control/issues/151
>>>>>>>>   # [3]
>>>>>>>> Tested-by: Casey Bowman <casey.g.bowman@intel.com>
>>>>>>>> Signed-off-by: Srinivas Pandruvada
>>>>>>>> <srinivas.pandruvada@linux.intel.com>
>>>>>>>> ---
>>>>>>>>      drivers/platform/x86/asus-wmi.c | 93
>>>>>>>> +++++++++++++++++++++++++++++++--
>>>>>>>>      1 file changed, 89 insertions(+), 4 deletions(-)
>>>>>>>>
>>>>>>>> diff --git a/drivers/platform/x86/asus-wmi.c
>>>>>>>> b/drivers/platform/x86/asus-wmi.c
>>>>>>>> index 7a48220b4f5a..06689d0f98c7 100644
>>>>>>>> --- a/drivers/platform/x86/asus-wmi.c
>>>>>>>> +++ b/drivers/platform/x86/asus-wmi.c
>>>>>>>> @@ -100,6 +100,11 @@ module_param(fnlock_default, bool,
>>>>>>>> 0444);
>>>>>>>>      #define ASUS_THROTTLE_THERMAL_POLICY_SILENT_VIVO    1
>>>>>>>>      #define
>>>>>>>> ASUS_THROTTLE_THERMAL_POLICY_OVERBOOST_VIVO    2
>>>>>>>>
>>>>>>>> +#define AIPT_STANDARD                0
>>>>>>>> +#define AIPT_WHISPER                1
>>>>>>>> +#define AIPT_PERFORMANCE            2
>>>>>>>> +#define AIPT_FULL_SPEED                3
>>>>>>>> +
>>>>>>>>      #define PLATFORM_PROFILE_MAX 2
>>>>>>>>
>>>>>>>>      #define USB_INTEL_XUSB2PR        0xD0
>>>>>>>> @@ -333,6 +338,9 @@ struct asus_wmi {
>>>>>>>>          struct asus_wmi_debug debug;
>>>>>>>>
>>>>>>>>          struct asus_wmi_driver *driver;
>>>>>>>> +    acpi_handle acpi_mgmt_handle;
>>>>>>>> +    int asus_aipt_mode;
>>>>>>>> +    bool asus_aipt_present;
>>>>>>>>      };
>>>>>>>>
>>>>>>>>      /* WMI
>>>>>>>> *********************************************************
>>>>>>>> ***************/
>>>>>>>> @@ -3804,6 +3812,19 @@ static ssize_t
>>>>>>>> throttle_thermal_policy_store(struct device *dev,
>>>>>>>>      static DEVICE_ATTR_RW(throttle_thermal_policy);
>>>>>>>>
>>>>>>>>      /* Platform profile
>>>>>>>> *********************************************************
>>>>>>>> **/
>>>>>>>> +static int asus_wmi_write_aipt_mode(struct asus_wmi
>>>>>>>> *asus, int
>>>>>>>> aipt_mode)
>>>>>>>> +{
>>>>>>>> +    int status;
>>>>>>>> +
>>>>>>>> +    status = acpi_execute_simple_method(asus-
>>>>>>>>> acpi_mgmt_handle,
>>>>>>>> "FANL", aipt_mode);
>>>>>>>> +    if (ACPI_FAILURE(status)) {
>>>>>>>> +        acpi_handle_info(asus->acpi_mgmt_handle, "FANL
>>>>>>>> execute
>>>>>>>> failed\n");
>>>>>>>> +        return -EIO;
>>>>>>>> +    }
>>>>>>>> +
>>>>>>>> +    return 0;
>>>>>>>> +}
>>>>>>>> +
>>>>>>>>      static int asus_wmi_platform_profile_to_vivo(struct
>>>>>>>> asus_wmi *asus,
>>>>>>>> int mode)
>>>>>>>>      {
>>>>>>>>          bool vivo;
>>>>>>>> @@ -3844,6 +3865,26 @@ static int
>>>>>>>> asus_wmi_platform_profile_mode_from_vivo(struct asus_wmi
>>>>>>>> *asus, int m
>>>>>>>>          return mode;
>>>>>>>>      }
>>>>>>>>
>>>>>>>> +static int asus_wmi_aipt_platform_profile_get(struct
>>>>>>>> asus_wmi *asus,
>>>>>>>> +                          enum platform_profile_option
>>>>>>>> *profile)
>>>>>>>> +{
>>>>>>>> +    switch (asus->asus_aipt_mode) {
>>>>>>>> +    case AIPT_STANDARD:
>>>>>>>> +        *profile = PLATFORM_PROFILE_BALANCED;
>>>>>>>> +        break;
>>>>>>>> +    case AIPT_PERFORMANCE:
>>>>>>>> +        *profile = PLATFORM_PROFILE_PERFORMANCE;
>>>>>>>> +        break;
>>>>>>>> +    case AIPT_WHISPER:
>>>>>>>> +        *profile = PLATFORM_PROFILE_QUIET;
>>>>>>>> +        break;
>>>>>>>> +    default:
>>>>>>>> +        return -EINVAL;
>>>>>>>> +    }
>>>>>>>> +
>>>>>>>> +    return 0;
>>>>>>>> +}
>>>>>>>> +
>>>>>>>>      static int asus_wmi_platform_profile_get(struct
>>>>>>>> platform_profile_handler *pprof,
>>>>>>>>                          enum platform_profile_option
>>>>>>>> *profile)
>>>>>>>>      {
>>>>>>>> @@ -3851,6 +3892,10 @@ static int
>>>>>>>> asus_wmi_platform_profile_get(struct
>>>>>>>> platform_profile_handler *pprof,
>>>>>>>>          int tp;
>>>>>>>>
>>>>>>>>          asus = container_of(pprof, struct asus_wmi,
>>>>>>>> platform_profile_handler);
>>>>>>>> +
>>>>>>>> +    if (asus->asus_aipt_present)
>>>>>>>> +        return asus_wmi_aipt_platform_profile_get(asus,
>>>>>>>> profile);
>>>>>>>> +
>>>>>>>>          tp = asus->throttle_thermal_policy_mode;
>>>>>>>>
>>>>>>>>          switch
>>>>>>>> (asus_wmi_platform_profile_mode_from_vivo(asus, tp)) {
>>>>>>>> @@ -3874,26 +3919,42 @@ static int
>>>>>>>> asus_wmi_platform_profile_set(struct
>>>>>>>> platform_profile_handler *pprof,
>>>>>>>>                          enum platform_profile_option
>>>>>>>> profile)
>>>>>>>>      {
>>>>>>>>          struct asus_wmi *asus;
>>>>>>>> -    int tp;
>>>>>>>> +    int ret = 0, tp, aipt_mode;
>>>>>>>>
>>>>>>>>          asus = container_of(pprof, struct asus_wmi,
>>>>>>>> platform_profile_handler);
>>>>>>>>
>>>>>>>>          switch (profile) {
>>>>>>>>          case PLATFORM_PROFILE_PERFORMANCE:
>>>>>>>>              tp = ASUS_THROTTLE_THERMAL_POLICY_OVERBOOST;
>>>>>>>> +        aipt_mode = AIPT_PERFORMANCE;
>>>>>>>>              break;
>>>>>>>>          case PLATFORM_PROFILE_BALANCED:
>>>>>>>>              tp = ASUS_THROTTLE_THERMAL_POLICY_DEFAULT;
>>>>>>>> +        aipt_mode = AIPT_STANDARD;
>>>>>>>>              break;
>>>>>>>>          case PLATFORM_PROFILE_QUIET:
>>>>>>>>              tp = ASUS_THROTTLE_THERMAL_POLICY_SILENT;
>>>>>>>> +        aipt_mode = AIPT_WHISPER;
>>>>>>>>              break;
>>>>>>>>          default:
>>>>>>>>              return -EOPNOTSUPP;
>>>>>>>>          }
>>>>>>>>
>>>>>>>> -    asus->throttle_thermal_policy_mode =
>>>>>>>> asus_wmi_platform_profile_to_vivo(asus, tp);
>>>>>>>> -    return throttle_thermal_policy_write(asus);
>>>>>>>> +    if (asus->asus_aipt_present) {
>>>>>>>> +        ret = asus_wmi_write_aipt_mode(asus, aipt_mode);
>>>>>>>> +        if (!ret) {
>>>>>>>> +            asus->asus_aipt_mode = aipt_mode;
>>>>>>>> +            goto skip_vivo;
>>>>>>>> +        }
>>>>>>>> +    }
>>>>>>>> +
>>>>>>>> +    if (asus->throttle_thermal_policy_dev) {
>>>>>>>> +        asus->throttle_thermal_policy_mode =
>>>>>>>> asus_wmi_platform_profile_to_vivo(asus, tp);
>>>>>>>> +        ret = throttle_thermal_policy_write(asus);
>>>>>>>> +    }
>>>>>>>> +
>>>>>>>> +skip_vivo:
>>>>>>>> +    return ret;
>>>>>>>>      }
>>>>>>>>
>>>>>>>>      static int platform_profile_setup(struct asus_wmi
>>>>>>>> *asus)
>>>>>>>> @@ -3905,7 +3966,7 @@ static int
>>>>>>>> platform_profile_setup(struct
>>>>>>>> asus_wmi *asus)
>>>>>>>>           * Not an error if a component platform_profile
>>>>>>>> relies on is
>>>>>>>> unavailable
>>>>>>>>           * so early return, skipping the setup of
>>>>>>>> platform_profile.
>>>>>>>>           */
>>>>>>>> -    if (!asus->throttle_thermal_policy_dev)
>>>>>>>> +    if (!asus->throttle_thermal_policy_dev && !asus-
>>>>>>>>> asus_aipt_present)
>>>>>>>>              return 0;
>>>>>>>>
>>>>>>>>          dev_info(dev, "Using throttle_thermal_policy for
>>>>>>>> platform_profile support\n");
>>>>>>>> @@ -4538,6 +4599,7 @@ static int
>>>>>>>> asus_wmi_sysfs_init(struct
>>>>>>>> platform_device *device)
>>>>>>>>      static int asus_wmi_platform_init(struct asus_wmi
>>>>>>>> *asus)
>>>>>>>>      {
>>>>>>>>          struct device *dev = &asus->platform_device->dev;
>>>>>>>> +    struct acpi_device *adev;
>>>>>>>>          char *wmi_uid;
>>>>>>>>          int rv;
>>>>>>>>
>>>>>>>> @@ -4593,6 +4655,29 @@ static int
>>>>>>>> asus_wmi_platform_init(struct
>>>>>>>> asus_wmi *asus)
>>>>>>>>              asus_wmi_set_devstate(ASUS_WMI_DEVID_CWAP,
>>>>>>>>                            asus->driver->quirks->wapf,
>>>>>>>> NULL);
>>>>>>>>
>>>>>>>> +    /*
>>>>>>>> +     * Check presence of Intelligent Performance
>>>>>>>> Technology (AIPT).
>>>>>>>> +     * If present store acpi handle and set
>>>>>>>> asus_aipt_present to true.
>>>>>>>> +     */
>>>>>>>> +    adev = acpi_dev_get_first_match_dev("PNP0C14",
>>>>>>>> "ATK", -1);
>>>>>>> Is there really no way of changing the AIPT mode through
>>>>>>> the WMI
>>>>>>> interface?
>>>>>>> I would prefer using the WMI interface if available, since
>>>>>>> the
>>>>>>> firmware might
>>>>>>> assume that FANL is only called through the WMI interface.
>>>>>>>
>>>>>>> Do you have a acpidump from a affected device?
>>>>>>>
>>>>>>> Thanks,
>>>>>>> Armin Wolf
>>>>>>>
>>>>>> I found a acpidump from a ASUS device with a matching FANL
>>>>>> method. It seems that this method
>>>>>> can indeed be called using the WMI interface using the DEVS()
>>>>>> WMI method:
>>>>>>
>>>>>> [WmiMethodId(1398162756), Implemented] void DEVS([in] uint32
>>>>>> Device_ID, [in] uint32 Control_status, [out] uint32 result);
>>>>>>
>>>>>> If Device_ID is 0x00110019, then Control_status is passed to
>>>>>> the FANL ACPI method.
>>>>>>
>>>>>> It also seems that support for AIPT can be queried using the
>>>>>> DSTS() WMI method:
>>>>>>
>>>>>> [WmiMethodId(1398035268), Implemented] void DSTS([in] uint32
>>>>>> Device_ID, [out] uint32 device_status);
>>>>>>
>>>>>> Using Device_ID 0x00110019, the returned device status seems
>>>>>> to contain the following information:
>>>>>>
>>>>>> - 16-bit current AIPT mode
>>>>>> - 4-bit unknown value (possible values 2, 3 and 7, maybe
>>>>>> number of supported modes or some kind of bitmap?)
>>>>>> - 1-bit with is set when (GGIV (0x0907000C) == One) is true
>>>>> I just saw this conversation and i think that the behaviour
>>>>> this
>>>>> patch will implement in the driver was already implemented in
>>>>> this patch
>>>>> that got added to kernel v6.12-rc3:
>>>>> https://lore.kernel.org/platform-driver-x86/20240609144849.2532-2-mohamed.ghanmi@supcom.tn/
>>>>>
>>>>> this patch introduced
>>>>> ASUS_WMI_DEVID_THROTTLE_THERMAL_POLICY_VIVO
>>>>> 0x00110019 which is the device_id that changes the fan
>>>>> profiles. the
>>>>> naming is not clear because it was initially intended to add
>>>>> support for
>>>>> fan profiles for vivobook laptops but it ended up adding
>>>>> support
>>>>> for a lot of modern laptops.
>>>> Nice, you are absolutely right.
>>>>
>>>> So this patch series is effectively already upstream, very good.
>>>> I did some research and found out
>>>> that the status of this device id contains the following data:
>>>>
>>>> Status          Supported Modes
>>>> -------------------------------
>>>> 0x00[1]300[xx]  0 1 2
>>>> 0x000700[xx]    0 1 2
>>>> 0x000200[xx]    ??? (ODV0)
>>>> 0x000700[xx]    0 1 2
>>>> 0x0a0700[xx]    ??? (ODV0)
>>>>
>>>> While i have no clue about the meaning of the remaining bits, i
>>>> can report that the first 8 Bits
>>>> contain the current thermal mode. Maybe adding support for this
>>>> would be nice, so the current
>>>> thermal mode can be read directly from the hardware.
>>>>
>>>> I also found out that on some models the thermal mode actually
>>>> modifies the ODV0 variable which
>>>> is consumed by int3400_thermal and exposed to the Intel Thermal
>>>> Daemon. So maybe the lackluster
>>>> performance also has something to do with it.
>>>>
>>>>> a point that Srinivas Pandruvada mentioned about RAPL (Running
>>>>> Average Power Limit)
>>>>> is valid for a lot of modern vivobook and zenbook laptops but i
>>>>> think
>>>>> it's unrelated to fan profiles.
>>>>>
>>>>> a lot of asus laptops that have intel cpus suffer from power
>>>>> throttling.
>>>>> for exemple in my case using windows, changing fan profiles
>>>>> will lead to max power
>>>>> changing to the values indicated in the table below (asus
>>>>> vivobook 16x
>>>>> pro k6604) which leads to higher performance than linux
>>>>>
>>>>> fan Profile             power limit
>>>>> -----------------------------------
>>>>> Whisper                 50watts
>>>>> Standard                120watts
>>>>> Performance             149watts
>>>>> ------------------------------------
>>>>>
>>>>> However in linux, even after changing to the appropriate fan
>>>>> profile,
>>>>> the power is still capped at 50watts and i found the reason why
>>>>>
>>>>> here is the results of using the powercap-info command:
>>>>>
>>>>> intel-rapl-mmio
>>>>>      enabled: 1
>>>>>      Zone 0
>>>>>        name: package-0
>>>>>        enabled: 1
>>>>>        max_energy_range_uj: 262143328850
>>>>>        Constraint 0
>>>>>          name: long_term
>>>>>          power_limit_uw: 30000000
>>>>>          time_window_us: 55967744
>>>>>          max_power_uw: 55000000
>>>>>        Constraint 1
>>>>>          name: short_term
>>>>>          power_limit_uw: 55000000
>>>>>          time_window_us: 2440
>>>>>          max_power_uw: 0
>>>>> intel-rapl
>>>>>      enabled: 1
>>>>>      Zone 0
>>>>>        name: package-0
>>>>>        enabled: 1
>>>>>        max_energy_range_uj: 262143328850
>>>>>        Constraint 0
>>>>>          name: long_term
>>>>>          power_limit_uw: 157000000
>>>>>          time_window_us: 55967744
>>>>>          max_power_uw: 55000000
>>>>>        Constraint 1
>>>>>          name: short_term
>>>>>          power_limit_uw: 157000000
>>>>>          time_window_us: 2440
>>>>>          max_power_uw: 0
>>>>>        Constraint 2
>>>>>          name: peak_power
>>>>>          power_limit_uw: 200000000
>>>>>          max_power_uw: 0
>>>>>        Zone 0:0
>>>>>          name: core
>>>>>          enabled: 0
>>>>>          max_energy_range_uj: 262143328850
>>>>>          Constraint 0
>>>>>            name: long_term
>>>>>            power_limit_uw: 0
>>>>>            time_window_us: 976
>>>>>        Zone 0:1
>>>>>          name: uncore
>>>>>          enabled: 0
>>>>>          max_energy_range_uj: 262143328850
>>>>>          Constraint 0
>>>>>            name: long_term
>>>>>            power_limit_uw: 0
>>>>>            time_window_us: 976
>>>>>      Zone 1
>>>>>        name: psys
>>>>>        enabled: 0
>>>>>        max_energy_range_uj: 262143328850
>>>>>        Constraint 0
>>>>>          name: long_term
>>>>>          power_limit_uw: 0
>>>>>          time_window_us: 27983872
>>>>>        Constraint 1
>>>>>          name: short_term
>>>>>          power_limit_uw: 0
>>>>>          time_window_us: 976
>>>>>
>>>>>
>>>>> as seen by the output of the command, the intel-rapl-mmio is
>>>>> causing the
>>>>> throttling as it sets power_limit_uw to 30 watts (readonly). so
>>>>> the current fix
>>>>> that i'm currently using is disabling the intel-rapl-mmio
>>>>> leaving only
>>>>> the intel-rapl which sets power_limit_uw to 157watts using this
>>>>> command: powercap-set -p intel-rapl-mmio -z 0 -e 0
>>>>>
>>>>> this will lead to the laptop being able to reach it's maximum
>>>>> power
>>>>> limit.
>>>>>
>>>>> after doing this, when i change the platform profile through
>>>>> sysfs the
>>>>> laptop will start behaving as described in the table above
>>>>> exactly like
>>>>> windows.
>>>>>
>>>>> in conclusion, the asus-wmi driver already has the platform
>>>>> profiles
>>>>> (a.k.a fan profiles)
>>>>> implemented and I think that the power throttling is caused by
>>>>> either
>>>>> intel Power Capping Framework or asus bios.
>>>> Or the Intel Thermal Daemon somehow does not properly support
>>>> intel-rapl-mmio
>>>> or is not installed.
>>> This was exactly it. the Intel Thermal Daemon wasn't installed. now
>>> everything is working as expected!
>>>
>>> Best regards,
>>> Mohamed G.
>> Interesting.
>>
>> Srinivas, can you verify that the Intel Thermal Daemon is installed
>> on the affected
>> Asus machines?
>>
>> I begin to wonder why this thermal daemon is a userspace component,
>> stuff like thermal
>> management should use the thermal subsystem inside the kernel.
> Thanks for detailed analysis here.
>
> Here the problem is not thermal daemon or INT340x (I am author of
> both).
>
> The ODVP variable is input into thermal tables. These thermal tables
> are defined by Asus via DTT tables. This results in matching certain
> max and min power limits and also various temperature limits.
>
> By default the laptop in question will boot with max limit of 17W,
> which is limit for whisper mode match based on ODVP variables. There is
> a SEN1 limit of 50C, once the limit reaches to 50C, you need to
> throttle upto 12W as per thermal table.
>
> If you stop thermald, yes, you will stay in 17W, so you will not see
> throttle but your SEN1 (seems skin limit) limit will be violated.
> Also if you remove the rapl_mmio driver, that will also work as no
> means to set power limits.
>
> Windows will do exactly same. Meeting thermal limit is a requirement.
>
> But on Windows this ODVP variable will be set to 0 to match standard
> mode. This will result in matching rules which will set the max power
> to 22W and min to 17W also increase thermal limit to 55C. So
> essentially lost 5W of performance.
>
> Here WMI method as you correctly found out matching VIVO thermal
> policy. But it will not set ODVP variable unless you call a WMI method
> to set the mode via DEVS() on the same device ID. So although platform
> power policy will say "balanced" it is actually "Whisper" for thermal
> policy. On Windows when system boots the Asus service will set to
> standard and will set the ODVP variable to 0 and will match the correct
> table.
>
> After Luke's help, I can do a work around from user space to change the
> power policy to any other policy than balanced and then again set to
> balance. This will result in setting the policy to standard via DEVS()
> and also set the correct ODVP variable.
>
> This driver on unload change the vivo thermal policy to default. But
> doesn't change that to default on load time to match the default
> platform power policy. So rmmod and modprobe of driver should also fix.
>
> Thanks,
> Srinivas
>
Good point, so basically throttle_thermal_policy_set_default() need to be called during
initialization of the thermal profile. Maybe you can send another patch which implements this?

Thanks,
Armin Wolf

>> Thanks,
>> Armin Wolf
>>
>
srinivas pandruvada Oct. 24, 2024, 6:15 p.m. UTC | #14
On Wed, 2024-10-23 at 22:32 +0200, Armin Wolf wrote:
> Am 23.10.24 um 22:15 schrieb srinivas pandruvada:
> 
> > On Wed, 2024-10-23 at 20:57 +0200, Armin Wolf wrote:
> > > Am 23.10.24 um 19:59 schrieb Mohamed Ghanmi:
> > > 
> > > > On Wed, Oct 23, 2024 at 06:31:17PM +0200, Armin Wolf wrote:
> > > > > Am 23.10.24 um 16:44 schrieb Mohamed Ghanmi:
> > > > > 
> > > > > > Hello !
> > > > > > On Sun, Oct 20, 2024 at 09:42:45PM +0200, Armin Wolf wrote:
> > > > > > > Am 20.10.24 um 21:05 schrieb Armin Wolf:
> > > > > > > 
> > > > > > > > Am 20.10.24 um 08:50 schrieb Srinivas Pandruvada:
> > > > > > > > 
> > > > > > > > > Some recent Asus laptops are supporting ASUS
> > > > > > > > > Intelligent
> > > > > > > > > Performance
> > > > > > > > > Technology (AIPT). This solution allows users to have
> > > > > > > > > maximized CPU
> > > > > > > > > performance in models with a chassis providing more
> > > > > > > > > thermal head room.
> > > > > > > > > Refer to [1].
> > > > > > > > > 
> > > > > > > > > There are major performance issues when Linux is
> > > > > > > > > installed on these
> > > > > > > > > laptops compared to Windows install. One such report
> > > > > > > > > is
> > > > > > > > > published for
> > > > > > > > > Graphics benchmarks on Asus ASUS Zenbook S 14 with
> > > > > > > > > Lunar
> > > > > > > > > Lake
> > > > > > > > > processors [2].
> > > > > > > > > 
> > > > > > > > > By default, these laptops are booting in "Whisper
> > > > > > > > > Mode"
> > > > > > > > > till OS power
> > > > > > > > > management or tools change this to other AIPT mode.
> > > > > > > > > This
> > > > > > > > > "Whisper" mode
> > > > > > > > > calls to set lower maximum and minimum RAPL (Running
> > > > > > > > > Average Power
> > > > > > > > > Limit)
> > > > > > > > > via thermal tables. On Linux this leads to lower
> > > > > > > > > performance even when
> > > > > > > > > platform power profile is "balanced". This "Whisper"
> > > > > > > > > mode
> > > > > > > > > should
> > > > > > > > > correspond to "quiet" mode.
> > > > > > > > > 
> > > > > > > > > So, when AIPT is present change the default mode to
> > > > > > > > > "Standard" during
> > > > > > > > > boot. Map the three platform power profile modes as
> > > > > > > > > follows:
> > > > > > > > > 
> > > > > > > > > Power Profile Mode      AIPT mode
> > > > > > > > > -----------------------------------
> > > > > > > > > quiet            Whisper
> > > > > > > > > balanced        Standard
> > > > > > > > > performance        Performance
> > > > > > > > > ------------------------------------
> > > > > > > > > 
> > > > > > > > > Here AIPT mode can be detected by checking presese of
> > > > > > > > > "FANL" method
> > > > > > > > > under
> > > > > > > > > PNP HID "PNP0C14" and UID "ATK". If AIPT mode is
> > > > > > > > > present,
> > > > > > > > > this takes
> > > > > > > > > precedence over the existing VIVO thermal policy.
> > > > > > > > > These
> > > > > > > > > modes are set
> > > > > > > > > using "FANL" method.
> > > > > > > > > 
> > > > > > > > > Although this “FANL” method is not used in the Asus
> > > > > > > > > WMI
> > > > > > > > > driver, users
> > > > > > > > > have used this method from user space [3] to set AIPT
> > > > > > > > > modes. Used this
> > > > > > > > > as a reference.
> > > > > > > > > 
> > > > > > > > > Link:
> > > > > > > > > https://www.asus.com/content/laptop-asus-intelligent-performance-technology-aipt/
> > > > > > > > > # [1]
> > > > > > > > > Reported-by: Michael Larabel <Michael@phoronix.com>
> > > > > > > > > Closes:
> > > > > > > > > https://www.phoronix.com/review/lunar-lake-xe2/5 #
> > > > > > > > > [2]
> > > > > > > > > Link:
> > > > > > > > > https://github.com/dominiksalvet/asus-fan-control/issues/151
> > > > > > > > >   # [3]
> > > > > > > > > Tested-by: Casey Bowman <casey.g.bowman@intel.com>
> > > > > > > > > Signed-off-by: Srinivas Pandruvada
> > > > > > > > > <srinivas.pandruvada@linux.intel.com>
> > > > > > > > > ---
> > > > > > > > >      drivers/platform/x86/asus-wmi.c | 93
> > > > > > > > > +++++++++++++++++++++++++++++++--
> > > > > > > > >      1 file changed, 89 insertions(+), 4 deletions(-)
> > > > > > > > > 
> > > > > > > > > diff --git a/drivers/platform/x86/asus-wmi.c
> > > > > > > > > b/drivers/platform/x86/asus-wmi.c
> > > > > > > > > index 7a48220b4f5a..06689d0f98c7 100644
> > > > > > > > > --- a/drivers/platform/x86/asus-wmi.c
> > > > > > > > > +++ b/drivers/platform/x86/asus-wmi.c
> > > > > > > > > @@ -100,6 +100,11 @@ module_param(fnlock_default,
> > > > > > > > > bool,
> > > > > > > > > 0444);
> > > > > > > > >      #define
> > > > > > > > > ASUS_THROTTLE_THERMAL_POLICY_SILENT_VIVO    1
> > > > > > > > >      #define
> > > > > > > > > ASUS_THROTTLE_THERMAL_POLICY_OVERBOOST_VIVO    2
> > > > > > > > > 
> > > > > > > > > +#define AIPT_STANDARD                0
> > > > > > > > > +#define AIPT_WHISPER                1
> > > > > > > > > +#define AIPT_PERFORMANCE            2
> > > > > > > > > +#define AIPT_FULL_SPEED                3
> > > > > > > > > +
> > > > > > > > >      #define PLATFORM_PROFILE_MAX 2
> > > > > > > > > 
> > > > > > > > >      #define USB_INTEL_XUSB2PR        0xD0
> > > > > > > > > @@ -333,6 +338,9 @@ struct asus_wmi {
> > > > > > > > >          struct asus_wmi_debug debug;
> > > > > > > > > 
> > > > > > > > >          struct asus_wmi_driver *driver;
> > > > > > > > > +    acpi_handle acpi_mgmt_handle;
> > > > > > > > > +    int asus_aipt_mode;
> > > > > > > > > +    bool asus_aipt_present;
> > > > > > > > >      };
> > > > > > > > > 
> > > > > > > > >      /* WMI
> > > > > > > > > *****************************************************
> > > > > > > > > ****
> > > > > > > > > ***************/
> > > > > > > > > @@ -3804,6 +3812,19 @@ static ssize_t
> > > > > > > > > throttle_thermal_policy_store(struct device *dev,
> > > > > > > > >      static DEVICE_ATTR_RW(throttle_thermal_policy);
> > > > > > > > > 
> > > > > > > > >      /* Platform profile
> > > > > > > > > *****************************************************
> > > > > > > > > ****
> > > > > > > > > **/
> > > > > > > > > +static int asus_wmi_write_aipt_mode(struct asus_wmi
> > > > > > > > > *asus, int
> > > > > > > > > aipt_mode)
> > > > > > > > > +{
> > > > > > > > > +    int status;
> > > > > > > > > +
> > > > > > > > > +    status = acpi_execute_simple_method(asus-
> > > > > > > > > > acpi_mgmt_handle,
> > > > > > > > > "FANL", aipt_mode);
> > > > > > > > > +    if (ACPI_FAILURE(status)) {
> > > > > > > > > +        acpi_handle_info(asus->acpi_mgmt_handle,
> > > > > > > > > "FANL
> > > > > > > > > execute
> > > > > > > > > failed\n");
> > > > > > > > > +        return -EIO;
> > > > > > > > > +    }
> > > > > > > > > +
> > > > > > > > > +    return 0;
> > > > > > > > > +}
> > > > > > > > > +
> > > > > > > > >      static int
> > > > > > > > > asus_wmi_platform_profile_to_vivo(struct
> > > > > > > > > asus_wmi *asus,
> > > > > > > > > int mode)
> > > > > > > > >      {
> > > > > > > > >          bool vivo;
> > > > > > > > > @@ -3844,6 +3865,26 @@ static int
> > > > > > > > > asus_wmi_platform_profile_mode_from_vivo(struct
> > > > > > > > > asus_wmi
> > > > > > > > > *asus, int m
> > > > > > > > >          return mode;
> > > > > > > > >      }
> > > > > > > > > 
> > > > > > > > > +static int asus_wmi_aipt_platform_profile_get(struct
> > > > > > > > > asus_wmi *asus,
> > > > > > > > > +                          enum
> > > > > > > > > platform_profile_option
> > > > > > > > > *profile)
> > > > > > > > > +{
> > > > > > > > > +    switch (asus->asus_aipt_mode) {
> > > > > > > > > +    case AIPT_STANDARD:
> > > > > > > > > +        *profile = PLATFORM_PROFILE_BALANCED;
> > > > > > > > > +        break;
> > > > > > > > > +    case AIPT_PERFORMANCE:
> > > > > > > > > +        *profile = PLATFORM_PROFILE_PERFORMANCE;
> > > > > > > > > +        break;
> > > > > > > > > +    case AIPT_WHISPER:
> > > > > > > > > +        *profile = PLATFORM_PROFILE_QUIET;
> > > > > > > > > +        break;
> > > > > > > > > +    default:
> > > > > > > > > +        return -EINVAL;
> > > > > > > > > +    }
> > > > > > > > > +
> > > > > > > > > +    return 0;
> > > > > > > > > +}
> > > > > > > > > +
> > > > > > > > >      static int asus_wmi_platform_profile_get(struct
> > > > > > > > > platform_profile_handler *pprof,
> > > > > > > > >                          enum platform_profile_option
> > > > > > > > > *profile)
> > > > > > > > >      {
> > > > > > > > > @@ -3851,6 +3892,10 @@ static int
> > > > > > > > > asus_wmi_platform_profile_get(struct
> > > > > > > > > platform_profile_handler *pprof,
> > > > > > > > >          int tp;
> > > > > > > > > 
> > > > > > > > >          asus = container_of(pprof, struct asus_wmi,
> > > > > > > > > platform_profile_handler);
> > > > > > > > > +
> > > > > > > > > +    if (asus->asus_aipt_present)
> > > > > > > > > +        return
> > > > > > > > > asus_wmi_aipt_platform_profile_get(asus,
> > > > > > > > > profile);
> > > > > > > > > +
> > > > > > > > >          tp = asus->throttle_thermal_policy_mode;
> > > > > > > > > 
> > > > > > > > >          switch
> > > > > > > > > (asus_wmi_platform_profile_mode_from_vivo(asus, tp))
> > > > > > > > > {
> > > > > > > > > @@ -3874,26 +3919,42 @@ static int
> > > > > > > > > asus_wmi_platform_profile_set(struct
> > > > > > > > > platform_profile_handler *pprof,
> > > > > > > > >                          enum platform_profile_option
> > > > > > > > > profile)
> > > > > > > > >      {
> > > > > > > > >          struct asus_wmi *asus;
> > > > > > > > > -    int tp;
> > > > > > > > > +    int ret = 0, tp, aipt_mode;
> > > > > > > > > 
> > > > > > > > >          asus = container_of(pprof, struct asus_wmi,
> > > > > > > > > platform_profile_handler);
> > > > > > > > > 
> > > > > > > > >          switch (profile) {
> > > > > > > > >          case PLATFORM_PROFILE_PERFORMANCE:
> > > > > > > > >              tp =
> > > > > > > > > ASUS_THROTTLE_THERMAL_POLICY_OVERBOOST;
> > > > > > > > > +        aipt_mode = AIPT_PERFORMANCE;
> > > > > > > > >              break;
> > > > > > > > >          case PLATFORM_PROFILE_BALANCED:
> > > > > > > > >              tp =
> > > > > > > > > ASUS_THROTTLE_THERMAL_POLICY_DEFAULT;
> > > > > > > > > +        aipt_mode = AIPT_STANDARD;
> > > > > > > > >              break;
> > > > > > > > >          case PLATFORM_PROFILE_QUIET:
> > > > > > > > >              tp =
> > > > > > > > > ASUS_THROTTLE_THERMAL_POLICY_SILENT;
> > > > > > > > > +        aipt_mode = AIPT_WHISPER;
> > > > > > > > >              break;
> > > > > > > > >          default:
> > > > > > > > >              return -EOPNOTSUPP;
> > > > > > > > >          }
> > > > > > > > > 
> > > > > > > > > -    asus->throttle_thermal_policy_mode =
> > > > > > > > > asus_wmi_platform_profile_to_vivo(asus, tp);
> > > > > > > > > -    return throttle_thermal_policy_write(asus);
> > > > > > > > > +    if (asus->asus_aipt_present) {
> > > > > > > > > +        ret = asus_wmi_write_aipt_mode(asus,
> > > > > > > > > aipt_mode);
> > > > > > > > > +        if (!ret) {
> > > > > > > > > +            asus->asus_aipt_mode = aipt_mode;
> > > > > > > > > +            goto skip_vivo;
> > > > > > > > > +        }
> > > > > > > > > +    }
> > > > > > > > > +
> > > > > > > > > +    if (asus->throttle_thermal_policy_dev) {
> > > > > > > > > +        asus->throttle_thermal_policy_mode =
> > > > > > > > > asus_wmi_platform_profile_to_vivo(asus, tp);
> > > > > > > > > +        ret = throttle_thermal_policy_write(asus);
> > > > > > > > > +    }
> > > > > > > > > +
> > > > > > > > > +skip_vivo:
> > > > > > > > > +    return ret;
> > > > > > > > >      }
> > > > > > > > > 
> > > > > > > > >      static int platform_profile_setup(struct
> > > > > > > > > asus_wmi
> > > > > > > > > *asus)
> > > > > > > > > @@ -3905,7 +3966,7 @@ static int
> > > > > > > > > platform_profile_setup(struct
> > > > > > > > > asus_wmi *asus)
> > > > > > > > >           * Not an error if a component
> > > > > > > > > platform_profile
> > > > > > > > > relies on is
> > > > > > > > > unavailable
> > > > > > > > >           * so early return, skipping the setup of
> > > > > > > > > platform_profile.
> > > > > > > > >           */
> > > > > > > > > -    if (!asus->throttle_thermal_policy_dev)
> > > > > > > > > +    if (!asus->throttle_thermal_policy_dev && !asus-
> > > > > > > > > > asus_aipt_present)
> > > > > > > > >              return 0;
> > > > > > > > > 
> > > > > > > > >          dev_info(dev, "Using throttle_thermal_policy
> > > > > > > > > for
> > > > > > > > > platform_profile support\n");
> > > > > > > > > @@ -4538,6 +4599,7 @@ static int
> > > > > > > > > asus_wmi_sysfs_init(struct
> > > > > > > > > platform_device *device)
> > > > > > > > >      static int asus_wmi_platform_init(struct
> > > > > > > > > asus_wmi
> > > > > > > > > *asus)
> > > > > > > > >      {
> > > > > > > > >          struct device *dev = &asus->platform_device-
> > > > > > > > > >dev;
> > > > > > > > > +    struct acpi_device *adev;
> > > > > > > > >          char *wmi_uid;
> > > > > > > > >          int rv;
> > > > > > > > > 
> > > > > > > > > @@ -4593,6 +4655,29 @@ static int
> > > > > > > > > asus_wmi_platform_init(struct
> > > > > > > > > asus_wmi *asus)
> > > > > > > > >             
> > > > > > > > > asus_wmi_set_devstate(ASUS_WMI_DEVID_CWAP,
> > > > > > > > >                            asus->driver->quirks-
> > > > > > > > > >wapf,
> > > > > > > > > NULL);
> > > > > > > > > 
> > > > > > > > > +    /*
> > > > > > > > > +     * Check presence of Intelligent Performance
> > > > > > > > > Technology (AIPT).
> > > > > > > > > +     * If present store acpi handle and set
> > > > > > > > > asus_aipt_present to true.
> > > > > > > > > +     */
> > > > > > > > > +    adev = acpi_dev_get_first_match_dev("PNP0C14",
> > > > > > > > > "ATK", -1);
> > > > > > > > Is there really no way of changing the AIPT mode
> > > > > > > > through
> > > > > > > > the WMI
> > > > > > > > interface?
> > > > > > > > I would prefer using the WMI interface if available,
> > > > > > > > since
> > > > > > > > the
> > > > > > > > firmware might
> > > > > > > > assume that FANL is only called through the WMI
> > > > > > > > interface.
> > > > > > > > 
> > > > > > > > Do you have a acpidump from a affected device?
> > > > > > > > 
> > > > > > > > Thanks,
> > > > > > > > Armin Wolf
> > > > > > > > 
> > > > > > > I found a acpidump from a ASUS device with a matching
> > > > > > > FANL
> > > > > > > method. It seems that this method
> > > > > > > can indeed be called using the WMI interface using the
> > > > > > > DEVS()
> > > > > > > WMI method:
> > > > > > > 
> > > > > > > [WmiMethodId(1398162756), Implemented] void DEVS([in]
> > > > > > > uint32
> > > > > > > Device_ID, [in] uint32 Control_status, [out] uint32
> > > > > > > result);
> > > > > > > 
> > > > > > > If Device_ID is 0x00110019, then Control_status is passed
> > > > > > > to
> > > > > > > the FANL ACPI method.
> > > > > > > 
> > > > > > > It also seems that support for AIPT can be queried using
> > > > > > > the
> > > > > > > DSTS() WMI method:
> > > > > > > 
> > > > > > > [WmiMethodId(1398035268), Implemented] void DSTS([in]
> > > > > > > uint32
> > > > > > > Device_ID, [out] uint32 device_status);
> > > > > > > 
> > > > > > > Using Device_ID 0x00110019, the returned device status
> > > > > > > seems
> > > > > > > to contain the following information:
> > > > > > > 
> > > > > > > - 16-bit current AIPT mode
> > > > > > > - 4-bit unknown value (possible values 2, 3 and 7, maybe
> > > > > > > number of supported modes or some kind of bitmap?)
> > > > > > > - 1-bit with is set when (GGIV (0x0907000C) == One) is
> > > > > > > true
> > > > > > I just saw this conversation and i think that the behaviour
> > > > > > this
> > > > > > patch will implement in the driver was already implemented
> > > > > > in
> > > > > > this patch
> > > > > > that got added to kernel v6.12-rc3:
> > > > > > https://lore.kernel.org/platform-driver-x86/20240609144849.2532-2-mohamed.ghanmi@supcom.tn/
> > > > > > 
> > > > > > this patch introduced
> > > > > > ASUS_WMI_DEVID_THROTTLE_THERMAL_POLICY_VIVO
> > > > > > 0x00110019 which is the device_id that changes the fan
> > > > > > profiles. the
> > > > > > naming is not clear because it was initially intended to
> > > > > > add
> > > > > > support for
> > > > > > fan profiles for vivobook laptops but it ended up adding
> > > > > > support
> > > > > > for a lot of modern laptops.
> > > > > Nice, you are absolutely right.
> > > > > 
> > > > > So this patch series is effectively already upstream, very
> > > > > good.
> > > > > I did some research and found out
> > > > > that the status of this device id contains the following
> > > > > data:
> > > > > 
> > > > > Status          Supported Modes
> > > > > -------------------------------
> > > > > 0x00[1]300[xx]  0 1 2
> > > > > 0x000700[xx]    0 1 2
> > > > > 0x000200[xx]    ??? (ODV0)
> > > > > 0x000700[xx]    0 1 2
> > > > > 0x0a0700[xx]    ??? (ODV0)
> > > > > 
> > > > > While i have no clue about the meaning of the remaining bits,
> > > > > i
> > > > > can report that the first 8 Bits
> > > > > contain the current thermal mode. Maybe adding support for
> > > > > this
> > > > > would be nice, so the current
> > > > > thermal mode can be read directly from the hardware.
> > > > > 
> > > > > I also found out that on some models the thermal mode
> > > > > actually
> > > > > modifies the ODV0 variable which
> > > > > is consumed by int3400_thermal and exposed to the Intel
> > > > > Thermal
> > > > > Daemon. So maybe the lackluster
> > > > > performance also has something to do with it.
> > > > > 
> > > > > > a point that Srinivas Pandruvada mentioned about RAPL
> > > > > > (Running
> > > > > > Average Power Limit)
> > > > > > is valid for a lot of modern vivobook and zenbook laptops
> > > > > > but i
> > > > > > think
> > > > > > it's unrelated to fan profiles.
> > > > > > 
> > > > > > a lot of asus laptops that have intel cpus suffer from
> > > > > > power
> > > > > > throttling.
> > > > > > for exemple in my case using windows, changing fan profiles
> > > > > > will lead to max power
> > > > > > changing to the values indicated in the table below (asus
> > > > > > vivobook 16x
> > > > > > pro k6604) which leads to higher performance than linux
> > > > > > 
> > > > > > fan Profile             power limit
> > > > > > -----------------------------------
> > > > > > Whisper                 50watts
> > > > > > Standard                120watts
> > > > > > Performance             149watts
> > > > > > ------------------------------------
> > > > > > 
> > > > > > However in linux, even after changing to the appropriate
> > > > > > fan
> > > > > > profile,
> > > > > > the power is still capped at 50watts and i found the reason
> > > > > > why
> > > > > > 
> > > > > > here is the results of using the powercap-info command:
> > > > > > 
> > > > > > intel-rapl-mmio
> > > > > >      enabled: 1
> > > > > >      Zone 0
> > > > > >        name: package-0
> > > > > >        enabled: 1
> > > > > >        max_energy_range_uj: 262143328850
> > > > > >        Constraint 0
> > > > > >          name: long_term
> > > > > >          power_limit_uw: 30000000
> > > > > >          time_window_us: 55967744
> > > > > >          max_power_uw: 55000000
> > > > > >        Constraint 1
> > > > > >          name: short_term
> > > > > >          power_limit_uw: 55000000
> > > > > >          time_window_us: 2440
> > > > > >          max_power_uw: 0
> > > > > > intel-rapl
> > > > > >      enabled: 1
> > > > > >      Zone 0
> > > > > >        name: package-0
> > > > > >        enabled: 1
> > > > > >        max_energy_range_uj: 262143328850
> > > > > >        Constraint 0
> > > > > >          name: long_term
> > > > > >          power_limit_uw: 157000000
> > > > > >          time_window_us: 55967744
> > > > > >          max_power_uw: 55000000
> > > > > >        Constraint 1
> > > > > >          name: short_term
> > > > > >          power_limit_uw: 157000000
> > > > > >          time_window_us: 2440
> > > > > >          max_power_uw: 0
> > > > > >        Constraint 2
> > > > > >          name: peak_power
> > > > > >          power_limit_uw: 200000000
> > > > > >          max_power_uw: 0
> > > > > >        Zone 0:0
> > > > > >          name: core
> > > > > >          enabled: 0
> > > > > >          max_energy_range_uj: 262143328850
> > > > > >          Constraint 0
> > > > > >            name: long_term
> > > > > >            power_limit_uw: 0
> > > > > >            time_window_us: 976
> > > > > >        Zone 0:1
> > > > > >          name: uncore
> > > > > >          enabled: 0
> > > > > >          max_energy_range_uj: 262143328850
> > > > > >          Constraint 0
> > > > > >            name: long_term
> > > > > >            power_limit_uw: 0
> > > > > >            time_window_us: 976
> > > > > >      Zone 1
> > > > > >        name: psys
> > > > > >        enabled: 0
> > > > > >        max_energy_range_uj: 262143328850
> > > > > >        Constraint 0
> > > > > >          name: long_term
> > > > > >          power_limit_uw: 0
> > > > > >          time_window_us: 27983872
> > > > > >        Constraint 1
> > > > > >          name: short_term
> > > > > >          power_limit_uw: 0
> > > > > >          time_window_us: 976
> > > > > > 
> > > > > > 
> > > > > > as seen by the output of the command, the intel-rapl-mmio
> > > > > > is
> > > > > > causing the
> > > > > > throttling as it sets power_limit_uw to 30 watts
> > > > > > (readonly). so
> > > > > > the current fix
> > > > > > that i'm currently using is disabling the intel-rapl-mmio
> > > > > > leaving only
> > > > > > the intel-rapl which sets power_limit_uw to 157watts using
> > > > > > this
> > > > > > command: powercap-set -p intel-rapl-mmio -z 0 -e 0
> > > > > > 
> > > > > > this will lead to the laptop being able to reach it's
> > > > > > maximum
> > > > > > power
> > > > > > limit.
> > > > > > 
> > > > > > after doing this, when i change the platform profile
> > > > > > through
> > > > > > sysfs the
> > > > > > laptop will start behaving as described in the table above
> > > > > > exactly like
> > > > > > windows.
> > > > > > 
> > > > > > in conclusion, the asus-wmi driver already has the platform
> > > > > > profiles
> > > > > > (a.k.a fan profiles)
> > > > > > implemented and I think that the power throttling is caused
> > > > > > by
> > > > > > either
> > > > > > intel Power Capping Framework or asus bios.
> > > > > Or the Intel Thermal Daemon somehow does not properly support
> > > > > intel-rapl-mmio
> > > > > or is not installed.
> > > > This was exactly it. the Intel Thermal Daemon wasn't installed.
> > > > now
> > > > everything is working as expected!
> > > > 
> > > > Best regards,
> > > > Mohamed G.
> > > Interesting.
> > > 
> > > Srinivas, can you verify that the Intel Thermal Daemon is
> > > installed
> > > on the affected
> > > Asus machines?
> > > 
> > > I begin to wonder why this thermal daemon is a userspace
> > > component,
> > > stuff like thermal
> > > management should use the thermal subsystem inside the kernel.
> > Thanks for detailed analysis here.
> > 
> > Here the problem is not thermal daemon or INT340x (I am author of
> > both).
> > 
> > The ODVP variable is input into thermal tables. These thermal
> > tables
> > are defined by Asus via DTT tables. This results in matching
> > certain
> > max and min power limits and also various temperature limits.
> > 
> > By default the laptop in question will boot with max limit of 17W,
> > which is limit for whisper mode match based on ODVP variables.
> > There is
> > a SEN1 limit of 50C, once the limit reaches to 50C, you need to
> > throttle upto 12W as per thermal table.
> > 
> > If you stop thermald, yes, you will stay in 17W, so you will not
> > see
> > throttle but your SEN1 (seems skin limit) limit will be violated.
> > Also if you remove the rapl_mmio driver, that will also work as no
> > means to set power limits.
> > 
> > Windows will do exactly same. Meeting thermal limit is a
> > requirement.
> > 
> > But on Windows this ODVP variable will be set to 0 to match
> > standard
> > mode. This will result in matching rules which will set the max
> > power
> > to 22W and min to 17W also increase thermal limit to 55C. So
> > essentially lost 5W of performance.
> > 
> > Here WMI method as you correctly found out matching VIVO thermal
> > policy. But it will not set ODVP variable unless you call a WMI
> > method
> > to set the mode via DEVS() on the same device ID. So although
> > platform
> > power policy will say "balanced" it is actually "Whisper" for
> > thermal
> > policy. On Windows when system boots the Asus service will set to
> > standard and will set the ODVP variable to 0 and will match the
> > correct
> > table.
> > 
> > After Luke's help, I can do a work around from user space to change
> > the
> > power policy to any other policy than balanced and then again set
> > to
> > balance. This will result in setting the policy to standard via
> > DEVS()
> > and also set the correct ODVP variable.
> > 
> > This driver on unload change the vivo thermal policy to default.
> > But
> > doesn't change that to default on load time to match the default
> > platform power policy. So rmmod and modprobe of driver should also
> > fix.
> > 
> > Thanks,
> > Srinivas
> > 
> Good point, so basically throttle_thermal_policy_set_default() need
> to be called during
> initialization of the thermal profile. Maybe you can send another
> patch which implements this?

I have already tested this change. But this seems a regression, so want
to confirm first as it was intentional. The following commit removed
the call. If it was unintentional, Mohamed can try to submit a change.


commit bcbfcebda2cbc6a10a347d726e4a4f69e43a864e
Author: Mohamed Ghanmi <mohamed.ghanmi@supcom.tn>
Date:   Sun Jun 9 15:48:49 2024 +0100

Thanks,
Srinivas




> 
> Thanks,
> Armin Wolf
> 
> > > Thanks,
> > > Armin Wolf
> > > 
> >
Mohamed Ghanmi Oct. 25, 2024, 1:30 p.m. UTC | #15
On Thu, Oct 24, 2024 at 11:15:31AM -0700, srinivas pandruvada wrote:
> On Wed, 2024-10-23 at 22:32 +0200, Armin Wolf wrote:
> > Am 23.10.24 um 22:15 schrieb srinivas pandruvada:
> > 
> > > On Wed, 2024-10-23 at 20:57 +0200, Armin Wolf wrote:
> > > > Am 23.10.24 um 19:59 schrieb Mohamed Ghanmi:
> > > > 
> > > > > On Wed, Oct 23, 2024 at 06:31:17PM +0200, Armin Wolf wrote:
> > > > > > Am 23.10.24 um 16:44 schrieb Mohamed Ghanmi:
> > > > > > 
> > > > > > > Hello !
> > > > > > > On Sun, Oct 20, 2024 at 09:42:45PM +0200, Armin Wolf wrote:
> > > > > > > > Am 20.10.24 um 21:05 schrieb Armin Wolf:
> > > > > > > > 
> > > > > > > > > Am 20.10.24 um 08:50 schrieb Srinivas Pandruvada:
> > > > > > > > > 
> > > > > > > > > > Some recent Asus laptops are supporting ASUS
> > > > > > > > > > Intelligent
> > > > > > > > > > Performance
> > > > > > > > > > Technology (AIPT). This solution allows users to have
> > > > > > > > > > maximized CPU
> > > > > > > > > > performance in models with a chassis providing more
> > > > > > > > > > thermal head room.
> > > > > > > > > > Refer to [1].
> > > > > > > > > > 
> > > > > > > > > > There are major performance issues when Linux is
> > > > > > > > > > installed on these
> > > > > > > > > > laptops compared to Windows install. One such report
> > > > > > > > > > is
> > > > > > > > > > published for
> > > > > > > > > > Graphics benchmarks on Asus ASUS Zenbook S 14 with
> > > > > > > > > > Lunar
> > > > > > > > > > Lake
> > > > > > > > > > processors [2].
> > > > > > > > > > 
> > > > > > > > > > By default, these laptops are booting in "Whisper
> > > > > > > > > > Mode"
> > > > > > > > > > till OS power
> > > > > > > > > > management or tools change this to other AIPT mode.
> > > > > > > > > > This
> > > > > > > > > > "Whisper" mode
> > > > > > > > > > calls to set lower maximum and minimum RAPL (Running
> > > > > > > > > > Average Power
> > > > > > > > > > Limit)
> > > > > > > > > > via thermal tables. On Linux this leads to lower
> > > > > > > > > > performance even when
> > > > > > > > > > platform power profile is "balanced". This "Whisper"
> > > > > > > > > > mode
> > > > > > > > > > should
> > > > > > > > > > correspond to "quiet" mode.
> > > > > > > > > > 
> > > > > > > > > > So, when AIPT is present change the default mode to
> > > > > > > > > > "Standard" during
> > > > > > > > > > boot. Map the three platform power profile modes as
> > > > > > > > > > follows:
> > > > > > > > > > 
> > > > > > > > > > Power Profile Mode      AIPT mode
> > > > > > > > > > -----------------------------------
> > > > > > > > > > quiet            Whisper
> > > > > > > > > > balanced        Standard
> > > > > > > > > > performance        Performance
> > > > > > > > > > ------------------------------------
> > > > > > > > > > 
> > > > > > > > > > Here AIPT mode can be detected by checking presese of
> > > > > > > > > > "FANL" method
> > > > > > > > > > under
> > > > > > > > > > PNP HID "PNP0C14" and UID "ATK". If AIPT mode is
> > > > > > > > > > present,
> > > > > > > > > > this takes
> > > > > > > > > > precedence over the existing VIVO thermal policy.
> > > > > > > > > > These
> > > > > > > > > > modes are set
> > > > > > > > > > using "FANL" method.
> > > > > > > > > > 
> > > > > > > > > > Although this “FANL” method is not used in the Asus
> > > > > > > > > > WMI
> > > > > > > > > > driver, users
> > > > > > > > > > have used this method from user space [3] to set AIPT
> > > > > > > > > > modes. Used this
> > > > > > > > > > as a reference.
> > > > > > > > > > 
> > > > > > > > > > Link:
> > > > > > > > > > https://www.asus.com/content/laptop-asus-intelligent-performance-technology-aipt/
> > > > > > > > > > # [1]
> > > > > > > > > > Reported-by: Michael Larabel <Michael@phoronix.com>
> > > > > > > > > > Closes:
> > > > > > > > > > https://www.phoronix.com/review/lunar-lake-xe2/5 #
> > > > > > > > > > [2]
> > > > > > > > > > Link:
> > > > > > > > > > https://github.com/dominiksalvet/asus-fan-control/issues/151
> > > > > > > > > >   # [3]
> > > > > > > > > > Tested-by: Casey Bowman <casey.g.bowman@intel.com>
> > > > > > > > > > Signed-off-by: Srinivas Pandruvada
> > > > > > > > > > <srinivas.pandruvada@linux.intel.com>
> > > > > > > > > > ---
> > > > > > > > > >      drivers/platform/x86/asus-wmi.c | 93
> > > > > > > > > > +++++++++++++++++++++++++++++++--
> > > > > > > > > >      1 file changed, 89 insertions(+), 4 deletions(-)
> > > > > > > > > > 
> > > > > > > > > > diff --git a/drivers/platform/x86/asus-wmi.c
> > > > > > > > > > b/drivers/platform/x86/asus-wmi.c
> > > > > > > > > > index 7a48220b4f5a..06689d0f98c7 100644
> > > > > > > > > > --- a/drivers/platform/x86/asus-wmi.c
> > > > > > > > > > +++ b/drivers/platform/x86/asus-wmi.c
> > > > > > > > > > @@ -100,6 +100,11 @@ module_param(fnlock_default,
> > > > > > > > > > bool,
> > > > > > > > > > 0444);
> > > > > > > > > >      #define
> > > > > > > > > > ASUS_THROTTLE_THERMAL_POLICY_SILENT_VIVO    1
> > > > > > > > > >      #define
> > > > > > > > > > ASUS_THROTTLE_THERMAL_POLICY_OVERBOOST_VIVO    2
> > > > > > > > > > 
> > > > > > > > > > +#define AIPT_STANDARD                0
> > > > > > > > > > +#define AIPT_WHISPER                1
> > > > > > > > > > +#define AIPT_PERFORMANCE            2
> > > > > > > > > > +#define AIPT_FULL_SPEED                3
> > > > > > > > > > +
> > > > > > > > > >      #define PLATFORM_PROFILE_MAX 2
> > > > > > > > > > 
> > > > > > > > > >      #define USB_INTEL_XUSB2PR        0xD0
> > > > > > > > > > @@ -333,6 +338,9 @@ struct asus_wmi {
> > > > > > > > > >          struct asus_wmi_debug debug;
> > > > > > > > > > 
> > > > > > > > > >          struct asus_wmi_driver *driver;
> > > > > > > > > > +    acpi_handle acpi_mgmt_handle;
> > > > > > > > > > +    int asus_aipt_mode;
> > > > > > > > > > +    bool asus_aipt_present;
> > > > > > > > > >      };
> > > > > > > > > > 
> > > > > > > > > >      /* WMI
> > > > > > > > > > *****************************************************
> > > > > > > > > > ****
> > > > > > > > > > ***************/
> > > > > > > > > > @@ -3804,6 +3812,19 @@ static ssize_t
> > > > > > > > > > throttle_thermal_policy_store(struct device *dev,
> > > > > > > > > >      static DEVICE_ATTR_RW(throttle_thermal_policy);
> > > > > > > > > > 
> > > > > > > > > >      /* Platform profile
> > > > > > > > > > *****************************************************
> > > > > > > > > > ****
> > > > > > > > > > **/
> > > > > > > > > > +static int asus_wmi_write_aipt_mode(struct asus_wmi
> > > > > > > > > > *asus, int
> > > > > > > > > > aipt_mode)
> > > > > > > > > > +{
> > > > > > > > > > +    int status;
> > > > > > > > > > +
> > > > > > > > > > +    status = acpi_execute_simple_method(asus-
> > > > > > > > > > > acpi_mgmt_handle,
> > > > > > > > > > "FANL", aipt_mode);
> > > > > > > > > > +    if (ACPI_FAILURE(status)) {
> > > > > > > > > > +        acpi_handle_info(asus->acpi_mgmt_handle,
> > > > > > > > > > "FANL
> > > > > > > > > > execute
> > > > > > > > > > failed\n");
> > > > > > > > > > +        return -EIO;
> > > > > > > > > > +    }
> > > > > > > > > > +
> > > > > > > > > > +    return 0;
> > > > > > > > > > +}
> > > > > > > > > > +
> > > > > > > > > >      static int
> > > > > > > > > > asus_wmi_platform_profile_to_vivo(struct
> > > > > > > > > > asus_wmi *asus,
> > > > > > > > > > int mode)
> > > > > > > > > >      {
> > > > > > > > > >          bool vivo;
> > > > > > > > > > @@ -3844,6 +3865,26 @@ static int
> > > > > > > > > > asus_wmi_platform_profile_mode_from_vivo(struct
> > > > > > > > > > asus_wmi
> > > > > > > > > > *asus, int m
> > > > > > > > > >          return mode;
> > > > > > > > > >      }
> > > > > > > > > > 
> > > > > > > > > > +static int asus_wmi_aipt_platform_profile_get(struct
> > > > > > > > > > asus_wmi *asus,
> > > > > > > > > > +                          enum
> > > > > > > > > > platform_profile_option
> > > > > > > > > > *profile)
> > > > > > > > > > +{
> > > > > > > > > > +    switch (asus->asus_aipt_mode) {
> > > > > > > > > > +    case AIPT_STANDARD:
> > > > > > > > > > +        *profile = PLATFORM_PROFILE_BALANCED;
> > > > > > > > > > +        break;
> > > > > > > > > > +    case AIPT_PERFORMANCE:
> > > > > > > > > > +        *profile = PLATFORM_PROFILE_PERFORMANCE;
> > > > > > > > > > +        break;
> > > > > > > > > > +    case AIPT_WHISPER:
> > > > > > > > > > +        *profile = PLATFORM_PROFILE_QUIET;
> > > > > > > > > > +        break;
> > > > > > > > > > +    default:
> > > > > > > > > > +        return -EINVAL;
> > > > > > > > > > +    }
> > > > > > > > > > +
> > > > > > > > > > +    return 0;
> > > > > > > > > > +}
> > > > > > > > > > +
> > > > > > > > > >      static int asus_wmi_platform_profile_get(struct
> > > > > > > > > > platform_profile_handler *pprof,
> > > > > > > > > >                          enum platform_profile_option
> > > > > > > > > > *profile)
> > > > > > > > > >      {
> > > > > > > > > > @@ -3851,6 +3892,10 @@ static int
> > > > > > > > > > asus_wmi_platform_profile_get(struct
> > > > > > > > > > platform_profile_handler *pprof,
> > > > > > > > > >          int tp;
> > > > > > > > > > 
> > > > > > > > > >          asus = container_of(pprof, struct asus_wmi,
> > > > > > > > > > platform_profile_handler);
> > > > > > > > > > +
> > > > > > > > > > +    if (asus->asus_aipt_present)
> > > > > > > > > > +        return
> > > > > > > > > > asus_wmi_aipt_platform_profile_get(asus,
> > > > > > > > > > profile);
> > > > > > > > > > +
> > > > > > > > > >          tp = asus->throttle_thermal_policy_mode;
> > > > > > > > > > 
> > > > > > > > > >          switch
> > > > > > > > > > (asus_wmi_platform_profile_mode_from_vivo(asus, tp))
> > > > > > > > > > {
> > > > > > > > > > @@ -3874,26 +3919,42 @@ static int
> > > > > > > > > > asus_wmi_platform_profile_set(struct
> > > > > > > > > > platform_profile_handler *pprof,
> > > > > > > > > >                          enum platform_profile_option
> > > > > > > > > > profile)
> > > > > > > > > >      {
> > > > > > > > > >          struct asus_wmi *asus;
> > > > > > > > > > -    int tp;
> > > > > > > > > > +    int ret = 0, tp, aipt_mode;
> > > > > > > > > > 
> > > > > > > > > >          asus = container_of(pprof, struct asus_wmi,
> > > > > > > > > > platform_profile_handler);
> > > > > > > > > > 
> > > > > > > > > >          switch (profile) {
> > > > > > > > > >          case PLATFORM_PROFILE_PERFORMANCE:
> > > > > > > > > >              tp =
> > > > > > > > > > ASUS_THROTTLE_THERMAL_POLICY_OVERBOOST;
> > > > > > > > > > +        aipt_mode = AIPT_PERFORMANCE;
> > > > > > > > > >              break;
> > > > > > > > > >          case PLATFORM_PROFILE_BALANCED:
> > > > > > > > > >              tp =
> > > > > > > > > > ASUS_THROTTLE_THERMAL_POLICY_DEFAULT;
> > > > > > > > > > +        aipt_mode = AIPT_STANDARD;
> > > > > > > > > >              break;
> > > > > > > > > >          case PLATFORM_PROFILE_QUIET:
> > > > > > > > > >              tp =
> > > > > > > > > > ASUS_THROTTLE_THERMAL_POLICY_SILENT;
> > > > > > > > > > +        aipt_mode = AIPT_WHISPER;
> > > > > > > > > >              break;
> > > > > > > > > >          default:
> > > > > > > > > >              return -EOPNOTSUPP;
> > > > > > > > > >          }
> > > > > > > > > > 
> > > > > > > > > > -    asus->throttle_thermal_policy_mode =
> > > > > > > > > > asus_wmi_platform_profile_to_vivo(asus, tp);
> > > > > > > > > > -    return throttle_thermal_policy_write(asus);
> > > > > > > > > > +    if (asus->asus_aipt_present) {
> > > > > > > > > > +        ret = asus_wmi_write_aipt_mode(asus,
> > > > > > > > > > aipt_mode);
> > > > > > > > > > +        if (!ret) {
> > > > > > > > > > +            asus->asus_aipt_mode = aipt_mode;
> > > > > > > > > > +            goto skip_vivo;
> > > > > > > > > > +        }
> > > > > > > > > > +    }
> > > > > > > > > > +
> > > > > > > > > > +    if (asus->throttle_thermal_policy_dev) {
> > > > > > > > > > +        asus->throttle_thermal_policy_mode =
> > > > > > > > > > asus_wmi_platform_profile_to_vivo(asus, tp);
> > > > > > > > > > +        ret = throttle_thermal_policy_write(asus);
> > > > > > > > > > +    }
> > > > > > > > > > +
> > > > > > > > > > +skip_vivo:
> > > > > > > > > > +    return ret;
> > > > > > > > > >      }
> > > > > > > > > > 
> > > > > > > > > >      static int platform_profile_setup(struct
> > > > > > > > > > asus_wmi
> > > > > > > > > > *asus)
> > > > > > > > > > @@ -3905,7 +3966,7 @@ static int
> > > > > > > > > > platform_profile_setup(struct
> > > > > > > > > > asus_wmi *asus)
> > > > > > > > > >           * Not an error if a component
> > > > > > > > > > platform_profile
> > > > > > > > > > relies on is
> > > > > > > > > > unavailable
> > > > > > > > > >           * so early return, skipping the setup of
> > > > > > > > > > platform_profile.
> > > > > > > > > >           */
> > > > > > > > > > -    if (!asus->throttle_thermal_policy_dev)
> > > > > > > > > > +    if (!asus->throttle_thermal_policy_dev && !asus-
> > > > > > > > > > > asus_aipt_present)
> > > > > > > > > >              return 0;
> > > > > > > > > > 
> > > > > > > > > >          dev_info(dev, "Using throttle_thermal_policy
> > > > > > > > > > for
> > > > > > > > > > platform_profile support\n");
> > > > > > > > > > @@ -4538,6 +4599,7 @@ static int
> > > > > > > > > > asus_wmi_sysfs_init(struct
> > > > > > > > > > platform_device *device)
> > > > > > > > > >      static int asus_wmi_platform_init(struct
> > > > > > > > > > asus_wmi
> > > > > > > > > > *asus)
> > > > > > > > > >      {
> > > > > > > > > >          struct device *dev = &asus->platform_device-
> > > > > > > > > > >dev;
> > > > > > > > > > +    struct acpi_device *adev;
> > > > > > > > > >          char *wmi_uid;
> > > > > > > > > >          int rv;
> > > > > > > > > > 
> > > > > > > > > > @@ -4593,6 +4655,29 @@ static int
> > > > > > > > > > asus_wmi_platform_init(struct
> > > > > > > > > > asus_wmi *asus)
> > > > > > > > > >             
> > > > > > > > > > asus_wmi_set_devstate(ASUS_WMI_DEVID_CWAP,
> > > > > > > > > >                            asus->driver->quirks-
> > > > > > > > > > >wapf,
> > > > > > > > > > NULL);
> > > > > > > > > > 
> > > > > > > > > > +    /*
> > > > > > > > > > +     * Check presence of Intelligent Performance
> > > > > > > > > > Technology (AIPT).
> > > > > > > > > > +     * If present store acpi handle and set
> > > > > > > > > > asus_aipt_present to true.
> > > > > > > > > > +     */
> > > > > > > > > > +    adev = acpi_dev_get_first_match_dev("PNP0C14",
> > > > > > > > > > "ATK", -1);
> > > > > > > > > Is there really no way of changing the AIPT mode
> > > > > > > > > through
> > > > > > > > > the WMI
> > > > > > > > > interface?
> > > > > > > > > I would prefer using the WMI interface if available,
> > > > > > > > > since
> > > > > > > > > the
> > > > > > > > > firmware might
> > > > > > > > > assume that FANL is only called through the WMI
> > > > > > > > > interface.
> > > > > > > > > 
> > > > > > > > > Do you have a acpidump from a affected device?
> > > > > > > > > 
> > > > > > > > > Thanks,
> > > > > > > > > Armin Wolf
> > > > > > > > > 
> > > > > > > > I found a acpidump from a ASUS device with a matching
> > > > > > > > FANL
> > > > > > > > method. It seems that this method
> > > > > > > > can indeed be called using the WMI interface using the
> > > > > > > > DEVS()
> > > > > > > > WMI method:
> > > > > > > > 
> > > > > > > > [WmiMethodId(1398162756), Implemented] void DEVS([in]
> > > > > > > > uint32
> > > > > > > > Device_ID, [in] uint32 Control_status, [out] uint32
> > > > > > > > result);
> > > > > > > > 
> > > > > > > > If Device_ID is 0x00110019, then Control_status is passed
> > > > > > > > to
> > > > > > > > the FANL ACPI method.
> > > > > > > > 
> > > > > > > > It also seems that support for AIPT can be queried using
> > > > > > > > the
> > > > > > > > DSTS() WMI method:
> > > > > > > > 
> > > > > > > > [WmiMethodId(1398035268), Implemented] void DSTS([in]
> > > > > > > > uint32
> > > > > > > > Device_ID, [out] uint32 device_status);
> > > > > > > > 
> > > > > > > > Using Device_ID 0x00110019, the returned device status
> > > > > > > > seems
> > > > > > > > to contain the following information:
> > > > > > > > 
> > > > > > > > - 16-bit current AIPT mode
> > > > > > > > - 4-bit unknown value (possible values 2, 3 and 7, maybe
> > > > > > > > number of supported modes or some kind of bitmap?)
> > > > > > > > - 1-bit with is set when (GGIV (0x0907000C) == One) is
> > > > > > > > true
> > > > > > > I just saw this conversation and i think that the behaviour
> > > > > > > this
> > > > > > > patch will implement in the driver was already implemented
> > > > > > > in
> > > > > > > this patch
> > > > > > > that got added to kernel v6.12-rc3:
> > > > > > > https://lore.kernel.org/platform-driver-x86/20240609144849.2532-2-mohamed.ghanmi@supcom.tn/
> > > > > > > 
> > > > > > > this patch introduced
> > > > > > > ASUS_WMI_DEVID_THROTTLE_THERMAL_POLICY_VIVO
> > > > > > > 0x00110019 which is the device_id that changes the fan
> > > > > > > profiles. the
> > > > > > > naming is not clear because it was initially intended to
> > > > > > > add
> > > > > > > support for
> > > > > > > fan profiles for vivobook laptops but it ended up adding
> > > > > > > support
> > > > > > > for a lot of modern laptops.
> > > > > > Nice, you are absolutely right.
> > > > > > 
> > > > > > So this patch series is effectively already upstream, very
> > > > > > good.
> > > > > > I did some research and found out
> > > > > > that the status of this device id contains the following
> > > > > > data:
> > > > > > 
> > > > > > Status          Supported Modes
> > > > > > -------------------------------
> > > > > > 0x00[1]300[xx]  0 1 2
> > > > > > 0x000700[xx]    0 1 2
> > > > > > 0x000200[xx]    ??? (ODV0)
> > > > > > 0x000700[xx]    0 1 2
> > > > > > 0x0a0700[xx]    ??? (ODV0)
> > > > > > 
> > > > > > While i have no clue about the meaning of the remaining bits,
> > > > > > i
> > > > > > can report that the first 8 Bits
> > > > > > contain the current thermal mode. Maybe adding support for
> > > > > > this
> > > > > > would be nice, so the current
> > > > > > thermal mode can be read directly from the hardware.
> > > > > > 
> > > > > > I also found out that on some models the thermal mode
> > > > > > actually
> > > > > > modifies the ODV0 variable which
> > > > > > is consumed by int3400_thermal and exposed to the Intel
> > > > > > Thermal
> > > > > > Daemon. So maybe the lackluster
> > > > > > performance also has something to do with it.
> > > > > > 
> > > > > > > a point that Srinivas Pandruvada mentioned about RAPL
> > > > > > > (Running
> > > > > > > Average Power Limit)
> > > > > > > is valid for a lot of modern vivobook and zenbook laptops
> > > > > > > but i
> > > > > > > think
> > > > > > > it's unrelated to fan profiles.
> > > > > > > 
> > > > > > > a lot of asus laptops that have intel cpus suffer from
> > > > > > > power
> > > > > > > throttling.
> > > > > > > for exemple in my case using windows, changing fan profiles
> > > > > > > will lead to max power
> > > > > > > changing to the values indicated in the table below (asus
> > > > > > > vivobook 16x
> > > > > > > pro k6604) which leads to higher performance than linux
> > > > > > > 
> > > > > > > fan Profile             power limit
> > > > > > > -----------------------------------
> > > > > > > Whisper                 50watts
> > > > > > > Standard                120watts
> > > > > > > Performance             149watts
> > > > > > > ------------------------------------
> > > > > > > 
> > > > > > > However in linux, even after changing to the appropriate
> > > > > > > fan
> > > > > > > profile,
> > > > > > > the power is still capped at 50watts and i found the reason
> > > > > > > why
> > > > > > > 
> > > > > > > here is the results of using the powercap-info command:
> > > > > > > 
> > > > > > > intel-rapl-mmio
> > > > > > >      enabled: 1
> > > > > > >      Zone 0
> > > > > > >        name: package-0
> > > > > > >        enabled: 1
> > > > > > >        max_energy_range_uj: 262143328850
> > > > > > >        Constraint 0
> > > > > > >          name: long_term
> > > > > > >          power_limit_uw: 30000000
> > > > > > >          time_window_us: 55967744
> > > > > > >          max_power_uw: 55000000
> > > > > > >        Constraint 1
> > > > > > >          name: short_term
> > > > > > >          power_limit_uw: 55000000
> > > > > > >          time_window_us: 2440
> > > > > > >          max_power_uw: 0
> > > > > > > intel-rapl
> > > > > > >      enabled: 1
> > > > > > >      Zone 0
> > > > > > >        name: package-0
> > > > > > >        enabled: 1
> > > > > > >        max_energy_range_uj: 262143328850
> > > > > > >        Constraint 0
> > > > > > >          name: long_term
> > > > > > >          power_limit_uw: 157000000
> > > > > > >          time_window_us: 55967744
> > > > > > >          max_power_uw: 55000000
> > > > > > >        Constraint 1
> > > > > > >          name: short_term
> > > > > > >          power_limit_uw: 157000000
> > > > > > >          time_window_us: 2440
> > > > > > >          max_power_uw: 0
> > > > > > >        Constraint 2
> > > > > > >          name: peak_power
> > > > > > >          power_limit_uw: 200000000
> > > > > > >          max_power_uw: 0
> > > > > > >        Zone 0:0
> > > > > > >          name: core
> > > > > > >          enabled: 0
> > > > > > >          max_energy_range_uj: 262143328850
> > > > > > >          Constraint 0
> > > > > > >            name: long_term
> > > > > > >            power_limit_uw: 0
> > > > > > >            time_window_us: 976
> > > > > > >        Zone 0:1
> > > > > > >          name: uncore
> > > > > > >          enabled: 0
> > > > > > >          max_energy_range_uj: 262143328850
> > > > > > >          Constraint 0
> > > > > > >            name: long_term
> > > > > > >            power_limit_uw: 0
> > > > > > >            time_window_us: 976
> > > > > > >      Zone 1
> > > > > > >        name: psys
> > > > > > >        enabled: 0
> > > > > > >        max_energy_range_uj: 262143328850
> > > > > > >        Constraint 0
> > > > > > >          name: long_term
> > > > > > >          power_limit_uw: 0
> > > > > > >          time_window_us: 27983872
> > > > > > >        Constraint 1
> > > > > > >          name: short_term
> > > > > > >          power_limit_uw: 0
> > > > > > >          time_window_us: 976
> > > > > > > 
> > > > > > > 
> > > > > > > as seen by the output of the command, the intel-rapl-mmio
> > > > > > > is
> > > > > > > causing the
> > > > > > > throttling as it sets power_limit_uw to 30 watts
> > > > > > > (readonly). so
> > > > > > > the current fix
> > > > > > > that i'm currently using is disabling the intel-rapl-mmio
> > > > > > > leaving only
> > > > > > > the intel-rapl which sets power_limit_uw to 157watts using
> > > > > > > this
> > > > > > > command: powercap-set -p intel-rapl-mmio -z 0 -e 0
> > > > > > > 
> > > > > > > this will lead to the laptop being able to reach it's
> > > > > > > maximum
> > > > > > > power
> > > > > > > limit.
> > > > > > > 
> > > > > > > after doing this, when i change the platform profile
> > > > > > > through
> > > > > > > sysfs the
> > > > > > > laptop will start behaving as described in the table above
> > > > > > > exactly like
> > > > > > > windows.
> > > > > > > 
> > > > > > > in conclusion, the asus-wmi driver already has the platform
> > > > > > > profiles
> > > > > > > (a.k.a fan profiles)
> > > > > > > implemented and I think that the power throttling is caused
> > > > > > > by
> > > > > > > either
> > > > > > > intel Power Capping Framework or asus bios.
> > > > > > Or the Intel Thermal Daemon somehow does not properly support
> > > > > > intel-rapl-mmio
> > > > > > or is not installed.
> > > > > This was exactly it. the Intel Thermal Daemon wasn't installed.
> > > > > now
> > > > > everything is working as expected!
> > > > > 
> > > > > Best regards,
> > > > > Mohamed G.
> > > > Interesting.
> > > > 
> > > > Srinivas, can you verify that the Intel Thermal Daemon is
> > > > installed
> > > > on the affected
> > > > Asus machines?
> > > > 
> > > > I begin to wonder why this thermal daemon is a userspace
> > > > component,
> > > > stuff like thermal
> > > > management should use the thermal subsystem inside the kernel.
> > > Thanks for detailed analysis here.
> > > 
> > > Here the problem is not thermal daemon or INT340x (I am author of
> > > both).
> > > 
> > > The ODVP variable is input into thermal tables. These thermal
> > > tables
> > > are defined by Asus via DTT tables. This results in matching
> > > certain
> > > max and min power limits and also various temperature limits.
> > > 
> > > By default the laptop in question will boot with max limit of 17W,
> > > which is limit for whisper mode match based on ODVP variables.
> > > There is
> > > a SEN1 limit of 50C, once the limit reaches to 50C, you need to
> > > throttle upto 12W as per thermal table.
> > > 
> > > If you stop thermald, yes, you will stay in 17W, so you will not
> > > see
> > > throttle but your SEN1 (seems skin limit) limit will be violated.
> > > Also if you remove the rapl_mmio driver, that will also work as no
> > > means to set power limits.
> > > 
> > > Windows will do exactly same. Meeting thermal limit is a
> > > requirement.
> > > 
> > > But on Windows this ODVP variable will be set to 0 to match
> > > standard
> > > mode. This will result in matching rules which will set the max
> > > power
> > > to 22W and min to 17W also increase thermal limit to 55C. So
> > > essentially lost 5W of performance.
> > > 
> > > Here WMI method as you correctly found out matching VIVO thermal
> > > policy. But it will not set ODVP variable unless you call a WMI
> > > method
> > > to set the mode via DEVS() on the same device ID. So although
> > > platform
> > > power policy will say "balanced" it is actually "Whisper" for
> > > thermal
> > > policy. On Windows when system boots the Asus service will set to
> > > standard and will set the ODVP variable to 0 and will match the
> > > correct
> > > table.
> > > 
> > > After Luke's help, I can do a work around from user space to change
> > > the
> > > power policy to any other policy than balanced and then again set
> > > to
> > > balance. This will result in setting the policy to standard via
> > > DEVS()
> > > and also set the correct ODVP variable.
> > > 
> > > This driver on unload change the vivo thermal policy to default.
> > > But
> > > doesn't change that to default on load time to match the default
> > > platform power policy. So rmmod and modprobe of driver should also
> > > fix.

Thank you Srinivas for the insights!

> > > 
> > > Thanks,
> > > Srinivas
> > > 
> > Good point, so basically throttle_thermal_policy_set_default() need
> > to be called during
> > initialization of the thermal profile. Maybe you can send another
> > patch which implements this?
> 
> I have already tested this change. But this seems a regression, so want
> to confirm first as it was intentional. The following commit removed
> the call. If it was unintentional, Mohamed can try to submit a change.
> 
> 
> commit bcbfcebda2cbc6a10a347d726e4a4f69e43a864e
> Author: Mohamed Ghanmi <mohamed.ghanmi@supcom.tn>
> Date:   Sun Jun 9 15:48:49 2024 +0100
> 
> Thanks,
> Srinivas

This was definitely not intentional. I'll write a patch asap
I also want your opinion on adding naming changes to the commit to
future proof the patch as it has been proven that it implements platform
profiles for various modern laptops other than the vivobooks and to
avoid any future confusion about the use of the patch

Best Regards,
Mohamed G.

> 
> 
> 
> > 
> > Thanks,
> > Armin Wolf
> > 
> > > > Thanks,
> > > > Armin Wolf
> > > > 
> > > 
>
Armin Wolf Oct. 25, 2024, 6:33 p.m. UTC | #16
Am 25.10.24 um 15:30 schrieb Mohamed Ghanmi:

> On Thu, Oct 24, 2024 at 11:15:31AM -0700, srinivas pandruvada wrote:
>> On Wed, 2024-10-23 at 22:32 +0200, Armin Wolf wrote:
>>> Am 23.10.24 um 22:15 schrieb srinivas pandruvada:
>>>
>>>> On Wed, 2024-10-23 at 20:57 +0200, Armin Wolf wrote:
>>>>> Am 23.10.24 um 19:59 schrieb Mohamed Ghanmi:
>>>>>
>>>>>> On Wed, Oct 23, 2024 at 06:31:17PM +0200, Armin Wolf wrote:
>>>>>>> Am 23.10.24 um 16:44 schrieb Mohamed Ghanmi:
>>>>>>>
>>>>>>>> Hello !
>>>>>>>> On Sun, Oct 20, 2024 at 09:42:45PM +0200, Armin Wolf wrote:
>>>>>>>>> Am 20.10.24 um 21:05 schrieb Armin Wolf:
>>>>>>>>>
>>>>>>>>>> Am 20.10.24 um 08:50 schrieb Srinivas Pandruvada:
>>>>>>>>>>
>>>>>>>>>>> Some recent Asus laptops are supporting ASUS
>>>>>>>>>>> Intelligent
>>>>>>>>>>> Performance
>>>>>>>>>>> Technology (AIPT). This solution allows users to have
>>>>>>>>>>> maximized CPU
>>>>>>>>>>> performance in models with a chassis providing more
>>>>>>>>>>> thermal head room.
>>>>>>>>>>> Refer to [1].
>>>>>>>>>>>
>>>>>>>>>>> There are major performance issues when Linux is
>>>>>>>>>>> installed on these
>>>>>>>>>>> laptops compared to Windows install. One such report
>>>>>>>>>>> is
>>>>>>>>>>> published for
>>>>>>>>>>> Graphics benchmarks on Asus ASUS Zenbook S 14 with
>>>>>>>>>>> Lunar
>>>>>>>>>>> Lake
>>>>>>>>>>> processors [2].
>>>>>>>>>>>
>>>>>>>>>>> By default, these laptops are booting in "Whisper
>>>>>>>>>>> Mode"
>>>>>>>>>>> till OS power
>>>>>>>>>>> management or tools change this to other AIPT mode.
>>>>>>>>>>> This
>>>>>>>>>>> "Whisper" mode
>>>>>>>>>>> calls to set lower maximum and minimum RAPL (Running
>>>>>>>>>>> Average Power
>>>>>>>>>>> Limit)
>>>>>>>>>>> via thermal tables. On Linux this leads to lower
>>>>>>>>>>> performance even when
>>>>>>>>>>> platform power profile is "balanced". This "Whisper"
>>>>>>>>>>> mode
>>>>>>>>>>> should
>>>>>>>>>>> correspond to "quiet" mode.
>>>>>>>>>>>
>>>>>>>>>>> So, when AIPT is present change the default mode to
>>>>>>>>>>> "Standard" during
>>>>>>>>>>> boot. Map the three platform power profile modes as
>>>>>>>>>>> follows:
>>>>>>>>>>>
>>>>>>>>>>> Power Profile Mode      AIPT mode
>>>>>>>>>>> -----------------------------------
>>>>>>>>>>> quiet            Whisper
>>>>>>>>>>> balanced        Standard
>>>>>>>>>>> performance        Performance
>>>>>>>>>>> ------------------------------------
>>>>>>>>>>>
>>>>>>>>>>> Here AIPT mode can be detected by checking presese of
>>>>>>>>>>> "FANL" method
>>>>>>>>>>> under
>>>>>>>>>>> PNP HID "PNP0C14" and UID "ATK". If AIPT mode is
>>>>>>>>>>> present,
>>>>>>>>>>> this takes
>>>>>>>>>>> precedence over the existing VIVO thermal policy.
>>>>>>>>>>> These
>>>>>>>>>>> modes are set
>>>>>>>>>>> using "FANL" method.
>>>>>>>>>>>
>>>>>>>>>>> Although this “FANL” method is not used in the Asus
>>>>>>>>>>> WMI
>>>>>>>>>>> driver, users
>>>>>>>>>>> have used this method from user space [3] to set AIPT
>>>>>>>>>>> modes. Used this
>>>>>>>>>>> as a reference.
>>>>>>>>>>>
>>>>>>>>>>> Link:
>>>>>>>>>>> https://www.asus.com/content/laptop-asus-intelligent-performance-technology-aipt/
>>>>>>>>>>> # [1]
>>>>>>>>>>> Reported-by: Michael Larabel <Michael@phoronix.com>
>>>>>>>>>>> Closes:
>>>>>>>>>>> https://www.phoronix.com/review/lunar-lake-xe2/5 #
>>>>>>>>>>> [2]
>>>>>>>>>>> Link:
>>>>>>>>>>> https://github.com/dominiksalvet/asus-fan-control/issues/151
>>>>>>>>>>>    # [3]
>>>>>>>>>>> Tested-by: Casey Bowman <casey.g.bowman@intel.com>
>>>>>>>>>>> Signed-off-by: Srinivas Pandruvada
>>>>>>>>>>> <srinivas.pandruvada@linux.intel.com>
>>>>>>>>>>> ---
>>>>>>>>>>>       drivers/platform/x86/asus-wmi.c | 93
>>>>>>>>>>> +++++++++++++++++++++++++++++++--
>>>>>>>>>>>       1 file changed, 89 insertions(+), 4 deletions(-)
>>>>>>>>>>>
>>>>>>>>>>> diff --git a/drivers/platform/x86/asus-wmi.c
>>>>>>>>>>> b/drivers/platform/x86/asus-wmi.c
>>>>>>>>>>> index 7a48220b4f5a..06689d0f98c7 100644
>>>>>>>>>>> --- a/drivers/platform/x86/asus-wmi.c
>>>>>>>>>>> +++ b/drivers/platform/x86/asus-wmi.c
>>>>>>>>>>> @@ -100,6 +100,11 @@ module_param(fnlock_default,
>>>>>>>>>>> bool,
>>>>>>>>>>> 0444);
>>>>>>>>>>>       #define
>>>>>>>>>>> ASUS_THROTTLE_THERMAL_POLICY_SILENT_VIVO    1
>>>>>>>>>>>       #define
>>>>>>>>>>> ASUS_THROTTLE_THERMAL_POLICY_OVERBOOST_VIVO    2
>>>>>>>>>>>
>>>>>>>>>>> +#define AIPT_STANDARD                0
>>>>>>>>>>> +#define AIPT_WHISPER                1
>>>>>>>>>>> +#define AIPT_PERFORMANCE            2
>>>>>>>>>>> +#define AIPT_FULL_SPEED                3
>>>>>>>>>>> +
>>>>>>>>>>>       #define PLATFORM_PROFILE_MAX 2
>>>>>>>>>>>
>>>>>>>>>>>       #define USB_INTEL_XUSB2PR        0xD0
>>>>>>>>>>> @@ -333,6 +338,9 @@ struct asus_wmi {
>>>>>>>>>>>           struct asus_wmi_debug debug;
>>>>>>>>>>>
>>>>>>>>>>>           struct asus_wmi_driver *driver;
>>>>>>>>>>> +    acpi_handle acpi_mgmt_handle;
>>>>>>>>>>> +    int asus_aipt_mode;
>>>>>>>>>>> +    bool asus_aipt_present;
>>>>>>>>>>>       };
>>>>>>>>>>>
>>>>>>>>>>>       /* WMI
>>>>>>>>>>> *****************************************************
>>>>>>>>>>> ****
>>>>>>>>>>> ***************/
>>>>>>>>>>> @@ -3804,6 +3812,19 @@ static ssize_t
>>>>>>>>>>> throttle_thermal_policy_store(struct device *dev,
>>>>>>>>>>>       static DEVICE_ATTR_RW(throttle_thermal_policy);
>>>>>>>>>>>
>>>>>>>>>>>       /* Platform profile
>>>>>>>>>>> *****************************************************
>>>>>>>>>>> ****
>>>>>>>>>>> **/
>>>>>>>>>>> +static int asus_wmi_write_aipt_mode(struct asus_wmi
>>>>>>>>>>> *asus, int
>>>>>>>>>>> aipt_mode)
>>>>>>>>>>> +{
>>>>>>>>>>> +    int status;
>>>>>>>>>>> +
>>>>>>>>>>> +    status = acpi_execute_simple_method(asus-
>>>>>>>>>>>> acpi_mgmt_handle,
>>>>>>>>>>> "FANL", aipt_mode);
>>>>>>>>>>> +    if (ACPI_FAILURE(status)) {
>>>>>>>>>>> +        acpi_handle_info(asus->acpi_mgmt_handle,
>>>>>>>>>>> "FANL
>>>>>>>>>>> execute
>>>>>>>>>>> failed\n");
>>>>>>>>>>> +        return -EIO;
>>>>>>>>>>> +    }
>>>>>>>>>>> +
>>>>>>>>>>> +    return 0;
>>>>>>>>>>> +}
>>>>>>>>>>> +
>>>>>>>>>>>       static int
>>>>>>>>>>> asus_wmi_platform_profile_to_vivo(struct
>>>>>>>>>>> asus_wmi *asus,
>>>>>>>>>>> int mode)
>>>>>>>>>>>       {
>>>>>>>>>>>           bool vivo;
>>>>>>>>>>> @@ -3844,6 +3865,26 @@ static int
>>>>>>>>>>> asus_wmi_platform_profile_mode_from_vivo(struct
>>>>>>>>>>> asus_wmi
>>>>>>>>>>> *asus, int m
>>>>>>>>>>>           return mode;
>>>>>>>>>>>       }
>>>>>>>>>>>
>>>>>>>>>>> +static int asus_wmi_aipt_platform_profile_get(struct
>>>>>>>>>>> asus_wmi *asus,
>>>>>>>>>>> +                          enum
>>>>>>>>>>> platform_profile_option
>>>>>>>>>>> *profile)
>>>>>>>>>>> +{
>>>>>>>>>>> +    switch (asus->asus_aipt_mode) {
>>>>>>>>>>> +    case AIPT_STANDARD:
>>>>>>>>>>> +        *profile = PLATFORM_PROFILE_BALANCED;
>>>>>>>>>>> +        break;
>>>>>>>>>>> +    case AIPT_PERFORMANCE:
>>>>>>>>>>> +        *profile = PLATFORM_PROFILE_PERFORMANCE;
>>>>>>>>>>> +        break;
>>>>>>>>>>> +    case AIPT_WHISPER:
>>>>>>>>>>> +        *profile = PLATFORM_PROFILE_QUIET;
>>>>>>>>>>> +        break;
>>>>>>>>>>> +    default:
>>>>>>>>>>> +        return -EINVAL;
>>>>>>>>>>> +    }
>>>>>>>>>>> +
>>>>>>>>>>> +    return 0;
>>>>>>>>>>> +}
>>>>>>>>>>> +
>>>>>>>>>>>       static int asus_wmi_platform_profile_get(struct
>>>>>>>>>>> platform_profile_handler *pprof,
>>>>>>>>>>>                           enum platform_profile_option
>>>>>>>>>>> *profile)
>>>>>>>>>>>       {
>>>>>>>>>>> @@ -3851,6 +3892,10 @@ static int
>>>>>>>>>>> asus_wmi_platform_profile_get(struct
>>>>>>>>>>> platform_profile_handler *pprof,
>>>>>>>>>>>           int tp;
>>>>>>>>>>>
>>>>>>>>>>>           asus = container_of(pprof, struct asus_wmi,
>>>>>>>>>>> platform_profile_handler);
>>>>>>>>>>> +
>>>>>>>>>>> +    if (asus->asus_aipt_present)
>>>>>>>>>>> +        return
>>>>>>>>>>> asus_wmi_aipt_platform_profile_get(asus,
>>>>>>>>>>> profile);
>>>>>>>>>>> +
>>>>>>>>>>>           tp = asus->throttle_thermal_policy_mode;
>>>>>>>>>>>
>>>>>>>>>>>           switch
>>>>>>>>>>> (asus_wmi_platform_profile_mode_from_vivo(asus, tp))
>>>>>>>>>>> {
>>>>>>>>>>> @@ -3874,26 +3919,42 @@ static int
>>>>>>>>>>> asus_wmi_platform_profile_set(struct
>>>>>>>>>>> platform_profile_handler *pprof,
>>>>>>>>>>>                           enum platform_profile_option
>>>>>>>>>>> profile)
>>>>>>>>>>>       {
>>>>>>>>>>>           struct asus_wmi *asus;
>>>>>>>>>>> -    int tp;
>>>>>>>>>>> +    int ret = 0, tp, aipt_mode;
>>>>>>>>>>>
>>>>>>>>>>>           asus = container_of(pprof, struct asus_wmi,
>>>>>>>>>>> platform_profile_handler);
>>>>>>>>>>>
>>>>>>>>>>>           switch (profile) {
>>>>>>>>>>>           case PLATFORM_PROFILE_PERFORMANCE:
>>>>>>>>>>>               tp =
>>>>>>>>>>> ASUS_THROTTLE_THERMAL_POLICY_OVERBOOST;
>>>>>>>>>>> +        aipt_mode = AIPT_PERFORMANCE;
>>>>>>>>>>>               break;
>>>>>>>>>>>           case PLATFORM_PROFILE_BALANCED:
>>>>>>>>>>>               tp =
>>>>>>>>>>> ASUS_THROTTLE_THERMAL_POLICY_DEFAULT;
>>>>>>>>>>> +        aipt_mode = AIPT_STANDARD;
>>>>>>>>>>>               break;
>>>>>>>>>>>           case PLATFORM_PROFILE_QUIET:
>>>>>>>>>>>               tp =
>>>>>>>>>>> ASUS_THROTTLE_THERMAL_POLICY_SILENT;
>>>>>>>>>>> +        aipt_mode = AIPT_WHISPER;
>>>>>>>>>>>               break;
>>>>>>>>>>>           default:
>>>>>>>>>>>               return -EOPNOTSUPP;
>>>>>>>>>>>           }
>>>>>>>>>>>
>>>>>>>>>>> -    asus->throttle_thermal_policy_mode =
>>>>>>>>>>> asus_wmi_platform_profile_to_vivo(asus, tp);
>>>>>>>>>>> -    return throttle_thermal_policy_write(asus);
>>>>>>>>>>> +    if (asus->asus_aipt_present) {
>>>>>>>>>>> +        ret = asus_wmi_write_aipt_mode(asus,
>>>>>>>>>>> aipt_mode);
>>>>>>>>>>> +        if (!ret) {
>>>>>>>>>>> +            asus->asus_aipt_mode = aipt_mode;
>>>>>>>>>>> +            goto skip_vivo;
>>>>>>>>>>> +        }
>>>>>>>>>>> +    }
>>>>>>>>>>> +
>>>>>>>>>>> +    if (asus->throttle_thermal_policy_dev) {
>>>>>>>>>>> +        asus->throttle_thermal_policy_mode =
>>>>>>>>>>> asus_wmi_platform_profile_to_vivo(asus, tp);
>>>>>>>>>>> +        ret = throttle_thermal_policy_write(asus);
>>>>>>>>>>> +    }
>>>>>>>>>>> +
>>>>>>>>>>> +skip_vivo:
>>>>>>>>>>> +    return ret;
>>>>>>>>>>>       }
>>>>>>>>>>>
>>>>>>>>>>>       static int platform_profile_setup(struct
>>>>>>>>>>> asus_wmi
>>>>>>>>>>> *asus)
>>>>>>>>>>> @@ -3905,7 +3966,7 @@ static int
>>>>>>>>>>> platform_profile_setup(struct
>>>>>>>>>>> asus_wmi *asus)
>>>>>>>>>>>            * Not an error if a component
>>>>>>>>>>> platform_profile
>>>>>>>>>>> relies on is
>>>>>>>>>>> unavailable
>>>>>>>>>>>            * so early return, skipping the setup of
>>>>>>>>>>> platform_profile.
>>>>>>>>>>>            */
>>>>>>>>>>> -    if (!asus->throttle_thermal_policy_dev)
>>>>>>>>>>> +    if (!asus->throttle_thermal_policy_dev && !asus-
>>>>>>>>>>>> asus_aipt_present)
>>>>>>>>>>>               return 0;
>>>>>>>>>>>
>>>>>>>>>>>           dev_info(dev, "Using throttle_thermal_policy
>>>>>>>>>>> for
>>>>>>>>>>> platform_profile support\n");
>>>>>>>>>>> @@ -4538,6 +4599,7 @@ static int
>>>>>>>>>>> asus_wmi_sysfs_init(struct
>>>>>>>>>>> platform_device *device)
>>>>>>>>>>>       static int asus_wmi_platform_init(struct
>>>>>>>>>>> asus_wmi
>>>>>>>>>>> *asus)
>>>>>>>>>>>       {
>>>>>>>>>>>           struct device *dev = &asus->platform_device-
>>>>>>>>>>>> dev;
>>>>>>>>>>> +    struct acpi_device *adev;
>>>>>>>>>>>           char *wmi_uid;
>>>>>>>>>>>           int rv;
>>>>>>>>>>>
>>>>>>>>>>> @@ -4593,6 +4655,29 @@ static int
>>>>>>>>>>> asus_wmi_platform_init(struct
>>>>>>>>>>> asus_wmi *asus)
>>>>>>>>>>>
>>>>>>>>>>> asus_wmi_set_devstate(ASUS_WMI_DEVID_CWAP,
>>>>>>>>>>>                             asus->driver->quirks-
>>>>>>>>>>>> wapf,
>>>>>>>>>>> NULL);
>>>>>>>>>>>
>>>>>>>>>>> +    /*
>>>>>>>>>>> +     * Check presence of Intelligent Performance
>>>>>>>>>>> Technology (AIPT).
>>>>>>>>>>> +     * If present store acpi handle and set
>>>>>>>>>>> asus_aipt_present to true.
>>>>>>>>>>> +     */
>>>>>>>>>>> +    adev = acpi_dev_get_first_match_dev("PNP0C14",
>>>>>>>>>>> "ATK", -1);
>>>>>>>>>> Is there really no way of changing the AIPT mode
>>>>>>>>>> through
>>>>>>>>>> the WMI
>>>>>>>>>> interface?
>>>>>>>>>> I would prefer using the WMI interface if available,
>>>>>>>>>> since
>>>>>>>>>> the
>>>>>>>>>> firmware might
>>>>>>>>>> assume that FANL is only called through the WMI
>>>>>>>>>> interface.
>>>>>>>>>>
>>>>>>>>>> Do you have a acpidump from a affected device?
>>>>>>>>>>
>>>>>>>>>> Thanks,
>>>>>>>>>> Armin Wolf
>>>>>>>>>>
>>>>>>>>> I found a acpidump from a ASUS device with a matching
>>>>>>>>> FANL
>>>>>>>>> method. It seems that this method
>>>>>>>>> can indeed be called using the WMI interface using the
>>>>>>>>> DEVS()
>>>>>>>>> WMI method:
>>>>>>>>>
>>>>>>>>> [WmiMethodId(1398162756), Implemented] void DEVS([in]
>>>>>>>>> uint32
>>>>>>>>> Device_ID, [in] uint32 Control_status, [out] uint32
>>>>>>>>> result);
>>>>>>>>>
>>>>>>>>> If Device_ID is 0x00110019, then Control_status is passed
>>>>>>>>> to
>>>>>>>>> the FANL ACPI method.
>>>>>>>>>
>>>>>>>>> It also seems that support for AIPT can be queried using
>>>>>>>>> the
>>>>>>>>> DSTS() WMI method:
>>>>>>>>>
>>>>>>>>> [WmiMethodId(1398035268), Implemented] void DSTS([in]
>>>>>>>>> uint32
>>>>>>>>> Device_ID, [out] uint32 device_status);
>>>>>>>>>
>>>>>>>>> Using Device_ID 0x00110019, the returned device status
>>>>>>>>> seems
>>>>>>>>> to contain the following information:
>>>>>>>>>
>>>>>>>>> - 16-bit current AIPT mode
>>>>>>>>> - 4-bit unknown value (possible values 2, 3 and 7, maybe
>>>>>>>>> number of supported modes or some kind of bitmap?)
>>>>>>>>> - 1-bit with is set when (GGIV (0x0907000C) == One) is
>>>>>>>>> true
>>>>>>>> I just saw this conversation and i think that the behaviour
>>>>>>>> this
>>>>>>>> patch will implement in the driver was already implemented
>>>>>>>> in
>>>>>>>> this patch
>>>>>>>> that got added to kernel v6.12-rc3:
>>>>>>>> https://lore.kernel.org/platform-driver-x86/20240609144849.2532-2-mohamed.ghanmi@supcom.tn/
>>>>>>>>
>>>>>>>> this patch introduced
>>>>>>>> ASUS_WMI_DEVID_THROTTLE_THERMAL_POLICY_VIVO
>>>>>>>> 0x00110019 which is the device_id that changes the fan
>>>>>>>> profiles. the
>>>>>>>> naming is not clear because it was initially intended to
>>>>>>>> add
>>>>>>>> support for
>>>>>>>> fan profiles for vivobook laptops but it ended up adding
>>>>>>>> support
>>>>>>>> for a lot of modern laptops.
>>>>>>> Nice, you are absolutely right.
>>>>>>>
>>>>>>> So this patch series is effectively already upstream, very
>>>>>>> good.
>>>>>>> I did some research and found out
>>>>>>> that the status of this device id contains the following
>>>>>>> data:
>>>>>>>
>>>>>>> Status          Supported Modes
>>>>>>> -------------------------------
>>>>>>> 0x00[1]300[xx]  0 1 2
>>>>>>> 0x000700[xx]    0 1 2
>>>>>>> 0x000200[xx]    ??? (ODV0)
>>>>>>> 0x000700[xx]    0 1 2
>>>>>>> 0x0a0700[xx]    ??? (ODV0)
>>>>>>>
>>>>>>> While i have no clue about the meaning of the remaining bits,
>>>>>>> i
>>>>>>> can report that the first 8 Bits
>>>>>>> contain the current thermal mode. Maybe adding support for
>>>>>>> this
>>>>>>> would be nice, so the current
>>>>>>> thermal mode can be read directly from the hardware.
>>>>>>>
>>>>>>> I also found out that on some models the thermal mode
>>>>>>> actually
>>>>>>> modifies the ODV0 variable which
>>>>>>> is consumed by int3400_thermal and exposed to the Intel
>>>>>>> Thermal
>>>>>>> Daemon. So maybe the lackluster
>>>>>>> performance also has something to do with it.
>>>>>>>
>>>>>>>> a point that Srinivas Pandruvada mentioned about RAPL
>>>>>>>> (Running
>>>>>>>> Average Power Limit)
>>>>>>>> is valid for a lot of modern vivobook and zenbook laptops
>>>>>>>> but i
>>>>>>>> think
>>>>>>>> it's unrelated to fan profiles.
>>>>>>>>
>>>>>>>> a lot of asus laptops that have intel cpus suffer from
>>>>>>>> power
>>>>>>>> throttling.
>>>>>>>> for exemple in my case using windows, changing fan profiles
>>>>>>>> will lead to max power
>>>>>>>> changing to the values indicated in the table below (asus
>>>>>>>> vivobook 16x
>>>>>>>> pro k6604) which leads to higher performance than linux
>>>>>>>>
>>>>>>>> fan Profile             power limit
>>>>>>>> -----------------------------------
>>>>>>>> Whisper                 50watts
>>>>>>>> Standard                120watts
>>>>>>>> Performance             149watts
>>>>>>>> ------------------------------------
>>>>>>>>
>>>>>>>> However in linux, even after changing to the appropriate
>>>>>>>> fan
>>>>>>>> profile,
>>>>>>>> the power is still capped at 50watts and i found the reason
>>>>>>>> why
>>>>>>>>
>>>>>>>> here is the results of using the powercap-info command:
>>>>>>>>
>>>>>>>> intel-rapl-mmio
>>>>>>>>       enabled: 1
>>>>>>>>       Zone 0
>>>>>>>>         name: package-0
>>>>>>>>         enabled: 1
>>>>>>>>         max_energy_range_uj: 262143328850
>>>>>>>>         Constraint 0
>>>>>>>>           name: long_term
>>>>>>>>           power_limit_uw: 30000000
>>>>>>>>           time_window_us: 55967744
>>>>>>>>           max_power_uw: 55000000
>>>>>>>>         Constraint 1
>>>>>>>>           name: short_term
>>>>>>>>           power_limit_uw: 55000000
>>>>>>>>           time_window_us: 2440
>>>>>>>>           max_power_uw: 0
>>>>>>>> intel-rapl
>>>>>>>>       enabled: 1
>>>>>>>>       Zone 0
>>>>>>>>         name: package-0
>>>>>>>>         enabled: 1
>>>>>>>>         max_energy_range_uj: 262143328850
>>>>>>>>         Constraint 0
>>>>>>>>           name: long_term
>>>>>>>>           power_limit_uw: 157000000
>>>>>>>>           time_window_us: 55967744
>>>>>>>>           max_power_uw: 55000000
>>>>>>>>         Constraint 1
>>>>>>>>           name: short_term
>>>>>>>>           power_limit_uw: 157000000
>>>>>>>>           time_window_us: 2440
>>>>>>>>           max_power_uw: 0
>>>>>>>>         Constraint 2
>>>>>>>>           name: peak_power
>>>>>>>>           power_limit_uw: 200000000
>>>>>>>>           max_power_uw: 0
>>>>>>>>         Zone 0:0
>>>>>>>>           name: core
>>>>>>>>           enabled: 0
>>>>>>>>           max_energy_range_uj: 262143328850
>>>>>>>>           Constraint 0
>>>>>>>>             name: long_term
>>>>>>>>             power_limit_uw: 0
>>>>>>>>             time_window_us: 976
>>>>>>>>         Zone 0:1
>>>>>>>>           name: uncore
>>>>>>>>           enabled: 0
>>>>>>>>           max_energy_range_uj: 262143328850
>>>>>>>>           Constraint 0
>>>>>>>>             name: long_term
>>>>>>>>             power_limit_uw: 0
>>>>>>>>             time_window_us: 976
>>>>>>>>       Zone 1
>>>>>>>>         name: psys
>>>>>>>>         enabled: 0
>>>>>>>>         max_energy_range_uj: 262143328850
>>>>>>>>         Constraint 0
>>>>>>>>           name: long_term
>>>>>>>>           power_limit_uw: 0
>>>>>>>>           time_window_us: 27983872
>>>>>>>>         Constraint 1
>>>>>>>>           name: short_term
>>>>>>>>           power_limit_uw: 0
>>>>>>>>           time_window_us: 976
>>>>>>>>
>>>>>>>>
>>>>>>>> as seen by the output of the command, the intel-rapl-mmio
>>>>>>>> is
>>>>>>>> causing the
>>>>>>>> throttling as it sets power_limit_uw to 30 watts
>>>>>>>> (readonly). so
>>>>>>>> the current fix
>>>>>>>> that i'm currently using is disabling the intel-rapl-mmio
>>>>>>>> leaving only
>>>>>>>> the intel-rapl which sets power_limit_uw to 157watts using
>>>>>>>> this
>>>>>>>> command: powercap-set -p intel-rapl-mmio -z 0 -e 0
>>>>>>>>
>>>>>>>> this will lead to the laptop being able to reach it's
>>>>>>>> maximum
>>>>>>>> power
>>>>>>>> limit.
>>>>>>>>
>>>>>>>> after doing this, when i change the platform profile
>>>>>>>> through
>>>>>>>> sysfs the
>>>>>>>> laptop will start behaving as described in the table above
>>>>>>>> exactly like
>>>>>>>> windows.
>>>>>>>>
>>>>>>>> in conclusion, the asus-wmi driver already has the platform
>>>>>>>> profiles
>>>>>>>> (a.k.a fan profiles)
>>>>>>>> implemented and I think that the power throttling is caused
>>>>>>>> by
>>>>>>>> either
>>>>>>>> intel Power Capping Framework or asus bios.
>>>>>>> Or the Intel Thermal Daemon somehow does not properly support
>>>>>>> intel-rapl-mmio
>>>>>>> or is not installed.
>>>>>> This was exactly it. the Intel Thermal Daemon wasn't installed.
>>>>>> now
>>>>>> everything is working as expected!
>>>>>>
>>>>>> Best regards,
>>>>>> Mohamed G.
>>>>> Interesting.
>>>>>
>>>>> Srinivas, can you verify that the Intel Thermal Daemon is
>>>>> installed
>>>>> on the affected
>>>>> Asus machines?
>>>>>
>>>>> I begin to wonder why this thermal daemon is a userspace
>>>>> component,
>>>>> stuff like thermal
>>>>> management should use the thermal subsystem inside the kernel.
>>>> Thanks for detailed analysis here.
>>>>
>>>> Here the problem is not thermal daemon or INT340x (I am author of
>>>> both).
>>>>
>>>> The ODVP variable is input into thermal tables. These thermal
>>>> tables
>>>> are defined by Asus via DTT tables. This results in matching
>>>> certain
>>>> max and min power limits and also various temperature limits.
>>>>
>>>> By default the laptop in question will boot with max limit of 17W,
>>>> which is limit for whisper mode match based on ODVP variables.
>>>> There is
>>>> a SEN1 limit of 50C, once the limit reaches to 50C, you need to
>>>> throttle upto 12W as per thermal table.
>>>>
>>>> If you stop thermald, yes, you will stay in 17W, so you will not
>>>> see
>>>> throttle but your SEN1 (seems skin limit) limit will be violated.
>>>> Also if you remove the rapl_mmio driver, that will also work as no
>>>> means to set power limits.
>>>>
>>>> Windows will do exactly same. Meeting thermal limit is a
>>>> requirement.
>>>>
>>>> But on Windows this ODVP variable will be set to 0 to match
>>>> standard
>>>> mode. This will result in matching rules which will set the max
>>>> power
>>>> to 22W and min to 17W also increase thermal limit to 55C. So
>>>> essentially lost 5W of performance.
>>>>
>>>> Here WMI method as you correctly found out matching VIVO thermal
>>>> policy. But it will not set ODVP variable unless you call a WMI
>>>> method
>>>> to set the mode via DEVS() on the same device ID. So although
>>>> platform
>>>> power policy will say "balanced" it is actually "Whisper" for
>>>> thermal
>>>> policy. On Windows when system boots the Asus service will set to
>>>> standard and will set the ODVP variable to 0 and will match the
>>>> correct
>>>> table.
>>>>
>>>> After Luke's help, I can do a work around from user space to change
>>>> the
>>>> power policy to any other policy than balanced and then again set
>>>> to
>>>> balance. This will result in setting the policy to standard via
>>>> DEVS()
>>>> and also set the correct ODVP variable.
>>>>
>>>> This driver on unload change the vivo thermal policy to default.
>>>> But
>>>> doesn't change that to default on load time to match the default
>>>> platform power policy. So rmmod and modprobe of driver should also
>>>> fix.
> Thank you Srinivas for the insights!
>
>>>> Thanks,
>>>> Srinivas
>>>>
>>> Good point, so basically throttle_thermal_policy_set_default() need
>>> to be called during
>>> initialization of the thermal profile. Maybe you can send another
>>> patch which implements this?
>> I have already tested this change. But this seems a regression, so want
>> to confirm first as it was intentional. The following commit removed
>> the call. If it was unintentional, Mohamed can try to submit a change.
>>
>>
>> commit bcbfcebda2cbc6a10a347d726e4a4f69e43a864e
>> Author: Mohamed Ghanmi <mohamed.ghanmi@supcom.tn>
>> Date:   Sun Jun 9 15:48:49 2024 +0100
>>
>> Thanks,
>> Srinivas
> This was definitely not intentional. I'll write a patch asap
> I also want your opinion on adding naming changes to the commit to
> future proof the patch as it has been proven that it implements platform
> profiles for various modern laptops other than the vivobooks and to
> avoid any future confusion about the use of the patch
>
> Best Regards,
> Mohamed G.

I already prepared two patches containing fixes for the asus-wmi driver. If you want
i can send the necessary patch.

Regarding the name change: i am fine with a rename of the constants. But please wait till
i send my patch series, since otherwise there is going to be a merge conflict.

Thanks,
Armin Wolf

>>
>>
>>> Thanks,
>>> Armin Wolf
>>>
>>>>> Thanks,
>>>>> Armin Wolf
>>>>>
Mohamed Ghanmi Oct. 25, 2024, 6:40 p.m. UTC | #17
Hello !

On Fri, Oct 25, 2024 at 08:33:06PM +0200, Armin Wolf wrote:
> Am 25.10.24 um 15:30 schrieb Mohamed Ghanmi:
> 
> > On Thu, Oct 24, 2024 at 11:15:31AM -0700, srinivas pandruvada wrote:
> > > On Wed, 2024-10-23 at 22:32 +0200, Armin Wolf wrote:
> > > > Am 23.10.24 um 22:15 schrieb srinivas pandruvada:
> > > > 
> > > > > On Wed, 2024-10-23 at 20:57 +0200, Armin Wolf wrote:
> > > > > > Am 23.10.24 um 19:59 schrieb Mohamed Ghanmi:
> > > > > > 
> > > > > > > On Wed, Oct 23, 2024 at 06:31:17PM +0200, Armin Wolf wrote:
> > > > > > > > Am 23.10.24 um 16:44 schrieb Mohamed Ghanmi:
> > > > > > > > 
> > > > > > > > > Hello !
> > > > > > > > > On Sun, Oct 20, 2024 at 09:42:45PM +0200, Armin Wolf wrote:
> > > > > > > > > > Am 20.10.24 um 21:05 schrieb Armin Wolf:
> > > > > > > > > > 
> > > > > > > > > > > Am 20.10.24 um 08:50 schrieb Srinivas Pandruvada:
> > > > > > > > > > > 
> > > > > > > > > > > > Some recent Asus laptops are supporting ASUS
> > > > > > > > > > > > Intelligent
> > > > > > > > > > > > Performance
> > > > > > > > > > > > Technology (AIPT). This solution allows users to have
> > > > > > > > > > > > maximized CPU
> > > > > > > > > > > > performance in models with a chassis providing more
> > > > > > > > > > > > thermal head room.
> > > > > > > > > > > > Refer to [1].
> > > > > > > > > > > > 
> > > > > > > > > > > > There are major performance issues when Linux is
> > > > > > > > > > > > installed on these
> > > > > > > > > > > > laptops compared to Windows install. One such report
> > > > > > > > > > > > is
> > > > > > > > > > > > published for
> > > > > > > > > > > > Graphics benchmarks on Asus ASUS Zenbook S 14 with
> > > > > > > > > > > > Lunar
> > > > > > > > > > > > Lake
> > > > > > > > > > > > processors [2].
> > > > > > > > > > > > 
> > > > > > > > > > > > By default, these laptops are booting in "Whisper
> > > > > > > > > > > > Mode"
> > > > > > > > > > > > till OS power
> > > > > > > > > > > > management or tools change this to other AIPT mode.
> > > > > > > > > > > > This
> > > > > > > > > > > > "Whisper" mode
> > > > > > > > > > > > calls to set lower maximum and minimum RAPL (Running
> > > > > > > > > > > > Average Power
> > > > > > > > > > > > Limit)
> > > > > > > > > > > > via thermal tables. On Linux this leads to lower
> > > > > > > > > > > > performance even when
> > > > > > > > > > > > platform power profile is "balanced". This "Whisper"
> > > > > > > > > > > > mode
> > > > > > > > > > > > should
> > > > > > > > > > > > correspond to "quiet" mode.
> > > > > > > > > > > > 
> > > > > > > > > > > > So, when AIPT is present change the default mode to
> > > > > > > > > > > > "Standard" during
> > > > > > > > > > > > boot. Map the three platform power profile modes as
> > > > > > > > > > > > follows:
> > > > > > > > > > > > 
> > > > > > > > > > > > Power Profile Mode      AIPT mode
> > > > > > > > > > > > -----------------------------------
> > > > > > > > > > > > quiet            Whisper
> > > > > > > > > > > > balanced        Standard
> > > > > > > > > > > > performance        Performance
> > > > > > > > > > > > ------------------------------------
> > > > > > > > > > > > 
> > > > > > > > > > > > Here AIPT mode can be detected by checking presese of
> > > > > > > > > > > > "FANL" method
> > > > > > > > > > > > under
> > > > > > > > > > > > PNP HID "PNP0C14" and UID "ATK". If AIPT mode is
> > > > > > > > > > > > present,
> > > > > > > > > > > > this takes
> > > > > > > > > > > > precedence over the existing VIVO thermal policy.
> > > > > > > > > > > > These
> > > > > > > > > > > > modes are set
> > > > > > > > > > > > using "FANL" method.
> > > > > > > > > > > > 
> > > > > > > > > > > > Although this “FANL” method is not used in the Asus
> > > > > > > > > > > > WMI
> > > > > > > > > > > > driver, users
> > > > > > > > > > > > have used this method from user space [3] to set AIPT
> > > > > > > > > > > > modes. Used this
> > > > > > > > > > > > as a reference.
> > > > > > > > > > > > 
> > > > > > > > > > > > Link:
> > > > > > > > > > > > https://www.asus.com/content/laptop-asus-intelligent-performance-technology-aipt/
> > > > > > > > > > > > # [1]
> > > > > > > > > > > > Reported-by: Michael Larabel <Michael@phoronix.com>
> > > > > > > > > > > > Closes:
> > > > > > > > > > > > https://www.phoronix.com/review/lunar-lake-xe2/5 #
> > > > > > > > > > > > [2]
> > > > > > > > > > > > Link:
> > > > > > > > > > > > https://github.com/dominiksalvet/asus-fan-control/issues/151
> > > > > > > > > > > >    # [3]
> > > > > > > > > > > > Tested-by: Casey Bowman <casey.g.bowman@intel.com>
> > > > > > > > > > > > Signed-off-by: Srinivas Pandruvada
> > > > > > > > > > > > <srinivas.pandruvada@linux.intel.com>
> > > > > > > > > > > > ---
> > > > > > > > > > > >       drivers/platform/x86/asus-wmi.c | 93
> > > > > > > > > > > > +++++++++++++++++++++++++++++++--
> > > > > > > > > > > >       1 file changed, 89 insertions(+), 4 deletions(-)
> > > > > > > > > > > > 
> > > > > > > > > > > > diff --git a/drivers/platform/x86/asus-wmi.c
> > > > > > > > > > > > b/drivers/platform/x86/asus-wmi.c
> > > > > > > > > > > > index 7a48220b4f5a..06689d0f98c7 100644
> > > > > > > > > > > > --- a/drivers/platform/x86/asus-wmi.c
> > > > > > > > > > > > +++ b/drivers/platform/x86/asus-wmi.c
> > > > > > > > > > > > @@ -100,6 +100,11 @@ module_param(fnlock_default,
> > > > > > > > > > > > bool,
> > > > > > > > > > > > 0444);
> > > > > > > > > > > >       #define
> > > > > > > > > > > > ASUS_THROTTLE_THERMAL_POLICY_SILENT_VIVO    1
> > > > > > > > > > > >       #define
> > > > > > > > > > > > ASUS_THROTTLE_THERMAL_POLICY_OVERBOOST_VIVO    2
> > > > > > > > > > > > 
> > > > > > > > > > > > +#define AIPT_STANDARD                0
> > > > > > > > > > > > +#define AIPT_WHISPER                1
> > > > > > > > > > > > +#define AIPT_PERFORMANCE            2
> > > > > > > > > > > > +#define AIPT_FULL_SPEED                3
> > > > > > > > > > > > +
> > > > > > > > > > > >       #define PLATFORM_PROFILE_MAX 2
> > > > > > > > > > > > 
> > > > > > > > > > > >       #define USB_INTEL_XUSB2PR        0xD0
> > > > > > > > > > > > @@ -333,6 +338,9 @@ struct asus_wmi {
> > > > > > > > > > > >           struct asus_wmi_debug debug;
> > > > > > > > > > > > 
> > > > > > > > > > > >           struct asus_wmi_driver *driver;
> > > > > > > > > > > > +    acpi_handle acpi_mgmt_handle;
> > > > > > > > > > > > +    int asus_aipt_mode;
> > > > > > > > > > > > +    bool asus_aipt_present;
> > > > > > > > > > > >       };
> > > > > > > > > > > > 
> > > > > > > > > > > >       /* WMI
> > > > > > > > > > > > *****************************************************
> > > > > > > > > > > > ****
> > > > > > > > > > > > ***************/
> > > > > > > > > > > > @@ -3804,6 +3812,19 @@ static ssize_t
> > > > > > > > > > > > throttle_thermal_policy_store(struct device *dev,
> > > > > > > > > > > >       static DEVICE_ATTR_RW(throttle_thermal_policy);
> > > > > > > > > > > > 
> > > > > > > > > > > >       /* Platform profile
> > > > > > > > > > > > *****************************************************
> > > > > > > > > > > > ****
> > > > > > > > > > > > **/
> > > > > > > > > > > > +static int asus_wmi_write_aipt_mode(struct asus_wmi
> > > > > > > > > > > > *asus, int
> > > > > > > > > > > > aipt_mode)
> > > > > > > > > > > > +{
> > > > > > > > > > > > +    int status;
> > > > > > > > > > > > +
> > > > > > > > > > > > +    status = acpi_execute_simple_method(asus-
> > > > > > > > > > > > > acpi_mgmt_handle,
> > > > > > > > > > > > "FANL", aipt_mode);
> > > > > > > > > > > > +    if (ACPI_FAILURE(status)) {
> > > > > > > > > > > > +        acpi_handle_info(asus->acpi_mgmt_handle,
> > > > > > > > > > > > "FANL
> > > > > > > > > > > > execute
> > > > > > > > > > > > failed\n");
> > > > > > > > > > > > +        return -EIO;
> > > > > > > > > > > > +    }
> > > > > > > > > > > > +
> > > > > > > > > > > > +    return 0;
> > > > > > > > > > > > +}
> > > > > > > > > > > > +
> > > > > > > > > > > >       static int
> > > > > > > > > > > > asus_wmi_platform_profile_to_vivo(struct
> > > > > > > > > > > > asus_wmi *asus,
> > > > > > > > > > > > int mode)
> > > > > > > > > > > >       {
> > > > > > > > > > > >           bool vivo;
> > > > > > > > > > > > @@ -3844,6 +3865,26 @@ static int
> > > > > > > > > > > > asus_wmi_platform_profile_mode_from_vivo(struct
> > > > > > > > > > > > asus_wmi
> > > > > > > > > > > > *asus, int m
> > > > > > > > > > > >           return mode;
> > > > > > > > > > > >       }
> > > > > > > > > > > > 
> > > > > > > > > > > > +static int asus_wmi_aipt_platform_profile_get(struct
> > > > > > > > > > > > asus_wmi *asus,
> > > > > > > > > > > > +                          enum
> > > > > > > > > > > > platform_profile_option
> > > > > > > > > > > > *profile)
> > > > > > > > > > > > +{
> > > > > > > > > > > > +    switch (asus->asus_aipt_mode) {
> > > > > > > > > > > > +    case AIPT_STANDARD:
> > > > > > > > > > > > +        *profile = PLATFORM_PROFILE_BALANCED;
> > > > > > > > > > > > +        break;
> > > > > > > > > > > > +    case AIPT_PERFORMANCE:
> > > > > > > > > > > > +        *profile = PLATFORM_PROFILE_PERFORMANCE;
> > > > > > > > > > > > +        break;
> > > > > > > > > > > > +    case AIPT_WHISPER:
> > > > > > > > > > > > +        *profile = PLATFORM_PROFILE_QUIET;
> > > > > > > > > > > > +        break;
> > > > > > > > > > > > +    default:
> > > > > > > > > > > > +        return -EINVAL;
> > > > > > > > > > > > +    }
> > > > > > > > > > > > +
> > > > > > > > > > > > +    return 0;
> > > > > > > > > > > > +}
> > > > > > > > > > > > +
> > > > > > > > > > > >       static int asus_wmi_platform_profile_get(struct
> > > > > > > > > > > > platform_profile_handler *pprof,
> > > > > > > > > > > >                           enum platform_profile_option
> > > > > > > > > > > > *profile)
> > > > > > > > > > > >       {
> > > > > > > > > > > > @@ -3851,6 +3892,10 @@ static int
> > > > > > > > > > > > asus_wmi_platform_profile_get(struct
> > > > > > > > > > > > platform_profile_handler *pprof,
> > > > > > > > > > > >           int tp;
> > > > > > > > > > > > 
> > > > > > > > > > > >           asus = container_of(pprof, struct asus_wmi,
> > > > > > > > > > > > platform_profile_handler);
> > > > > > > > > > > > +
> > > > > > > > > > > > +    if (asus->asus_aipt_present)
> > > > > > > > > > > > +        return
> > > > > > > > > > > > asus_wmi_aipt_platform_profile_get(asus,
> > > > > > > > > > > > profile);
> > > > > > > > > > > > +
> > > > > > > > > > > >           tp = asus->throttle_thermal_policy_mode;
> > > > > > > > > > > > 
> > > > > > > > > > > >           switch
> > > > > > > > > > > > (asus_wmi_platform_profile_mode_from_vivo(asus, tp))
> > > > > > > > > > > > {
> > > > > > > > > > > > @@ -3874,26 +3919,42 @@ static int
> > > > > > > > > > > > asus_wmi_platform_profile_set(struct
> > > > > > > > > > > > platform_profile_handler *pprof,
> > > > > > > > > > > >                           enum platform_profile_option
> > > > > > > > > > > > profile)
> > > > > > > > > > > >       {
> > > > > > > > > > > >           struct asus_wmi *asus;
> > > > > > > > > > > > -    int tp;
> > > > > > > > > > > > +    int ret = 0, tp, aipt_mode;
> > > > > > > > > > > > 
> > > > > > > > > > > >           asus = container_of(pprof, struct asus_wmi,
> > > > > > > > > > > > platform_profile_handler);
> > > > > > > > > > > > 
> > > > > > > > > > > >           switch (profile) {
> > > > > > > > > > > >           case PLATFORM_PROFILE_PERFORMANCE:
> > > > > > > > > > > >               tp =
> > > > > > > > > > > > ASUS_THROTTLE_THERMAL_POLICY_OVERBOOST;
> > > > > > > > > > > > +        aipt_mode = AIPT_PERFORMANCE;
> > > > > > > > > > > >               break;
> > > > > > > > > > > >           case PLATFORM_PROFILE_BALANCED:
> > > > > > > > > > > >               tp =
> > > > > > > > > > > > ASUS_THROTTLE_THERMAL_POLICY_DEFAULT;
> > > > > > > > > > > > +        aipt_mode = AIPT_STANDARD;
> > > > > > > > > > > >               break;
> > > > > > > > > > > >           case PLATFORM_PROFILE_QUIET:
> > > > > > > > > > > >               tp =
> > > > > > > > > > > > ASUS_THROTTLE_THERMAL_POLICY_SILENT;
> > > > > > > > > > > > +        aipt_mode = AIPT_WHISPER;
> > > > > > > > > > > >               break;
> > > > > > > > > > > >           default:
> > > > > > > > > > > >               return -EOPNOTSUPP;
> > > > > > > > > > > >           }
> > > > > > > > > > > > 
> > > > > > > > > > > > -    asus->throttle_thermal_policy_mode =
> > > > > > > > > > > > asus_wmi_platform_profile_to_vivo(asus, tp);
> > > > > > > > > > > > -    return throttle_thermal_policy_write(asus);
> > > > > > > > > > > > +    if (asus->asus_aipt_present) {
> > > > > > > > > > > > +        ret = asus_wmi_write_aipt_mode(asus,
> > > > > > > > > > > > aipt_mode);
> > > > > > > > > > > > +        if (!ret) {
> > > > > > > > > > > > +            asus->asus_aipt_mode = aipt_mode;
> > > > > > > > > > > > +            goto skip_vivo;
> > > > > > > > > > > > +        }
> > > > > > > > > > > > +    }
> > > > > > > > > > > > +
> > > > > > > > > > > > +    if (asus->throttle_thermal_policy_dev) {
> > > > > > > > > > > > +        asus->throttle_thermal_policy_mode =
> > > > > > > > > > > > asus_wmi_platform_profile_to_vivo(asus, tp);
> > > > > > > > > > > > +        ret = throttle_thermal_policy_write(asus);
> > > > > > > > > > > > +    }
> > > > > > > > > > > > +
> > > > > > > > > > > > +skip_vivo:
> > > > > > > > > > > > +    return ret;
> > > > > > > > > > > >       }
> > > > > > > > > > > > 
> > > > > > > > > > > >       static int platform_profile_setup(struct
> > > > > > > > > > > > asus_wmi
> > > > > > > > > > > > *asus)
> > > > > > > > > > > > @@ -3905,7 +3966,7 @@ static int
> > > > > > > > > > > > platform_profile_setup(struct
> > > > > > > > > > > > asus_wmi *asus)
> > > > > > > > > > > >            * Not an error if a component
> > > > > > > > > > > > platform_profile
> > > > > > > > > > > > relies on is
> > > > > > > > > > > > unavailable
> > > > > > > > > > > >            * so early return, skipping the setup of
> > > > > > > > > > > > platform_profile.
> > > > > > > > > > > >            */
> > > > > > > > > > > > -    if (!asus->throttle_thermal_policy_dev)
> > > > > > > > > > > > +    if (!asus->throttle_thermal_policy_dev && !asus-
> > > > > > > > > > > > > asus_aipt_present)
> > > > > > > > > > > >               return 0;
> > > > > > > > > > > > 
> > > > > > > > > > > >           dev_info(dev, "Using throttle_thermal_policy
> > > > > > > > > > > > for
> > > > > > > > > > > > platform_profile support\n");
> > > > > > > > > > > > @@ -4538,6 +4599,7 @@ static int
> > > > > > > > > > > > asus_wmi_sysfs_init(struct
> > > > > > > > > > > > platform_device *device)
> > > > > > > > > > > >       static int asus_wmi_platform_init(struct
> > > > > > > > > > > > asus_wmi
> > > > > > > > > > > > *asus)
> > > > > > > > > > > >       {
> > > > > > > > > > > >           struct device *dev = &asus->platform_device-
> > > > > > > > > > > > > dev;
> > > > > > > > > > > > +    struct acpi_device *adev;
> > > > > > > > > > > >           char *wmi_uid;
> > > > > > > > > > > >           int rv;
> > > > > > > > > > > > 
> > > > > > > > > > > > @@ -4593,6 +4655,29 @@ static int
> > > > > > > > > > > > asus_wmi_platform_init(struct
> > > > > > > > > > > > asus_wmi *asus)
> > > > > > > > > > > > 
> > > > > > > > > > > > asus_wmi_set_devstate(ASUS_WMI_DEVID_CWAP,
> > > > > > > > > > > >                             asus->driver->quirks-
> > > > > > > > > > > > > wapf,
> > > > > > > > > > > > NULL);
> > > > > > > > > > > > 
> > > > > > > > > > > > +    /*
> > > > > > > > > > > > +     * Check presence of Intelligent Performance
> > > > > > > > > > > > Technology (AIPT).
> > > > > > > > > > > > +     * If present store acpi handle and set
> > > > > > > > > > > > asus_aipt_present to true.
> > > > > > > > > > > > +     */
> > > > > > > > > > > > +    adev = acpi_dev_get_first_match_dev("PNP0C14",
> > > > > > > > > > > > "ATK", -1);
> > > > > > > > > > > Is there really no way of changing the AIPT mode
> > > > > > > > > > > through
> > > > > > > > > > > the WMI
> > > > > > > > > > > interface?
> > > > > > > > > > > I would prefer using the WMI interface if available,
> > > > > > > > > > > since
> > > > > > > > > > > the
> > > > > > > > > > > firmware might
> > > > > > > > > > > assume that FANL is only called through the WMI
> > > > > > > > > > > interface.
> > > > > > > > > > > 
> > > > > > > > > > > Do you have a acpidump from a affected device?
> > > > > > > > > > > 
> > > > > > > > > > > Thanks,
> > > > > > > > > > > Armin Wolf
> > > > > > > > > > > 
> > > > > > > > > > I found a acpidump from a ASUS device with a matching
> > > > > > > > > > FANL
> > > > > > > > > > method. It seems that this method
> > > > > > > > > > can indeed be called using the WMI interface using the
> > > > > > > > > > DEVS()
> > > > > > > > > > WMI method:
> > > > > > > > > > 
> > > > > > > > > > [WmiMethodId(1398162756), Implemented] void DEVS([in]
> > > > > > > > > > uint32
> > > > > > > > > > Device_ID, [in] uint32 Control_status, [out] uint32
> > > > > > > > > > result);
> > > > > > > > > > 
> > > > > > > > > > If Device_ID is 0x00110019, then Control_status is passed
> > > > > > > > > > to
> > > > > > > > > > the FANL ACPI method.
> > > > > > > > > > 
> > > > > > > > > > It also seems that support for AIPT can be queried using
> > > > > > > > > > the
> > > > > > > > > > DSTS() WMI method:
> > > > > > > > > > 
> > > > > > > > > > [WmiMethodId(1398035268), Implemented] void DSTS([in]
> > > > > > > > > > uint32
> > > > > > > > > > Device_ID, [out] uint32 device_status);
> > > > > > > > > > 
> > > > > > > > > > Using Device_ID 0x00110019, the returned device status
> > > > > > > > > > seems
> > > > > > > > > > to contain the following information:
> > > > > > > > > > 
> > > > > > > > > > - 16-bit current AIPT mode
> > > > > > > > > > - 4-bit unknown value (possible values 2, 3 and 7, maybe
> > > > > > > > > > number of supported modes or some kind of bitmap?)
> > > > > > > > > > - 1-bit with is set when (GGIV (0x0907000C) == One) is
> > > > > > > > > > true
> > > > > > > > > I just saw this conversation and i think that the behaviour
> > > > > > > > > this
> > > > > > > > > patch will implement in the driver was already implemented
> > > > > > > > > in
> > > > > > > > > this patch
> > > > > > > > > that got added to kernel v6.12-rc3:
> > > > > > > > > https://lore.kernel.org/platform-driver-x86/20240609144849.2532-2-mohamed.ghanmi@supcom.tn/
> > > > > > > > > 
> > > > > > > > > this patch introduced
> > > > > > > > > ASUS_WMI_DEVID_THROTTLE_THERMAL_POLICY_VIVO
> > > > > > > > > 0x00110019 which is the device_id that changes the fan
> > > > > > > > > profiles. the
> > > > > > > > > naming is not clear because it was initially intended to
> > > > > > > > > add
> > > > > > > > > support for
> > > > > > > > > fan profiles for vivobook laptops but it ended up adding
> > > > > > > > > support
> > > > > > > > > for a lot of modern laptops.
> > > > > > > > Nice, you are absolutely right.
> > > > > > > > 
> > > > > > > > So this patch series is effectively already upstream, very
> > > > > > > > good.
> > > > > > > > I did some research and found out
> > > > > > > > that the status of this device id contains the following
> > > > > > > > data:
> > > > > > > > 
> > > > > > > > Status          Supported Modes
> > > > > > > > -------------------------------
> > > > > > > > 0x00[1]300[xx]  0 1 2
> > > > > > > > 0x000700[xx]    0 1 2
> > > > > > > > 0x000200[xx]    ??? (ODV0)
> > > > > > > > 0x000700[xx]    0 1 2
> > > > > > > > 0x0a0700[xx]    ??? (ODV0)
> > > > > > > > 
> > > > > > > > While i have no clue about the meaning of the remaining bits,
> > > > > > > > i
> > > > > > > > can report that the first 8 Bits
> > > > > > > > contain the current thermal mode. Maybe adding support for
> > > > > > > > this
> > > > > > > > would be nice, so the current
> > > > > > > > thermal mode can be read directly from the hardware.
> > > > > > > > 
> > > > > > > > I also found out that on some models the thermal mode
> > > > > > > > actually
> > > > > > > > modifies the ODV0 variable which
> > > > > > > > is consumed by int3400_thermal and exposed to the Intel
> > > > > > > > Thermal
> > > > > > > > Daemon. So maybe the lackluster
> > > > > > > > performance also has something to do with it.
> > > > > > > > 
> > > > > > > > > a point that Srinivas Pandruvada mentioned about RAPL
> > > > > > > > > (Running
> > > > > > > > > Average Power Limit)
> > > > > > > > > is valid for a lot of modern vivobook and zenbook laptops
> > > > > > > > > but i
> > > > > > > > > think
> > > > > > > > > it's unrelated to fan profiles.
> > > > > > > > > 
> > > > > > > > > a lot of asus laptops that have intel cpus suffer from
> > > > > > > > > power
> > > > > > > > > throttling.
> > > > > > > > > for exemple in my case using windows, changing fan profiles
> > > > > > > > > will lead to max power
> > > > > > > > > changing to the values indicated in the table below (asus
> > > > > > > > > vivobook 16x
> > > > > > > > > pro k6604) which leads to higher performance than linux
> > > > > > > > > 
> > > > > > > > > fan Profile             power limit
> > > > > > > > > -----------------------------------
> > > > > > > > > Whisper                 50watts
> > > > > > > > > Standard                120watts
> > > > > > > > > Performance             149watts
> > > > > > > > > ------------------------------------
> > > > > > > > > 
> > > > > > > > > However in linux, even after changing to the appropriate
> > > > > > > > > fan
> > > > > > > > > profile,
> > > > > > > > > the power is still capped at 50watts and i found the reason
> > > > > > > > > why
> > > > > > > > > 
> > > > > > > > > here is the results of using the powercap-info command:
> > > > > > > > > 
> > > > > > > > > intel-rapl-mmio
> > > > > > > > >       enabled: 1
> > > > > > > > >       Zone 0
> > > > > > > > >         name: package-0
> > > > > > > > >         enabled: 1
> > > > > > > > >         max_energy_range_uj: 262143328850
> > > > > > > > >         Constraint 0
> > > > > > > > >           name: long_term
> > > > > > > > >           power_limit_uw: 30000000
> > > > > > > > >           time_window_us: 55967744
> > > > > > > > >           max_power_uw: 55000000
> > > > > > > > >         Constraint 1
> > > > > > > > >           name: short_term
> > > > > > > > >           power_limit_uw: 55000000
> > > > > > > > >           time_window_us: 2440
> > > > > > > > >           max_power_uw: 0
> > > > > > > > > intel-rapl
> > > > > > > > >       enabled: 1
> > > > > > > > >       Zone 0
> > > > > > > > >         name: package-0
> > > > > > > > >         enabled: 1
> > > > > > > > >         max_energy_range_uj: 262143328850
> > > > > > > > >         Constraint 0
> > > > > > > > >           name: long_term
> > > > > > > > >           power_limit_uw: 157000000
> > > > > > > > >           time_window_us: 55967744
> > > > > > > > >           max_power_uw: 55000000
> > > > > > > > >         Constraint 1
> > > > > > > > >           name: short_term
> > > > > > > > >           power_limit_uw: 157000000
> > > > > > > > >           time_window_us: 2440
> > > > > > > > >           max_power_uw: 0
> > > > > > > > >         Constraint 2
> > > > > > > > >           name: peak_power
> > > > > > > > >           power_limit_uw: 200000000
> > > > > > > > >           max_power_uw: 0
> > > > > > > > >         Zone 0:0
> > > > > > > > >           name: core
> > > > > > > > >           enabled: 0
> > > > > > > > >           max_energy_range_uj: 262143328850
> > > > > > > > >           Constraint 0
> > > > > > > > >             name: long_term
> > > > > > > > >             power_limit_uw: 0
> > > > > > > > >             time_window_us: 976
> > > > > > > > >         Zone 0:1
> > > > > > > > >           name: uncore
> > > > > > > > >           enabled: 0
> > > > > > > > >           max_energy_range_uj: 262143328850
> > > > > > > > >           Constraint 0
> > > > > > > > >             name: long_term
> > > > > > > > >             power_limit_uw: 0
> > > > > > > > >             time_window_us: 976
> > > > > > > > >       Zone 1
> > > > > > > > >         name: psys
> > > > > > > > >         enabled: 0
> > > > > > > > >         max_energy_range_uj: 262143328850
> > > > > > > > >         Constraint 0
> > > > > > > > >           name: long_term
> > > > > > > > >           power_limit_uw: 0
> > > > > > > > >           time_window_us: 27983872
> > > > > > > > >         Constraint 1
> > > > > > > > >           name: short_term
> > > > > > > > >           power_limit_uw: 0
> > > > > > > > >           time_window_us: 976
> > > > > > > > > 
> > > > > > > > > 
> > > > > > > > > as seen by the output of the command, the intel-rapl-mmio
> > > > > > > > > is
> > > > > > > > > causing the
> > > > > > > > > throttling as it sets power_limit_uw to 30 watts
> > > > > > > > > (readonly). so
> > > > > > > > > the current fix
> > > > > > > > > that i'm currently using is disabling the intel-rapl-mmio
> > > > > > > > > leaving only
> > > > > > > > > the intel-rapl which sets power_limit_uw to 157watts using
> > > > > > > > > this
> > > > > > > > > command: powercap-set -p intel-rapl-mmio -z 0 -e 0
> > > > > > > > > 
> > > > > > > > > this will lead to the laptop being able to reach it's
> > > > > > > > > maximum
> > > > > > > > > power
> > > > > > > > > limit.
> > > > > > > > > 
> > > > > > > > > after doing this, when i change the platform profile
> > > > > > > > > through
> > > > > > > > > sysfs the
> > > > > > > > > laptop will start behaving as described in the table above
> > > > > > > > > exactly like
> > > > > > > > > windows.
> > > > > > > > > 
> > > > > > > > > in conclusion, the asus-wmi driver already has the platform
> > > > > > > > > profiles
> > > > > > > > > (a.k.a fan profiles)
> > > > > > > > > implemented and I think that the power throttling is caused
> > > > > > > > > by
> > > > > > > > > either
> > > > > > > > > intel Power Capping Framework or asus bios.
> > > > > > > > Or the Intel Thermal Daemon somehow does not properly support
> > > > > > > > intel-rapl-mmio
> > > > > > > > or is not installed.
> > > > > > > This was exactly it. the Intel Thermal Daemon wasn't installed.
> > > > > > > now
> > > > > > > everything is working as expected!
> > > > > > > 
> > > > > > > Best regards,
> > > > > > > Mohamed G.
> > > > > > Interesting.
> > > > > > 
> > > > > > Srinivas, can you verify that the Intel Thermal Daemon is
> > > > > > installed
> > > > > > on the affected
> > > > > > Asus machines?
> > > > > > 
> > > > > > I begin to wonder why this thermal daemon is a userspace
> > > > > > component,
> > > > > > stuff like thermal
> > > > > > management should use the thermal subsystem inside the kernel.
> > > > > Thanks for detailed analysis here.
> > > > > 
> > > > > Here the problem is not thermal daemon or INT340x (I am author of
> > > > > both).
> > > > > 
> > > > > The ODVP variable is input into thermal tables. These thermal
> > > > > tables
> > > > > are defined by Asus via DTT tables. This results in matching
> > > > > certain
> > > > > max and min power limits and also various temperature limits.
> > > > > 
> > > > > By default the laptop in question will boot with max limit of 17W,
> > > > > which is limit for whisper mode match based on ODVP variables.
> > > > > There is
> > > > > a SEN1 limit of 50C, once the limit reaches to 50C, you need to
> > > > > throttle upto 12W as per thermal table.
> > > > > 
> > > > > If you stop thermald, yes, you will stay in 17W, so you will not
> > > > > see
> > > > > throttle but your SEN1 (seems skin limit) limit will be violated.
> > > > > Also if you remove the rapl_mmio driver, that will also work as no
> > > > > means to set power limits.
> > > > > 
> > > > > Windows will do exactly same. Meeting thermal limit is a
> > > > > requirement.
> > > > > 
> > > > > But on Windows this ODVP variable will be set to 0 to match
> > > > > standard
> > > > > mode. This will result in matching rules which will set the max
> > > > > power
> > > > > to 22W and min to 17W also increase thermal limit to 55C. So
> > > > > essentially lost 5W of performance.
> > > > > 
> > > > > Here WMI method as you correctly found out matching VIVO thermal
> > > > > policy. But it will not set ODVP variable unless you call a WMI
> > > > > method
> > > > > to set the mode via DEVS() on the same device ID. So although
> > > > > platform
> > > > > power policy will say "balanced" it is actually "Whisper" for
> > > > > thermal
> > > > > policy. On Windows when system boots the Asus service will set to
> > > > > standard and will set the ODVP variable to 0 and will match the
> > > > > correct
> > > > > table.
> > > > > 
> > > > > After Luke's help, I can do a work around from user space to change
> > > > > the
> > > > > power policy to any other policy than balanced and then again set
> > > > > to
> > > > > balance. This will result in setting the policy to standard via
> > > > > DEVS()
> > > > > and also set the correct ODVP variable.
> > > > > 
> > > > > This driver on unload change the vivo thermal policy to default.
> > > > > But
> > > > > doesn't change that to default on load time to match the default
> > > > > platform power policy. So rmmod and modprobe of driver should also
> > > > > fix.
> > Thank you Srinivas for the insights!
> > 
> > > > > Thanks,
> > > > > Srinivas
> > > > > 
> > > > Good point, so basically throttle_thermal_policy_set_default() need
> > > > to be called during
> > > > initialization of the thermal profile. Maybe you can send another
> > > > patch which implements this?
> > > I have already tested this change. But this seems a regression, so want
> > > to confirm first as it was intentional. The following commit removed
> > > the call. If it was unintentional, Mohamed can try to submit a change.
> > > 
> > > 
> > > commit bcbfcebda2cbc6a10a347d726e4a4f69e43a864e
> > > Author: Mohamed Ghanmi <mohamed.ghanmi@supcom.tn>
> > > Date:   Sun Jun 9 15:48:49 2024 +0100
> > > 
> > > Thanks,
> > > Srinivas
> > This was definitely not intentional. I'll write a patch asap
> > I also want your opinion on adding naming changes to the commit to
> > future proof the patch as it has been proven that it implements platform
> > profiles for various modern laptops other than the vivobooks and to
> > avoid any future confusion about the use of the patch
> > 
> > Best Regards,
> > Mohamed G.
> 
> I already prepared two patches containing fixes for the asus-wmi driver. If you want
> i can send the necessary patch.

Amazing! yes Armin go for it

> Regarding the name change: i am fine with a rename of the constants. But please wait till
> i send my patch series, since otherwise there is going to be a merge conflict.

definitely i'll wait for your patches


Best Regards,
Mohamed G.
diff mbox series

Patch

diff --git a/drivers/platform/x86/asus-wmi.c b/drivers/platform/x86/asus-wmi.c
index 7a48220b4f5a..06689d0f98c7 100644
--- a/drivers/platform/x86/asus-wmi.c
+++ b/drivers/platform/x86/asus-wmi.c
@@ -100,6 +100,11 @@  module_param(fnlock_default, bool, 0444);
 #define ASUS_THROTTLE_THERMAL_POLICY_SILENT_VIVO	1
 #define ASUS_THROTTLE_THERMAL_POLICY_OVERBOOST_VIVO	2
 
+#define AIPT_STANDARD				0
+#define AIPT_WHISPER				1
+#define AIPT_PERFORMANCE			2
+#define AIPT_FULL_SPEED				3
+
 #define PLATFORM_PROFILE_MAX 2
 
 #define USB_INTEL_XUSB2PR		0xD0
@@ -333,6 +338,9 @@  struct asus_wmi {
 	struct asus_wmi_debug debug;
 
 	struct asus_wmi_driver *driver;
+	acpi_handle acpi_mgmt_handle;
+	int asus_aipt_mode;
+	bool asus_aipt_present;
 };
 
 /* WMI ************************************************************************/
@@ -3804,6 +3812,19 @@  static ssize_t throttle_thermal_policy_store(struct device *dev,
 static DEVICE_ATTR_RW(throttle_thermal_policy);
 
 /* Platform profile ***********************************************************/
+static int asus_wmi_write_aipt_mode(struct asus_wmi *asus, int aipt_mode)
+{
+	int status;
+
+	status = acpi_execute_simple_method(asus->acpi_mgmt_handle, "FANL", aipt_mode);
+	if (ACPI_FAILURE(status)) {
+		acpi_handle_info(asus->acpi_mgmt_handle, "FANL execute failed\n");
+		return -EIO;
+	}
+
+	return 0;
+}
+
 static int asus_wmi_platform_profile_to_vivo(struct asus_wmi *asus, int mode)
 {
 	bool vivo;
@@ -3844,6 +3865,26 @@  static int asus_wmi_platform_profile_mode_from_vivo(struct asus_wmi *asus, int m
 	return mode;
 }
 
+static int asus_wmi_aipt_platform_profile_get(struct asus_wmi *asus,
+					      enum platform_profile_option *profile)
+{
+	switch (asus->asus_aipt_mode) {
+	case AIPT_STANDARD:
+		*profile = PLATFORM_PROFILE_BALANCED;
+		break;
+	case AIPT_PERFORMANCE:
+		*profile = PLATFORM_PROFILE_PERFORMANCE;
+		break;
+	case AIPT_WHISPER:
+		*profile = PLATFORM_PROFILE_QUIET;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
 static int asus_wmi_platform_profile_get(struct platform_profile_handler *pprof,
 					enum platform_profile_option *profile)
 {
@@ -3851,6 +3892,10 @@  static int asus_wmi_platform_profile_get(struct platform_profile_handler *pprof,
 	int tp;
 
 	asus = container_of(pprof, struct asus_wmi, platform_profile_handler);
+
+	if (asus->asus_aipt_present)
+		return asus_wmi_aipt_platform_profile_get(asus, profile);
+
 	tp = asus->throttle_thermal_policy_mode;
 
 	switch (asus_wmi_platform_profile_mode_from_vivo(asus, tp)) {
@@ -3874,26 +3919,42 @@  static int asus_wmi_platform_profile_set(struct platform_profile_handler *pprof,
 					enum platform_profile_option profile)
 {
 	struct asus_wmi *asus;
-	int tp;
+	int ret = 0, tp, aipt_mode;
 
 	asus = container_of(pprof, struct asus_wmi, platform_profile_handler);
 
 	switch (profile) {
 	case PLATFORM_PROFILE_PERFORMANCE:
 		tp = ASUS_THROTTLE_THERMAL_POLICY_OVERBOOST;
+		aipt_mode = AIPT_PERFORMANCE;
 		break;
 	case PLATFORM_PROFILE_BALANCED:
 		tp = ASUS_THROTTLE_THERMAL_POLICY_DEFAULT;
+		aipt_mode = AIPT_STANDARD;
 		break;
 	case PLATFORM_PROFILE_QUIET:
 		tp = ASUS_THROTTLE_THERMAL_POLICY_SILENT;
+		aipt_mode = AIPT_WHISPER;
 		break;
 	default:
 		return -EOPNOTSUPP;
 	}
 
-	asus->throttle_thermal_policy_mode = asus_wmi_platform_profile_to_vivo(asus, tp);
-	return throttle_thermal_policy_write(asus);
+	if (asus->asus_aipt_present) {
+		ret = asus_wmi_write_aipt_mode(asus, aipt_mode);
+		if (!ret) {
+			asus->asus_aipt_mode = aipt_mode;
+			goto skip_vivo;
+		}
+	}
+
+	if (asus->throttle_thermal_policy_dev) {
+		asus->throttle_thermal_policy_mode = asus_wmi_platform_profile_to_vivo(asus, tp);
+		ret = throttle_thermal_policy_write(asus);
+	}
+
+skip_vivo:
+	return ret;
 }
 
 static int platform_profile_setup(struct asus_wmi *asus)
@@ -3905,7 +3966,7 @@  static int platform_profile_setup(struct asus_wmi *asus)
 	 * Not an error if a component platform_profile relies on is unavailable
 	 * so early return, skipping the setup of platform_profile.
 	 */
-	if (!asus->throttle_thermal_policy_dev)
+	if (!asus->throttle_thermal_policy_dev && !asus->asus_aipt_present)
 		return 0;
 
 	dev_info(dev, "Using throttle_thermal_policy for platform_profile support\n");
@@ -4538,6 +4599,7 @@  static int asus_wmi_sysfs_init(struct platform_device *device)
 static int asus_wmi_platform_init(struct asus_wmi *asus)
 {
 	struct device *dev = &asus->platform_device->dev;
+	struct acpi_device *adev;
 	char *wmi_uid;
 	int rv;
 
@@ -4593,6 +4655,29 @@  static int asus_wmi_platform_init(struct asus_wmi *asus)
 		asus_wmi_set_devstate(ASUS_WMI_DEVID_CWAP,
 				      asus->driver->quirks->wapf, NULL);
 
+	/*
+	 * Check presence of Intelligent Performance Technology (AIPT).
+	 * If present store acpi handle and set asus_aipt_present to true.
+	 */
+	adev = acpi_dev_get_first_match_dev("PNP0C14", "ATK", -1);
+	if (adev) {
+		acpi_handle handle = acpi_device_handle(adev);
+
+		acpi_dev_put(adev);
+
+		if (!acpi_has_method(handle, "FANL"))
+			return 0;
+
+		asus->acpi_mgmt_handle = handle;
+		asus->asus_aipt_present = true;
+		dev_info(dev, "ASUS Intelligent Performance Technology (AIPT) is present\n");
+		/*
+		 * Set the mode corresponding to default Linux platform power
+		 * profile Balanced
+		 */
+		asus_wmi_write_aipt_mode(asus, AIPT_STANDARD);
+	}
+
 	return 0;
 }