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

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

 



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.


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,




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

  Powered by Linux