Re: [PATCH] platform/x86: asus-wmi: Support setting AIPT modes

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



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@xxxxxxxxxxxx>
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@xxxxxxxxx>
Signed-off-by: Srinivas Pandruvada
<srinivas.pandruvada@xxxxxxxxxxxxxxx>
---
      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@xxxxxxxxx/

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@xxxxxxxxx>
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






[Index of Archives]     [Linux Kernel Development]     [Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux