2024-04-25 17:29:56

by Lyndon Sanche

[permalink] [raw]
Subject: [PATCH] platform/x86: dell-laptop: Implement platform_profile

Some Dell laptops support configuration of preset
fan modes through smbios tables.

If the platform supports these fan modes, set up
platform_profile to change these modes. If not
supported, skip enabling platform_profile.

Signed-off-by: Lyndon Sanche <[email protected]>
---
drivers/platform/x86/dell/dell-laptop.c | 220 ++++++++++++++++++++++++
drivers/platform/x86/dell/dell-smbios.h | 1 +
2 files changed, 221 insertions(+)

diff --git a/drivers/platform/x86/dell/dell-laptop.c b/drivers/platform/x86/dell/dell-laptop.c
index 42f7de2b4522..7f9c4e0e5ef5 100644
--- a/drivers/platform/x86/dell/dell-laptop.c
+++ b/drivers/platform/x86/dell/dell-laptop.c
@@ -27,6 +27,7 @@
#include <linux/i8042.h>
#include <linux/debugfs.h>
#include <linux/seq_file.h>
+#include <linux/platform_profile.h>
#include <acpi/video.h>
#include "dell-rbtn.h"
#include "dell-smbios.h"
@@ -95,10 +96,18 @@ static struct backlight_device *dell_backlight_device;
static struct rfkill *wifi_rfkill;
static struct rfkill *bluetooth_rfkill;
static struct rfkill *wwan_rfkill;
+static struct platform_profile_handler *thermal_handler;
static bool force_rfkill;
static bool micmute_led_registered;
static bool mute_led_registered;

+enum thermal_mode_bits {
+ DELL_BALANCED = 0,
+ DELL_COOL_BOTTOM = 1,
+ DELL_QUIET = 2,
+ DELL_PERFORMANCE = 3,
+};
+
module_param(force_rfkill, bool, 0444);
MODULE_PARM_DESC(force_rfkill, "enable rfkill on non whitelisted models");

@@ -2199,6 +2208,211 @@ static int mute_led_set(struct led_classdev *led_cdev,
return 0;
}

+// Derived from smbios-thermal-ctl
+//
+// cbClass 17
+// cbSelect 19
+// User Selectable Thermal Tables(USTT)
+// cbArg1 determines the function to be performed
+// cbArg1 0x0 = Get Thermal Information
+// cbRES1 Standard return codes (0, -1, -2)
+// cbRES2, byte 0 Bitmap of supported thermal modes. A mode is supported if its bit is set to 1
+// Bit 0 Balanced
+// Bit 1 Cool Bottom
+// Bit 2 Quiet
+// Bit 3 Performance
+// cbRES2, byte 1 Bitmap of supported Active Acoustic Controller (AAC) modes. Each mode
+// corresponds to the supported thermal modes in byte 0. A mode is supported if
+// its bit is set to 1.
+// Bit 0 AAC (Balanced)
+// Bit 1 AAC (Cool Bottom
+// Bit 2 AAC (Quiet)
+// Bit 3 AAC (Performance)
+// cbRes3, byte 0 Current Thermal Mode
+// Bit 0 Balanced
+// Bit 1 Cool Bottom
+// Bit 2 Quiet
+// Bit 3 Performanc
+// cbRes3, byte 1 AAC Configuration type
+// 0 Global (AAC enable/disable applies to all supported USTT modes)
+// 1 USTT mode specific
+// cbRes3, byte 2 Current Active Acoustic Controller (AAC) Mode
+// If AAC Configuration Type is Global,
+// 0 AAC mode disabled
+// 1 AAC mode enabled
+// If AAC Configuration Type is USTT mode specific (multiple bits may be set),
+// Bit 0 AAC (Balanced)
+// Bit 1 AAC (Cool Bottom
+// Bit 2 AAC (Quiet)
+// Bit 3 AAC (Performance)
+// cbRes3, byte 3 Current Fan Failure Mode
+// Bit 0 Minimal Fan Failure (at least one fan has failed, one fan working)
+// Bit 1 Catastrophic Fan Failure (all fans have failed)
+// cbArg1 0x1 (Set Thermal Information), both desired thermal mode and
+// desired AAC mode shall be applied
+// cbArg2, byte 0 Desired Thermal Mode to set (only one bit may be set for this parameter)
+// Bit 0 Balanced
+// Bit 1 Cool Bottom
+// Bit 2 Quiet
+// Bit 3 Performance
+// cbArg2, byte 1 Desired Active Acoustic Controller (AAC) Mode to set
+// If AAC Configuration Type is Global,
+// 0 AAC mode disabled
+// 1 AAC mode enabled
+//
+// If AAC Configuration Type is USTT mode specific (multiple bits may be set for this parameter),
+// Bit 0 AAC (Balanced)
+// Bit 1 AAC (Cool Bottom
+// Bit 2 AAC (Quiet)
+// Bit 3 AAC (Performance)
+static int thermal_get_mode(void)
+{
+ struct calling_interface_buffer buffer;
+ int state;
+ int ret;
+
+ dell_fill_request(&buffer, 0x0, 0, 0, 0);
+ ret = dell_send_request(&buffer, CLASS_INFO, SELECT_THERMAL_MANAGEMENT);
+ if (ret)
+ return ret;
+ state = buffer.output[2];
+ if ((state >> DELL_BALANCED) & 1)
+ return DELL_BALANCED;
+ else if ((state >> DELL_COOL_BOTTOM) & 1)
+ return DELL_COOL_BOTTOM;
+ else if ((state >> DELL_QUIET) & 1)
+ return DELL_QUIET;
+ else if ((state >> DELL_PERFORMANCE) & 1)
+ return DELL_PERFORMANCE;
+ else
+ return 0;
+}
+
+static int thermal_get_supported_modes(int *supported_bits)
+{
+ struct calling_interface_buffer buffer;
+ int ret;
+
+ dell_fill_request(&buffer, 0x0, 0, 0, 0);
+ ret = dell_send_request(&buffer, CLASS_INFO, SELECT_THERMAL_MANAGEMENT);
+ if (ret)
+ return ret;
+ *supported_bits = buffer.output[1] & 0xF;
+ return 0;
+}
+
+static int thermal_get_acc_mode(int *acc_mode)
+{
+ struct calling_interface_buffer buffer;
+ int ret;
+
+ dell_fill_request(&buffer, 0x0, 0, 0, 0);
+ ret = dell_send_request(&buffer, CLASS_INFO, SELECT_THERMAL_MANAGEMENT);
+ if (ret)
+ return ret;
+ *acc_mode = ((buffer.output[3] >> 8) & 0xFF);
+ return 0;
+}
+
+static int thermal_set_mode(enum thermal_mode_bits state)
+{
+ struct calling_interface_buffer buffer;
+ int ret;
+ int acc_mode;
+
+ ret = thermal_get_acc_mode(&acc_mode);
+ if (ret)
+ return ret;
+
+ dell_fill_request(&buffer, 0x1, (acc_mode << 8) | BIT(state), 0, 0);
+ ret = dell_send_request(&buffer, CLASS_INFO, SELECT_THERMAL_MANAGEMENT);
+ return ret;
+}
+
+static int thermal_platform_profile_set(struct platform_profile_handler *pprof,
+ enum platform_profile_option profile)
+{
+ int ret;
+
+ switch (profile) {
+ case PLATFORM_PROFILE_BALANCED:
+ ret = thermal_set_mode(DELL_BALANCED);
+ break;
+ case PLATFORM_PROFILE_PERFORMANCE:
+ ret = thermal_set_mode(DELL_PERFORMANCE);
+ break;
+ case PLATFORM_PROFILE_QUIET:
+ ret = thermal_set_mode(DELL_QUIET);
+ break;
+ case PLATFORM_PROFILE_COOL:
+ ret = thermal_set_mode(DELL_COOL_BOTTOM);
+ break;
+ default:
+ return -EOPNOTSUPP;
+ }
+
+ return ret;
+}
+
+static int thermal_platform_profile_get(struct platform_profile_handler *pprof,
+ enum platform_profile_option *profile)
+{
+ switch (thermal_get_mode()) {
+ case DELL_BALANCED:
+ *profile = PLATFORM_PROFILE_BALANCED;
+ break;
+ case DELL_PERFORMANCE:
+ *profile = PLATFORM_PROFILE_PERFORMANCE;
+ break;
+ case DELL_COOL_BOTTOM:
+ *profile = PLATFORM_PROFILE_COOL;
+ break;
+ case DELL_QUIET:
+ *profile = PLATFORM_PROFILE_QUIET;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+int thermal_init(void)
+{
+ int ret;
+ int supported_modes;
+
+ ret = thermal_get_supported_modes(&supported_modes);
+
+ if (ret != 0 || supported_modes == 0)
+ return -ENXIO;
+
+ thermal_handler = kzalloc(sizeof(*thermal_handler), GFP_KERNEL);
+ if (!thermal_handler)
+ return -ENOMEM;
+ thermal_handler->profile_get = thermal_platform_profile_get;
+ thermal_handler->profile_set = thermal_platform_profile_set;
+
+ if ((supported_modes >> DELL_QUIET) & 1)
+ set_bit(PLATFORM_PROFILE_QUIET, thermal_handler->choices);
+ if ((supported_modes >> DELL_COOL_BOTTOM) & 1)
+ set_bit(PLATFORM_PROFILE_COOL, thermal_handler->choices);
+ if ((supported_modes >> DELL_BALANCED) & 1)
+ set_bit(PLATFORM_PROFILE_BALANCED, thermal_handler->choices);
+ if ((supported_modes >> DELL_PERFORMANCE) & 1)
+ set_bit(PLATFORM_PROFILE_PERFORMANCE, thermal_handler->choices);
+
+ platform_profile_register(thermal_handler);
+
+ return 0;
+}
+
+void thermal_cleanup(void)
+{
+ platform_profile_remove();
+ kfree(thermal_handler);
+}
+
static struct led_classdev mute_led_cdev = {
.name = "platform::mute",
.max_brightness = 1,
@@ -2266,6 +2480,11 @@ static int __init dell_init(void)
mute_led_registered = true;
}

+ // Do not fail module if thermal modes not supported,
+ // just skip
+ if (thermal_init() != 0)
+ pr_warn("Unable to setup platform_profile, skipping");
+
if (acpi_video_get_backlight_type() != acpi_backlight_vendor)
return 0;

@@ -2344,6 +2563,7 @@ static void __exit dell_exit(void)
platform_device_unregister(platform_device);
platform_driver_unregister(&platform_driver);
}
+ thermal_cleanup();
}

/* dell-rbtn.c driver export functions which will not work correctly (and could
diff --git a/drivers/platform/x86/dell/dell-smbios.h b/drivers/platform/x86/dell/dell-smbios.h
index eb341bf000c6..585d042f1779 100644
--- a/drivers/platform/x86/dell/dell-smbios.h
+++ b/drivers/platform/x86/dell/dell-smbios.h
@@ -19,6 +19,7 @@
/* Classes and selects used only in kernel drivers */
#define CLASS_KBD_BACKLIGHT 4
#define SELECT_KBD_BACKLIGHT 11
+#define SELECT_THERMAL_MANAGEMENT 19

/* Tokens used in kernel drivers, any of these
* should be filtered from userspace access
--
2.42.0



2024-04-25 20:07:46

by Mario Limonciello

[permalink] [raw]
Subject: Re: [PATCH] platform/x86: dell-laptop: Implement platform_profile

+ Srinivas

On 4/25/2024 12:27, Lyndon Sanche wrote:
> Some Dell laptops support configuration of preset
> fan modes through smbios tables.
>
> If the platform supports these fan modes, set up
> platform_profile to change these modes. If not
> supported, skip enabling platform_profile.
>
> Signed-off-by: Lyndon Sanche <[email protected]>
> ---

When you developed this was it using a Dell Intel or Dell AMD system?

If it was an Intel system, did you test it with thermald installed and
active?

I'm wondering how all this stuff jives with the stuff that thermald
does. I don't know if they fight for any of the same "resources".

> drivers/platform/x86/dell/dell-laptop.c | 220 ++++++++++++++++++++++++
> drivers/platform/x86/dell/dell-smbios.h | 1 +
> 2 files changed, 221 insertions(+)
>
> diff --git a/drivers/platform/x86/dell/dell-laptop.c b/drivers/platform/x86/dell/dell-laptop.c
> index 42f7de2b4522..7f9c4e0e5ef5 100644
> --- a/drivers/platform/x86/dell/dell-laptop.c
> +++ b/drivers/platform/x86/dell/dell-laptop.c
> @@ -27,6 +27,7 @@
> #include <linux/i8042.h>
> #include <linux/debugfs.h>
> #include <linux/seq_file.h>
> +#include <linux/platform_profile.h>
> #include <acpi/video.h>
> #include "dell-rbtn.h"
> #include "dell-smbios.h"
> @@ -95,10 +96,18 @@ static struct backlight_device *dell_backlight_device;
> static struct rfkill *wifi_rfkill;
> static struct rfkill *bluetooth_rfkill;
> static struct rfkill *wwan_rfkill;
> +static struct platform_profile_handler *thermal_handler;
> static bool force_rfkill;
> static bool micmute_led_registered;
> static bool mute_led_registered;
>
> +enum thermal_mode_bits {
> + DELL_BALANCED = 0,
> + DELL_COOL_BOTTOM = 1,
> + DELL_QUIET = 2,
> + DELL_PERFORMANCE = 3,
> +};
> +
> module_param(force_rfkill, bool, 0444);
> MODULE_PARM_DESC(force_rfkill, "enable rfkill on non whitelisted models");
>
> @@ -2199,6 +2208,211 @@ static int mute_led_set(struct led_classdev *led_cdev,
> return 0;
> }
>
> +// Derived from smbios-thermal-ctl
> +//
> +// cbClass 17
> +// cbSelect 19
> +// User Selectable Thermal Tables(USTT)
> +// cbArg1 determines the function to be performed
> +// cbArg1 0x0 = Get Thermal Information
> +// cbRES1 Standard return codes (0, -1, -2)
> +// cbRES2, byte 0 Bitmap of supported thermal modes. A mode is supported if its bit is set to 1
> +// Bit 0 Balanced
> +// Bit 1 Cool Bottom
> +// Bit 2 Quiet
> +// Bit 3 Performance
> +// cbRES2, byte 1 Bitmap of supported Active Acoustic Controller (AAC) modes. Each mode
> +// corresponds to the supported thermal modes in byte 0. A mode is supported if
> +// its bit is set to 1.
> +// Bit 0 AAC (Balanced)
> +// Bit 1 AAC (Cool Bottom
> +// Bit 2 AAC (Quiet)
> +// Bit 3 AAC (Performance)
> +// cbRes3, byte 0 Current Thermal Mode
> +// Bit 0 Balanced
> +// Bit 1 Cool Bottom
> +// Bit 2 Quiet
> +// Bit 3 Performanc
> +// cbRes3, byte 1 AAC Configuration type
> +// 0 Global (AAC enable/disable applies to all supported USTT modes)
> +// 1 USTT mode specific
> +// cbRes3, byte 2 Current Active Acoustic Controller (AAC) Mode
> +// If AAC Configuration Type is Global,
> +// 0 AAC mode disabled
> +// 1 AAC mode enabled
> +// If AAC Configuration Type is USTT mode specific (multiple bits may be set),
> +// Bit 0 AAC (Balanced)
> +// Bit 1 AAC (Cool Bottom
> +// Bit 2 AAC (Quiet)
> +// Bit 3 AAC (Performance)
> +// cbRes3, byte 3 Current Fan Failure Mode
> +// Bit 0 Minimal Fan Failure (at least one fan has failed, one fan working)
> +// Bit 1 Catastrophic Fan Failure (all fans have failed)
> +// cbArg1 0x1 (Set Thermal Information), both desired thermal mode and
> +// desired AAC mode shall be applied
> +// cbArg2, byte 0 Desired Thermal Mode to set (only one bit may be set for this parameter)
> +// Bit 0 Balanced
> +// Bit 1 Cool Bottom
> +// Bit 2 Quiet
> +// Bit 3 Performance
> +// cbArg2, byte 1 Desired Active Acoustic Controller (AAC) Mode to set
> +// If AAC Configuration Type is Global,
> +// 0 AAC mode disabled
> +// 1 AAC mode enabled
> +//
> +// If AAC Configuration Type is USTT mode specific (multiple bits may be set for this parameter),
> +// Bit 0 AAC (Balanced)
> +// Bit 1 AAC (Cool Bottom
> +// Bit 2 AAC (Quiet)
> +// Bit 3 AAC (Performance)
> +static int thermal_get_mode(void)
> +{
> + struct calling_interface_buffer buffer;
> + int state;
> + int ret;
> +
> + dell_fill_request(&buffer, 0x0, 0, 0, 0);
> + ret = dell_send_request(&buffer, CLASS_INFO, SELECT_THERMAL_MANAGEMENT);
> + if (ret)
> + return ret;
> + state = buffer.output[2];
> + if ((state >> DELL_BALANCED) & 1)
> + return DELL_BALANCED;
> + else if ((state >> DELL_COOL_BOTTOM) & 1)
> + return DELL_COOL_BOTTOM;
> + else if ((state >> DELL_QUIET) & 1)
> + return DELL_QUIET;
> + else if ((state >> DELL_PERFORMANCE) & 1)
> + return DELL_PERFORMANCE;
> + else
> + return 0;
> +}
> +
> +static int thermal_get_supported_modes(int *supported_bits)
> +{
> + struct calling_interface_buffer buffer;
> + int ret;
> +
> + dell_fill_request(&buffer, 0x0, 0, 0, 0);
> + ret = dell_send_request(&buffer, CLASS_INFO, SELECT_THERMAL_MANAGEMENT);
> + if (ret)
> + return ret;
> + *supported_bits = buffer.output[1] & 0xF;
> + return 0;
> +}
> +
> +static int thermal_get_acc_mode(int *acc_mode)
> +{
> + struct calling_interface_buffer buffer;
> + int ret;
> +
> + dell_fill_request(&buffer, 0x0, 0, 0, 0);
> + ret = dell_send_request(&buffer, CLASS_INFO, SELECT_THERMAL_MANAGEMENT);
> + if (ret)
> + return ret;
> + *acc_mode = ((buffer.output[3] >> 8) & 0xFF);
> + return 0;
> +}
> +
> +static int thermal_set_mode(enum thermal_mode_bits state)
> +{
> + struct calling_interface_buffer buffer;
> + int ret;
> + int acc_mode;
> +
> + ret = thermal_get_acc_mode(&acc_mode);
> + if (ret)
> + return ret;
> +
> + dell_fill_request(&buffer, 0x1, (acc_mode << 8) | BIT(state), 0, 0);
> + ret = dell_send_request(&buffer, CLASS_INFO, SELECT_THERMAL_MANAGEMENT);
> + return ret;
> +}
> +
> +static int thermal_platform_profile_set(struct platform_profile_handler *pprof,
> + enum platform_profile_option profile)
> +{
> + int ret;
> +
> + switch (profile) {
> + case PLATFORM_PROFILE_BALANCED:
> + ret = thermal_set_mode(DELL_BALANCED);
> + break;
> + case PLATFORM_PROFILE_PERFORMANCE:
> + ret = thermal_set_mode(DELL_PERFORMANCE);
> + break;
> + case PLATFORM_PROFILE_QUIET:
> + ret = thermal_set_mode(DELL_QUIET);
> + break;
> + case PLATFORM_PROFILE_COOL:
> + ret = thermal_set_mode(DELL_COOL_BOTTOM);
> + break;
> + default:
> + return -EOPNOTSUPP;
> + }
> +
> + return ret;
> +}
> +
> +static int thermal_platform_profile_get(struct platform_profile_handler *pprof,
> + enum platform_profile_option *profile)
> +{
> + switch (thermal_get_mode()) {
> + case DELL_BALANCED:
> + *profile = PLATFORM_PROFILE_BALANCED;
> + break;
> + case DELL_PERFORMANCE:
> + *profile = PLATFORM_PROFILE_PERFORMANCE;
> + break;
> + case DELL_COOL_BOTTOM:
> + *profile = PLATFORM_PROFILE_COOL;
> + break;
> + case DELL_QUIET:
> + *profile = PLATFORM_PROFILE_QUIET;
> + break;
> + default:
> + return -EINVAL;
> + }
> +
> + return 0;
> +}
> +
> +int thermal_init(void)
> +{
> + int ret;
> + int supported_modes;
> +
> + ret = thermal_get_supported_modes(&supported_modes);
> +
> + if (ret != 0 || supported_modes == 0)
> + return -ENXIO;
> +
> + thermal_handler = kzalloc(sizeof(*thermal_handler), GFP_KERNEL);
> + if (!thermal_handler)
> + return -ENOMEM;
> + thermal_handler->profile_get = thermal_platform_profile_get;
> + thermal_handler->profile_set = thermal_platform_profile_set;
> +
> + if ((supported_modes >> DELL_QUIET) & 1)
> + set_bit(PLATFORM_PROFILE_QUIET, thermal_handler->choices);
> + if ((supported_modes >> DELL_COOL_BOTTOM) & 1)
> + set_bit(PLATFORM_PROFILE_COOL, thermal_handler->choices);
> + if ((supported_modes >> DELL_BALANCED) & 1)
> + set_bit(PLATFORM_PROFILE_BALANCED, thermal_handler->choices);
> + if ((supported_modes >> DELL_PERFORMANCE) & 1)
> + set_bit(PLATFORM_PROFILE_PERFORMANCE, thermal_handler->choices);
> +
> + platform_profile_register(thermal_handler);
> +
> + return 0;
> +}
> +
> +void thermal_cleanup(void)
> +{
> + platform_profile_remove();
> + kfree(thermal_handler);
> +}
> +
> static struct led_classdev mute_led_cdev = {
> .name = "platform::mute",
> .max_brightness = 1,
> @@ -2266,6 +2480,11 @@ static int __init dell_init(void)
> mute_led_registered = true;
> }
>
> + // Do not fail module if thermal modes not supported,
> + // just skip
> + if (thermal_init() != 0)
> + pr_warn("Unable to setup platform_profile, skipping");
> +
> if (acpi_video_get_backlight_type() != acpi_backlight_vendor)
> return 0;
>
> @@ -2344,6 +2563,7 @@ static void __exit dell_exit(void)
> platform_device_unregister(platform_device);
> platform_driver_unregister(&platform_driver);
> }
> + thermal_cleanup();
> }
>
> /* dell-rbtn.c driver export functions which will not work correctly (and could
> diff --git a/drivers/platform/x86/dell/dell-smbios.h b/drivers/platform/x86/dell/dell-smbios.h
> index eb341bf000c6..585d042f1779 100644
> --- a/drivers/platform/x86/dell/dell-smbios.h
> +++ b/drivers/platform/x86/dell/dell-smbios.h
> @@ -19,6 +19,7 @@
> /* Classes and selects used only in kernel drivers */
> #define CLASS_KBD_BACKLIGHT 4
> #define SELECT_KBD_BACKLIGHT 11
> +#define SELECT_THERMAL_MANAGEMENT 19
>
> /* Tokens used in kernel drivers, any of these
> * should be filtered from userspace access


2024-04-25 20:12:23

by Pali Rohár

[permalink] [raw]
Subject: Re: [PATCH] platform/x86: dell-laptop: Implement platform_profile

On Thursday 25 April 2024 11:27:57 Lyndon Sanche wrote:
> +int thermal_init(void)
> +{
> + int ret;
> + int supported_modes;
> +
> + ret = thermal_get_supported_modes(&supported_modes);
> +
> + if (ret != 0 || supported_modes == 0)
> + return -ENXIO;
> +
> + thermal_handler = kzalloc(sizeof(*thermal_handler), GFP_KERNEL);
> + if (!thermal_handler)
> + return -ENOMEM;
> + thermal_handler->profile_get = thermal_platform_profile_get;
> + thermal_handler->profile_set = thermal_platform_profile_set;
> +
> + if ((supported_modes >> DELL_QUIET) & 1)
> + set_bit(PLATFORM_PROFILE_QUIET, thermal_handler->choices);
> + if ((supported_modes >> DELL_COOL_BOTTOM) & 1)
> + set_bit(PLATFORM_PROFILE_COOL, thermal_handler->choices);
> + if ((supported_modes >> DELL_BALANCED) & 1)
> + set_bit(PLATFORM_PROFILE_BALANCED, thermal_handler->choices);
> + if ((supported_modes >> DELL_PERFORMANCE) & 1)
> + set_bit(PLATFORM_PROFILE_PERFORMANCE, thermal_handler->choices);
> +
> + platform_profile_register(thermal_handler);
> +
> + return 0;
> +}
> +
> +void thermal_cleanup(void)
> +{
> + platform_profile_remove();
> + kfree(thermal_handler);
> +}
> +
> static struct led_classdev mute_led_cdev = {
> .name = "platform::mute",
> .max_brightness = 1,
> @@ -2266,6 +2480,11 @@ static int __init dell_init(void)
> mute_led_registered = true;
> }
>
> + // Do not fail module if thermal modes not supported,
> + // just skip
> + if (thermal_init() != 0)
> + pr_warn("Unable to setup platform_profile, skipping");

I think that -ENOMEM error should be failure of the loading the driver.
It does not make sense to continue of memory allocation failed.

On the other hand when the thermal modes are not support (e.g. old
Latitude models) then there should not be a warning message. It is
expected that on systems without thermal modes the setup fails.

> +
> if (acpi_video_get_backlight_type() != acpi_backlight_vendor)
> return 0;

2024-04-25 20:27:11

by Lyndon Sanche

[permalink] [raw]
Subject: Re: [PATCH] platform/x86: dell-laptop: Implement platform_profile

On Thu, Apr 25, 2024, at 2:07 PM, Mario Limonciello wrote:
> + Srinivas
>
> On 4/25/2024 12:27, Lyndon Sanche wrote:
>> Some Dell laptops support configuration of preset
>> fan modes through smbios tables.
>>
>> If the platform supports these fan modes, set up
>> platform_profile to change these modes. If not
>> supported, skip enabling platform_profile.
>>
>> Signed-off-by: Lyndon Sanche <[email protected]>
>> ---
>
> When you developed this was it using a Dell Intel or Dell AMD system?
>
> If it was an Intel system, did you test it with thermald installed and
> active?
>
> I'm wondering how all this stuff jives with the stuff that thermald
> does. I don't know if they fight for any of the same "resources".

Thank you for your response.

I did my development and testing on a Dell Intel system. Specifically the XPS 15 9560 with i7-7700HQ.

I do have thermald running, though I admit I am not really aware of what exactly it does, besides being related to thermals in some way.

I normally set the thermal mode with Dell's smbios-thermal-ctl program. I am not too sure all the values that the bios configures on it's own depending on the provided mode, so I am not sure if thermald conflicts. But my understanding is that would be out of scope of this driver, since we are only telling the bios what we want at a high level.

Lyndon

2024-04-25 20:29:16

by Lyndon Sanche

[permalink] [raw]
Subject: Re: [PATCH] platform/x86: dell-laptop: Implement platform_profile

On Thu, Apr 25, 2024, at 2:12 PM, Pali Rohár wrote:
> On Thursday 25 April 2024 11:27:57 Lyndon Sanche wrote:
>> +int thermal_init(void)
>> +{
>> + int ret;
>> + int supported_modes;
>> +
>> + ret = thermal_get_supported_modes(&supported_modes);
>> +
>> + if (ret != 0 || supported_modes == 0)
>> + return -ENXIO;
>> +
>> + thermal_handler = kzalloc(sizeof(*thermal_handler), GFP_KERNEL);
>> + if (!thermal_handler)
>> + return -ENOMEM;
>> + thermal_handler->profile_get = thermal_platform_profile_get;
>> + thermal_handler->profile_set = thermal_platform_profile_set;
>> +
>> + if ((supported_modes >> DELL_QUIET) & 1)
>> + set_bit(PLATFORM_PROFILE_QUIET, thermal_handler->choices);
>> + if ((supported_modes >> DELL_COOL_BOTTOM) & 1)
>> + set_bit(PLATFORM_PROFILE_COOL, thermal_handler->choices);
>> + if ((supported_modes >> DELL_BALANCED) & 1)
>> + set_bit(PLATFORM_PROFILE_BALANCED, thermal_handler->choices);
>> + if ((supported_modes >> DELL_PERFORMANCE) & 1)
>> + set_bit(PLATFORM_PROFILE_PERFORMANCE, thermal_handler->choices);
>> +
>> + platform_profile_register(thermal_handler);
>> +
>> + return 0;
>> +}
>> +
>> +void thermal_cleanup(void)
>> +{
>> + platform_profile_remove();
>> + kfree(thermal_handler);
>> +}
>> +
>> static struct led_classdev mute_led_cdev = {
>> .name = "platform::mute",
>> .max_brightness = 1,
>> @@ -2266,6 +2480,11 @@ static int __init dell_init(void)
>> mute_led_registered = true;
>> }
>>
>> + // Do not fail module if thermal modes not supported,
>> + // just skip
>> + if (thermal_init() != 0)
>> + pr_warn("Unable to setup platform_profile, skipping");
>
> I think that -ENOMEM error should be failure of the loading the driver.
> It does not make sense to continue of memory allocation failed.
>
> On the other hand when the thermal modes are not support (e.g. old
> Latitude models) then there should not be a warning message. It is
> expected that on systems without thermal modes the setup fails.

Thank you for your feedback.

I agree with your suggestion. -ENOMEM would indicate something bigger is amiss. I can add a check:

If -ENOMEM, fail driver.
If anything other error, skip, but do not show a message.

Lyndon

2024-04-25 20:29:31

by Mario Limonciello

[permalink] [raw]
Subject: Re: [PATCH] platform/x86: dell-laptop: Implement platform_profile

On 4/25/2024 15:24, Lyndon Sanche wrote:
> On Thu, Apr 25, 2024, at 2:07 PM, Mario Limonciello wrote:
>> + Srinivas
>>
>> On 4/25/2024 12:27, Lyndon Sanche wrote:
>>> Some Dell laptops support configuration of preset
>>> fan modes through smbios tables.
>>>
>>> If the platform supports these fan modes, set up
>>> platform_profile to change these modes. If not
>>> supported, skip enabling platform_profile.
>>>
>>> Signed-off-by: Lyndon Sanche <[email protected]>
>>> ---
>>
>> When you developed this was it using a Dell Intel or Dell AMD system?
>>
>> If it was an Intel system, did you test it with thermald installed and
>> active?
>>
>> I'm wondering how all this stuff jives with the stuff that thermald
>> does. I don't know if they fight for any of the same "resources".
>
> Thank you for your response.
>
> I did my development and testing on a Dell Intel system. Specifically the XPS 15 9560 with i7-7700HQ.
>
> I do have thermald running, though I admit I am not really aware of what exactly it does, besides being related to thermals in some way.
>
> I normally set the thermal mode with Dell's smbios-thermal-ctl program. I am not too sure all the values that the bios configures on it's own depending on the provided mode, so I am not sure if thermald conflicts. But my understanding is that would be out of scope of this driver, since we are only telling the bios what we want at a high level.
>
> Lyndon

Yeah it's not say it's a "new" conflict, it would just become a lot more
prevalent since software like GNOME and KDE use power-profiles-daemon to
manipulate the new power profile you're exporting from the driver.

If there really is no conflict, then great!
If there is a conflict then I was just wondering if there needs to be an
easy way to turn on/off the profile support when thermald is in use.

2024-04-25 20:31:24

by Pali Rohár

[permalink] [raw]
Subject: Re: [PATCH] platform/x86: dell-laptop: Implement platform_profile

On Thursday 25 April 2024 14:27:32 Lyndon Sanche wrote:
> On Thu, Apr 25, 2024, at 2:12 PM, Pali Rohár wrote:
> > On Thursday 25 April 2024 11:27:57 Lyndon Sanche wrote:
> >> +int thermal_init(void)
> >> +{
> >> + int ret;
> >> + int supported_modes;
> >> +
> >> + ret = thermal_get_supported_modes(&supported_modes);
> >> +
> >> + if (ret != 0 || supported_modes == 0)
> >> + return -ENXIO;
> >> +
> >> + thermal_handler = kzalloc(sizeof(*thermal_handler), GFP_KERNEL);
> >> + if (!thermal_handler)
> >> + return -ENOMEM;
> >> + thermal_handler->profile_get = thermal_platform_profile_get;
> >> + thermal_handler->profile_set = thermal_platform_profile_set;
> >> +
> >> + if ((supported_modes >> DELL_QUIET) & 1)
> >> + set_bit(PLATFORM_PROFILE_QUIET, thermal_handler->choices);
> >> + if ((supported_modes >> DELL_COOL_BOTTOM) & 1)
> >> + set_bit(PLATFORM_PROFILE_COOL, thermal_handler->choices);
> >> + if ((supported_modes >> DELL_BALANCED) & 1)
> >> + set_bit(PLATFORM_PROFILE_BALANCED, thermal_handler->choices);
> >> + if ((supported_modes >> DELL_PERFORMANCE) & 1)
> >> + set_bit(PLATFORM_PROFILE_PERFORMANCE, thermal_handler->choices);
> >> +
> >> + platform_profile_register(thermal_handler);
> >> +
> >> + return 0;
> >> +}
> >> +
> >> +void thermal_cleanup(void)
> >> +{
> >> + platform_profile_remove();
> >> + kfree(thermal_handler);
> >> +}
> >> +
> >> static struct led_classdev mute_led_cdev = {
> >> .name = "platform::mute",
> >> .max_brightness = 1,
> >> @@ -2266,6 +2480,11 @@ static int __init dell_init(void)
> >> mute_led_registered = true;
> >> }
> >>
> >> + // Do not fail module if thermal modes not supported,
> >> + // just skip
> >> + if (thermal_init() != 0)
> >> + pr_warn("Unable to setup platform_profile, skipping");
> >
> > I think that -ENOMEM error should be failure of the loading the driver.
> > It does not make sense to continue of memory allocation failed.
> >
> > On the other hand when the thermal modes are not support (e.g. old
> > Latitude models) then there should not be a warning message. It is
> > expected that on systems without thermal modes the setup fails.
>
> Thank you for your feedback.
>
> I agree with your suggestion. -ENOMEM would indicate something bigger is amiss. I can add a check:
>
> If -ENOMEM, fail driver.
> If anything other error, skip, but do not show a message.
>
> Lyndon

Maybe you can simplify it more. thermal_init() could return 0 also for
the case when thermal modes are not supported. And dell_init() then can
unconditionally fail when thermal_init() returns non-zero value. It has
benefit that in case thermal_init() is extended in future for some other
fatal error, it would not be required to update also caller to handle
another error (and not just ENOMEM).

2024-04-25 21:07:56

by Armin Wolf

[permalink] [raw]
Subject: Re: [PATCH] platform/x86: dell-laptop: Implement platform_profile

Am 25.04.24 um 19:27 schrieb Lyndon Sanche:

> Some Dell laptops support configuration of preset
> fan modes through smbios tables.
>
> If the platform supports these fan modes, set up
> platform_profile to change these modes. If not
> supported, skip enabling platform_profile.
>
> Signed-off-by: Lyndon Sanche <[email protected]>
> ---
> drivers/platform/x86/dell/dell-laptop.c | 220 ++++++++++++++++++++++++
> drivers/platform/x86/dell/dell-smbios.h | 1 +
> 2 files changed, 221 insertions(+)
>
> diff --git a/drivers/platform/x86/dell/dell-laptop.c b/drivers/platform/x86/dell/dell-laptop.c
> index 42f7de2b4522..7f9c4e0e5ef5 100644
> --- a/drivers/platform/x86/dell/dell-laptop.c
> +++ b/drivers/platform/x86/dell/dell-laptop.c
> @@ -27,6 +27,7 @@
> #include <linux/i8042.h>
> #include <linux/debugfs.h>
> #include <linux/seq_file.h>
> +#include <linux/platform_profile.h>
> #include <acpi/video.h>
> #include "dell-rbtn.h"
> #include "dell-smbios.h"
> @@ -95,10 +96,18 @@ static struct backlight_device *dell_backlight_device;
> static struct rfkill *wifi_rfkill;
> static struct rfkill *bluetooth_rfkill;
> static struct rfkill *wwan_rfkill;
> +static struct platform_profile_handler *thermal_handler;
> static bool force_rfkill;
> static bool micmute_led_registered;
> static bool mute_led_registered;
>
> +enum thermal_mode_bits {
> + DELL_BALANCED = 0,
> + DELL_COOL_BOTTOM = 1,
> + DELL_QUIET = 2,
> + DELL_PERFORMANCE = 3,
> +};
> +
> module_param(force_rfkill, bool, 0444);
> MODULE_PARM_DESC(force_rfkill, "enable rfkill on non whitelisted models");
>
> @@ -2199,6 +2208,211 @@ static int mute_led_set(struct led_classdev *led_cdev,
> return 0;
> }
>
> +// Derived from smbios-thermal-ctl
> +//
> +// cbClass 17
> +// cbSelect 19
> +// User Selectable Thermal Tables(USTT)
> +// cbArg1 determines the function to be performed
> +// cbArg1 0x0 = Get Thermal Information
> +// cbRES1 Standard return codes (0, -1, -2)
> +// cbRES2, byte 0 Bitmap of supported thermal modes. A mode is supported if its bit is set to 1
> +// Bit 0 Balanced
> +// Bit 1 Cool Bottom
> +// Bit 2 Quiet
> +// Bit 3 Performance
> +// cbRES2, byte 1 Bitmap of supported Active Acoustic Controller (AAC) modes. Each mode
> +// corresponds to the supported thermal modes in byte 0 A mode is supported if
> +// its bit is set to 1.
> +// Bit 0 AAC (Balanced)
> +// Bit 1 AAC (Cool Bottom
> +// Bit 2 AAC (Quiet)
> +// Bit 3 AAC (Performance)
> +// cbRes3, byte 0 Current Thermal Mode
> +// Bit 0 Balanced
> +// Bit 1 Cool Bottom
> +// Bit 2 Quiet
> +// Bit 3 Performanc
> +// cbRes3, byte 1 AAC Configuration type
> +// 0 Global (AAC enable/disable applies to all supported USTT modes)
> +// 1 USTT mode specific
> +// cbRes3, byte 2 Current Active Acoustic Controller (AAC) Mode
> +// If AAC Configuration Type is Global,
> +// 0 AAC mode disabled
> +// 1 AAC mode enabled
> +// If AAC Configuration Type is USTT mode specific (multiple bits may be set),
> +// Bit 0 AAC (Balanced)
> +// Bit 1 AAC (Cool Bottom
> +// Bit 2 AAC (Quiet)
> +// Bit 3 AAC (Performance)
> +// cbRes3, byte 3 Current Fan Failure Mode
> +// Bit 0 Minimal Fan Failure (at least one fan has failed, one fan working)
> +// Bit 1 Catastrophic Fan Failure (all fans have failed)
> +// cbArg1 0x1 (Set Thermal Information), both desired thermal mode and
> +// desired AAC mode shall be applied
> +// cbArg2, byte 0 Desired Thermal Mode to set (only one bit may be set for this parameter)
> +// Bit 0 Balanced
> +// Bit 1 Cool Bottom
> +// Bit 2 Quiet
> +// Bit 3 Performance
> +// cbArg2, byte 1 Desired Active Acoustic Controller (AAC) Mode to set
> +// If AAC Configuration Type is Global,
> +// 0 AAC mode disabled
> +// 1 AAC mode enabled
> +//
> +// If AAC Configuration Type is USTT mode specific (multiple bits may be set for this parameter),

Hi,

checkpatch reports: WARNING: line length of 101 exceeds 100 columns

> +// Bit 0 AAC (Balanced)
> +// Bit 1 AAC (Cool Bottom
> +// Bit 2 AAC (Quiet)
> +// Bit 3 AAC (Performance)
> +static int thermal_get_mode(void)
> +{
> + struct calling_interface_buffer buffer;
> + int state;
> + int ret;
> +
> + dell_fill_request(&buffer, 0x0, 0, 0, 0);
> + ret = dell_send_request(&buffer, CLASS_INFO, SELECT_THERMAL_MANAGEMENT);
> + if (ret)
> + return ret;
> + state = buffer.output[2];
> + if ((state >> DELL_BALANCED) & 1)
> + return DELL_BALANCED;
> + else if ((state >> DELL_COOL_BOTTOM) & 1)
> + return DELL_COOL_BOTTOM;
> + else if ((state >> DELL_QUIET) & 1)
> + return DELL_QUIET;
> + else if ((state >> DELL_PERFORMANCE) & 1)
> + return DELL_PERFORMANCE;
> + else
> + return 0;

This would return DELL_BALANCED if no option is set. Please return an appropriate error code.

> +}
> +
> +static int thermal_get_supported_modes(int *supported_bits)
> +{
> + struct calling_interface_buffer buffer;
> + int ret;
> +
> + dell_fill_request(&buffer, 0x0, 0, 0, 0);
> + ret = dell_send_request(&buffer, CLASS_INFO, SELECT_THERMAL_MANAGEMENT);
> + if (ret)
> + return ret;
> + *supported_bits = buffer.output[1] & 0xF;
> + return 0;
> +}
> +
> +static int thermal_get_acc_mode(int *acc_mode)
> +{
> + struct calling_interface_buffer buffer;
> + int ret;
> +
> + dell_fill_request(&buffer, 0x0, 0, 0, 0);
> + ret = dell_send_request(&buffer, CLASS_INFO, SELECT_THERMAL_MANAGEMENT);
> + if (ret)
> + return ret;
> + *acc_mode = ((buffer.output[3] >> 8) & 0xFF);
> + return 0;
> +}
> +
> +static int thermal_set_mode(enum thermal_mode_bits state)
> +{
> + struct calling_interface_buffer buffer;
> + int ret;
> + int acc_mode;
> +
> + ret = thermal_get_acc_mode(&acc_mode);
> + if (ret)
> + return ret;
> +
> + dell_fill_request(&buffer, 0x1, (acc_mode << 8) | BIT(state), 0, 0);
> + ret = dell_send_request(&buffer, CLASS_INFO, SELECT_THERMAL_MANAGEMENT);
> + return ret;
> +}
> +
> +static int thermal_platform_profile_set(struct platform_profile_handler *pprof,
> + enum platform_profile_option profile)
> +{
> + int ret;
> +
> + switch (profile) {
> + case PLATFORM_PROFILE_BALANCED:
> + ret = thermal_set_mode(DELL_BALANCED);
> + break;

Maybe using "return thermal_set_mode()" would be better in this cases.

> + case PLATFORM_PROFILE_PERFORMANCE:
> + ret = thermal_set_mode(DELL_PERFORMANCE);
> + break;
> + case PLATFORM_PROFILE_QUIET:
> + ret = thermal_set_mode(DELL_QUIET);
> + break;
> + case PLATFORM_PROFILE_COOL:
> + ret = thermal_set_mode(DELL_COOL_BOTTOM);
> + break;
> + default:
> + return -EOPNOTSUPP;
> + }
> +
> + return ret;
> +}
> +
> +static int thermal_platform_profile_get(struct platform_profile_handler *pprof,
> + enum platform_profile_option *profile)
> +{
> + switch (thermal_get_mode()) {

Please check if thermal_get_mode() returned an error code and return it in this case.

> + case DELL_BALANCED:
> + *profile = PLATFORM_PROFILE_BALANCED;
> + break;
> + case DELL_PERFORMANCE:
> + *profile = PLATFORM_PROFILE_PERFORMANCE;
> + break;
> + case DELL_COOL_BOTTOM:
> + *profile = PLATFORM_PROFILE_COOL;
> + break;
> + case DELL_QUIET:
> + *profile = PLATFORM_PROFILE_QUIET;
> + break;
> + default:
> + return -EINVAL;
> + }
> +
> + return 0;
> +}
> +
> +int thermal_init(void)
> +{
> + int ret;
> + int supported_modes;
> +
> + ret = thermal_get_supported_modes(&supported_modes);
> +
> + if (ret != 0 || supported_modes == 0)
> + return -ENXIO;
> +
> + thermal_handler = kzalloc(sizeof(*thermal_handler), GFP_KERNEL);
> + if (!thermal_handler)
> + return -ENOMEM;
> + thermal_handler->profile_get = thermal_platform_profile_get;
> + thermal_handler->profile_set = thermal_platform_profile_set;
> +
> + if ((supported_modes >> DELL_QUIET) & 1)
> + set_bit(PLATFORM_PROFILE_QUIET, thermal_handler->choices);
> + if ((supported_modes >> DELL_COOL_BOTTOM) & 1)
> + set_bit(PLATFORM_PROFILE_COOL, thermal_handler->choices);
> + if ((supported_modes >> DELL_BALANCED) & 1)
> + set_bit(PLATFORM_PROFILE_BALANCED, thermal_handler->choices);
> + if ((supported_modes >> DELL_PERFORMANCE) & 1)
> + set_bit(PLATFORM_PROFILE_PERFORMANCE, thermal_handler->choices);
> +
> + platform_profile_register(thermal_handler);
> +
> + return 0;

Please check the return value of platform_profile_register() and return the error if this function fails,
see commit fe0e04cf66a1 ("platform/surface: platform_profile: Propagate error if profile registration fails")
for an explanation.

> +}
> +
> +void thermal_cleanup(void)
> +{
> + platform_profile_remove();
> + kfree(thermal_handler);
> +}
> +
> static struct led_classdev mute_led_cdev = {
> .name = "platform::mute",
> .max_brightness = 1,
> @@ -2266,6 +2480,11 @@ static int __init dell_init(void)
> mute_led_registered = true;
> }
>
> + // Do not fail module if thermal modes not supported,
> + // just skip
> + if (thermal_init() != 0)
> + pr_warn("Unable to setup platform_profile, skipping");
> +
> if (acpi_video_get_backlight_type() != acpi_backlight_vendor)
> return 0;
>
> @@ -2344,6 +2563,7 @@ static void __exit dell_exit(void)
> platform_device_unregister(platform_device);
> platform_driver_unregister(&platform_driver);
> }
> + thermal_cleanup();

Should only be called when thermal_init() was successful.

Thanks,
Armin Wolf

> }
>
> /* dell-rbtn.c driver export functions which will not work correctly (and could
> diff --git a/drivers/platform/x86/dell/dell-smbios.h b/drivers/platform/x86/dell/dell-smbios.h
> index eb341bf000c6..585d042f1779 100644
> --- a/drivers/platform/x86/dell/dell-smbios.h
> +++ b/drivers/platform/x86/dell/dell-smbios.h
> @@ -19,6 +19,7 @@
> /* Classes and selects used only in kernel drivers */
> #define CLASS_KBD_BACKLIGHT 4
> #define SELECT_KBD_BACKLIGHT 11
> +#define SELECT_THERMAL_MANAGEMENT 19
>
> /* Tokens used in kernel drivers, any of these
> * should be filtered from userspace access

2024-04-25 21:52:30

by srinivas pandruvada

[permalink] [raw]
Subject: Re: [PATCH] platform/x86: dell-laptop: Implement platform_profile


On 4/25/24 13:28, Mario Limonciello wrote:
> On 4/25/2024 15:24, Lyndon Sanche wrote:
>> On Thu, Apr 25, 2024, at 2:07 PM, Mario Limonciello wrote:
>>> + Srinivas
>>>
>>> On 4/25/2024 12:27, Lyndon Sanche wrote:
>>>> Some Dell laptops support configuration of preset
>>>> fan modes through smbios tables.
>>>>
>>>> If the platform supports these fan modes, set up
>>>> platform_profile to change these modes. If not
>>>> supported, skip enabling platform_profile.
>>>>
>>>> Signed-off-by: Lyndon Sanche <[email protected]>
>>>> ---
>>>
>>> When you developed this was it using a Dell Intel or Dell AMD system?
>>>
>>> If it was an Intel system, did you test it with thermald installed and
>>> active?
>>>
>>> I'm wondering how all this stuff jives with the stuff that thermald
>>> does.  I don't know if they fight for any of the same "resources".
>>
>> Thank you for your response.
>>
>> I did my development and testing on a Dell Intel system. Specifically
>> the XPS 15 9560 with i7-7700HQ.
>>
>> I do have thermald running, though I admit I am not really aware of
>> what exactly it does, besides being related to thermals in some way.
>>
>> I normally set the thermal mode with Dell's smbios-thermal-ctl
>> program. I am not too sure all the values that the bios configures on
>> it's own depending on the provided mode, so I am not sure if thermald
>> conflicts. But my understanding is that would be out of scope of this
>> driver, since we are only telling the bios what we want at a high level.
>>
>> Lyndon
>
> Yeah it's not say it's a "new" conflict, it would just become a lot
> more prevalent since software like GNOME and KDE use
> power-profiles-daemon to manipulate the new power profile you're
> exporting from the driver.
>
> If there really is no conflict, then great!
> If there is a conflict then I was just wondering if there needs to be
> an easy way to turn on/off the profile support when thermald is in use.

This shouldn't be in conflict as this should be directly changing some
settings in BIOS. BIOS should send some notification, if it wants some
changes in thermal tables used by thermald.


Thanks,

Srinivas



2024-04-26 00:39:03

by Lyndon Sanche

[permalink] [raw]
Subject: Re: [PATCH] platform/x86: dell-laptop: Implement platform_profile



On Thu, Apr 25 2024 at 02:51:42 PM -07:00:00, Srinivas Pandruvada
<[email protected]> wrote:
>
> On 4/25/24 13:28, Mario Limonciello wrote:
>> Yeah it's not say it's a "new" conflict, it would just become a lot
>> more prevalent since software like GNOME and KDE use
>> power-profiles-daemon to manipulate the new power profile you're
>> exporting from the driver.
>>
>> If there really is no conflict, then great!
>> If there is a conflict then I was just wondering if there needs to
>> be an easy way to turn on/off the profile support when thermald is
>> in use.
>
> This shouldn't be in conflict as this should be directly changing
> some settings in BIOS. BIOS should send some notification, if it
> wants some changes in thermal tables used by thermald.
>
>
> Thanks,
>
> Srinivas
>

If we do not think there is a conflict I can leave it without a toggle.

Lyndon




2024-04-26 00:54:31

by Lyndon Sanche

[permalink] [raw]
Subject: Re: [PATCH] platform/x86: dell-laptop: Implement platform_profile



On Thu, Apr 25 2024 at 11:07:22 PM +02:00:00, Armin Wolf
<[email protected]> wrote:
> Am 25.04.24 um 19:27 schrieb Lyndon Sanche:
>>
>> +// 1 AAC mode enabled
>> +//
>> +// If AAC Configuration Type is USTT mode specific (multiple
>> bits may be set for this parameter),
>
> Hi,
>
> checkpatch reports: WARNING: line length of 101 exceeds 100 columns

I can wrap this last line.

>
>> +// Bit 0 AAC (Balanced)
>> +// Bit 1 AAC (Cool Bottom
>> +// Bit 2 AAC (Quiet)
>> +// Bit 3 AAC (Performance)
>> +static int thermal_get_mode(void)
>> +{
>> + struct calling_interface_buffer buffer;
>> + int state;
>> + int ret;
>> +
>> + dell_fill_request(&buffer, 0x0, 0, 0, 0);
>> + ret = dell_send_request(&buffer, CLASS_INFO,
>> SELECT_THERMAL_MANAGEMENT);
>> + if (ret)
>> + return ret;
>> + state = buffer.output[2];
>> + if ((state >> DELL_BALANCED) & 1)
>> + return DELL_BALANCED;
>> + else if ((state >> DELL_COOL_BOTTOM) & 1)
>> + return DELL_COOL_BOTTOM;
>> + else if ((state >> DELL_QUIET) & 1)
>> + return DELL_QUIET;
>> + else if ((state >> DELL_PERFORMANCE) & 1)
>> + return DELL_PERFORMANCE;
>> + else
>> + return 0;
>
> This would return DELL_BALANCED if no option is set. Please return an
> appropriate error code.

Thanks for catching this, I will return a proper error code.

>
>> +}
>> +
>> +static int thermal_get_supported_modes(int *supported_bits)
>> +{
>> + struct calling_interface_buffer buffer;
>> + int ret;
>> +
>> + dell_fill_request(&buffer, 0x0, 0, 0, 0);
>> + ret = dell_send_request(&buffer, CLASS_INFO,
>> SELECT_THERMAL_MANAGEMENT);
>> + if (ret)
>> + return ret;
>> + *supported_bits = buffer.output[1] & 0xF;
>> + return 0;
>> +}
>> +
>> +static int thermal_get_acc_mode(int *acc_mode)
>> +{
>> + struct calling_interface_buffer buffer;
>> + int ret;
>> +
>> + dell_fill_request(&buffer, 0x0, 0, 0, 0);
>> + ret = dell_send_request(&buffer, CLASS_INFO,
>> SELECT_THERMAL_MANAGEMENT);
>> + if (ret)
>> + return ret;
>> + *acc_mode = ((buffer.output[3] >> 8) & 0xFF);
>> + return 0;
>> +}
>> +
>> +static int thermal_set_mode(enum thermal_mode_bits state)
>> +{
>> + struct calling_interface_buffer buffer;
>> + int ret;
>> + int acc_mode;
>> +
>> + ret = thermal_get_acc_mode(&acc_mode);
>> + if (ret)
>> + return ret;
>> +
>> + dell_fill_request(&buffer, 0x1, (acc_mode << 8) | BIT(state), 0,
>> 0);
>> + ret = dell_send_request(&buffer, CLASS_INFO,
>> SELECT_THERMAL_MANAGEMENT);
>> + return ret;
>> +}
>> +
>> +static int thermal_platform_profile_set(struct
>> platform_profile_handler *pprof,
>> + enum platform_profile_option profile)
>> +{
>> + int ret;
>> +
>> + switch (profile) {
>> + case PLATFORM_PROFILE_BALANCED:
>> + ret = thermal_set_mode(DELL_BALANCED);
>> + break;
>
> Maybe using "return thermal_set_mode()" would be better in this cases.

Good idea, I can clean up the code with this suggestion.

>
>> + case PLATFORM_PROFILE_PERFORMANCE:
>> + ret = thermal_set_mode(DELL_PERFORMANCE);
>> + break;
>> + case PLATFORM_PROFILE_QUIET:
>> + ret = thermal_set_mode(DELL_QUIET);
>> + break;
>> + case PLATFORM_PROFILE_COOL:
>> + ret = thermal_set_mode(DELL_COOL_BOTTOM);
>> + break;
>> + default:
>> + return -EOPNOTSUPP;
>> + }
>> +
>> + return ret;
>> +}
>> +
>> +static int thermal_platform_profile_get(struct
>> platform_profile_handler *pprof,
>> + enum platform_profile_option *profile)
>> +{
>> + switch (thermal_get_mode()) {
>
> Please check if thermal_get_mode() returned an error code and return
> it in this case.

Will add error checking.

>> + set_bit(PLATFORM_PROFILE_PERFORMANCE, thermal_handler->choices);
>> +
>> + platform_profile_register(thermal_handler);
>> +
>> + return 0;
>
> Please check the return value of platform_profile_register() and
> return the error if this function fails,
> see commit fe0e04cf66a1 ("platform/surface: platform_profile:
> Propagate error if profile registration fails")
> for an explanation.

Thank you for catching this. I forgot to handle the return value.

>
>> +}
>> +
>> +void thermal_cleanup(void)
>> +{
>> + platform_profile_remove();
>> + kfree(thermal_handler);
>> +}
>> +
>> static struct led_classdev mute_led_cdev = {
>> .name = "platform::mute",
>> .max_brightness = 1,
>> @@ -2266,6 +2480,11 @@ static int __init dell_init(void)
>> mute_led_registered = true;
>> }
>>
>> + // Do not fail module if thermal modes not supported,
>> + // just skip
>> + if (thermal_init() != 0)
>> + pr_warn("Unable to setup platform_profile, skipping");
>> +
>> if (acpi_video_get_backlight_type() != acpi_backlight_vendor)
>> return 0;
>>
>> @@ -2344,6 +2563,7 @@ static void __exit dell_exit(void)
>> platform_device_unregister(platform_device);
>> platform_driver_unregister(&platform_driver);
>> }
>> + thermal_cleanup();
>
> Should only be called when thermal_init() was successful.

I do not believe it is incorrect to skip checking for this.

platform_profile_remove() does not return anything and does not panic
when a profile is not currently registered. My understanding from
reading the source is it handles the case of no profile gracefully.
Please let me know if my understanding is incorrect however.

kfree does not care of the thermal handler is allocated or not. Please
let me know if calling kfree on NULL pointers is poor form for this
application.

Thank you for your feedback, I do appreciate it.

Lyndon



2024-04-26 02:05:44

by Lyndon Sanche

[permalink] [raw]
Subject: [PATCH v2] platform/x86: dell-laptop: Implement platform_profile

Some Dell laptops support configuration of preset
fan modes through smbios tables.

If the platform supports these fan modes, set up
platform_profile to change these modes. If not
supported, skip enabling platform_profile.

Signed-off-by: Lyndon Sanche <[email protected]>
---
drivers/platform/x86/dell/dell-laptop.c | 223 ++++++++++++++++++++++++
drivers/platform/x86/dell/dell-smbios.h | 1 +
2 files changed, 224 insertions(+)

diff --git a/drivers/platform/x86/dell/dell-laptop.c b/drivers/platform/x86/dell/dell-laptop.c
index 42f7de2b4522..ff67bc7697b1 100644
--- a/drivers/platform/x86/dell/dell-laptop.c
+++ b/drivers/platform/x86/dell/dell-laptop.c
@@ -27,6 +27,7 @@
#include <linux/i8042.h>
#include <linux/debugfs.h>
#include <linux/seq_file.h>
+#include <linux/platform_profile.h>
#include <acpi/video.h>
#include "dell-rbtn.h"
#include "dell-smbios.h"
@@ -95,10 +96,18 @@ static struct backlight_device *dell_backlight_device;
static struct rfkill *wifi_rfkill;
static struct rfkill *bluetooth_rfkill;
static struct rfkill *wwan_rfkill;
+static struct platform_profile_handler *thermal_handler;
static bool force_rfkill;
static bool micmute_led_registered;
static bool mute_led_registered;

+enum thermal_mode_bits {
+ DELL_BALANCED = 0,
+ DELL_COOL_BOTTOM = 1,
+ DELL_QUIET = 2,
+ DELL_PERFORMANCE = 3,
+};
+
module_param(force_rfkill, bool, 0444);
MODULE_PARM_DESC(force_rfkill, "enable rfkill on non whitelisted models");

@@ -2199,6 +2208,211 @@ static int mute_led_set(struct led_classdev *led_cdev,
return 0;
}

+// Derived from smbios-thermal-ctl
+//
+// cbClass 17
+// cbSelect 19
+// User Selectable Thermal Tables(USTT)
+// cbArg1 determines the function to be performed
+// cbArg1 0x0 = Get Thermal Information
+// cbRES1 Standard return codes (0, -1, -2)
+// cbRES2, byte 0 Bitmap of supported thermal modes. A mode is supported if its bit is set to 1
+// Bit 0 Balanced
+// Bit 1 Cool Bottom
+// Bit 2 Quiet
+// Bit 3 Performance
+// cbRES2, byte 1 Bitmap of supported Active Acoustic Controller (AAC) modes. Each mode
+// corresponds to the supported thermal modes in byte 0. A mode is supported if
+// its bit is set to 1.
+// Bit 0 AAC (Balanced)
+// Bit 1 AAC (Cool Bottom
+// Bit 2 AAC (Quiet)
+// Bit 3 AAC (Performance)
+// cbRes3, byte 0 Current Thermal Mode
+// Bit 0 Balanced
+// Bit 1 Cool Bottom
+// Bit 2 Quiet
+// Bit 3 Performanc
+// cbRes3, byte 1 AAC Configuration type
+// 0 Global (AAC enable/disable applies to all supported USTT modes)
+// 1 USTT mode specific
+// cbRes3, byte 2 Current Active Acoustic Controller (AAC) Mode
+// If AAC Configuration Type is Global,
+// 0 AAC mode disabled
+// 1 AAC mode enabled
+// If AAC Configuration Type is USTT mode specific (multiple bits may be set),
+// Bit 0 AAC (Balanced)
+// Bit 1 AAC (Cool Bottom
+// Bit 2 AAC (Quiet)
+// Bit 3 AAC (Performance)
+// cbRes3, byte 3 Current Fan Failure Mode
+// Bit 0 Minimal Fan Failure (at least one fan has failed, one fan working)
+// Bit 1 Catastrophic Fan Failure (all fans have failed)
+// cbArg1 0x1 (Set Thermal Information), both desired thermal mode and
+// desired AAC mode shall be applied
+// cbArg2, byte 0 Desired Thermal Mode to set (only one bit may be set for this parameter)
+// Bit 0 Balanced
+// Bit 1 Cool Bottom
+// Bit 2 Quiet
+// Bit 3 Performance
+// cbArg2, byte 1 Desired Active Acoustic Controller (AAC) Mode to set
+// If AAC Configuration Type is Global,
+// 0 AAC mode disabled
+// 1 AAC mode enabled
+//
+// If AAC Configuration Type is USTT mode specific
+// (multiple bits may be set for this parameter),
+// Bit 0 AAC (Balanced)
+// Bit 1 AAC (Cool Bottom
+// Bit 2 AAC (Quiet)
+// Bit 3 AAC (Performance)
+static int thermal_get_mode(void)
+{
+ struct calling_interface_buffer buffer;
+ int state;
+ int ret;
+
+ dell_fill_request(&buffer, 0x0, 0, 0, 0);
+ ret = dell_send_request(&buffer, CLASS_INFO, SELECT_THERMAL_MANAGEMENT);
+ if (ret)
+ return ret;
+ state = buffer.output[2];
+ if ((state >> DELL_BALANCED) & 1)
+ return DELL_BALANCED;
+ else if ((state >> DELL_COOL_BOTTOM) & 1)
+ return DELL_COOL_BOTTOM;
+ else if ((state >> DELL_QUIET) & 1)
+ return DELL_QUIET;
+ else if ((state >> DELL_PERFORMANCE) & 1)
+ return DELL_PERFORMANCE;
+ else
+ return -ENXIO;
+}
+
+static int thermal_get_supported_modes(int *supported_bits)
+{
+ struct calling_interface_buffer buffer;
+ int ret;
+
+ dell_fill_request(&buffer, 0x0, 0, 0, 0);
+ ret = dell_send_request(&buffer, CLASS_INFO, SELECT_THERMAL_MANAGEMENT);
+ if (ret)
+ return ret;
+ *supported_bits = buffer.output[1] & 0xF;
+ return 0;
+}
+
+static int thermal_get_acc_mode(int *acc_mode)
+{
+ struct calling_interface_buffer buffer;
+ int ret;
+
+ dell_fill_request(&buffer, 0x0, 0, 0, 0);
+ ret = dell_send_request(&buffer, CLASS_INFO, SELECT_THERMAL_MANAGEMENT);
+ if (ret)
+ return ret;
+ *acc_mode = ((buffer.output[3] >> 8) & 0xFF);
+ return 0;
+}
+
+static int thermal_set_mode(enum thermal_mode_bits state)
+{
+ struct calling_interface_buffer buffer;
+ int ret;
+ int acc_mode;
+
+ ret = thermal_get_acc_mode(&acc_mode);
+ if (ret)
+ return ret;
+
+ dell_fill_request(&buffer, 0x1, (acc_mode << 8) | BIT(state), 0, 0);
+ ret = dell_send_request(&buffer, CLASS_INFO, SELECT_THERMAL_MANAGEMENT);
+ return ret;
+}
+
+static int thermal_platform_profile_set(struct platform_profile_handler *pprof,
+ enum platform_profile_option profile)
+{
+ switch (profile) {
+ case PLATFORM_PROFILE_BALANCED:
+ return thermal_set_mode(DELL_BALANCED);
+ case PLATFORM_PROFILE_PERFORMANCE:
+ return thermal_set_mode(DELL_PERFORMANCE);
+ case PLATFORM_PROFILE_QUIET:
+ return thermal_set_mode(DELL_QUIET);
+ case PLATFORM_PROFILE_COOL:
+ return thermal_set_mode(DELL_COOL_BOTTOM);
+ default:
+ return -EOPNOTSUPP;
+ }
+}
+
+static int thermal_platform_profile_get(struct platform_profile_handler *pprof,
+ enum platform_profile_option *profile)
+{
+ int ret = thermal_get_mode();
+
+ if (ret < 0)
+ return ret;
+
+ switch (ret) {
+ case DELL_BALANCED:
+ *profile = PLATFORM_PROFILE_BALANCED;
+ break;
+ case DELL_PERFORMANCE:
+ *profile = PLATFORM_PROFILE_PERFORMANCE;
+ break;
+ case DELL_COOL_BOTTOM:
+ *profile = PLATFORM_PROFILE_COOL;
+ break;
+ case DELL_QUIET:
+ *profile = PLATFORM_PROFILE_QUIET;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+int thermal_init(void)
+{
+ int ret;
+ int supported_modes;
+
+ ret = thermal_get_supported_modes(&supported_modes);
+
+ if (ret || !supported_modes)
+ return 0;
+
+ thermal_handler = kzalloc(sizeof(*thermal_handler), GFP_KERNEL);
+ if (!thermal_handler)
+ return -ENOMEM;
+ thermal_handler->profile_get = thermal_platform_profile_get;
+ thermal_handler->profile_set = thermal_platform_profile_set;
+
+ if ((supported_modes >> DELL_QUIET) & 1)
+ set_bit(PLATFORM_PROFILE_QUIET, thermal_handler->choices);
+ if ((supported_modes >> DELL_COOL_BOTTOM) & 1)
+ set_bit(PLATFORM_PROFILE_COOL, thermal_handler->choices);
+ if ((supported_modes >> DELL_BALANCED) & 1)
+ set_bit(PLATFORM_PROFILE_BALANCED, thermal_handler->choices);
+ if ((supported_modes >> DELL_PERFORMANCE) & 1)
+ set_bit(PLATFORM_PROFILE_PERFORMANCE, thermal_handler->choices);
+
+ // Clean up but do not fail
+ if (platform_profile_register(thermal_handler))
+ kfree(thermal_handler);
+
+ return 0;
+}
+
+void thermal_cleanup(void)
+{
+ platform_profile_remove();
+ kfree(thermal_handler);
+}
+
static struct led_classdev mute_led_cdev = {
.name = "platform::mute",
.max_brightness = 1,
@@ -2238,6 +2452,12 @@ static int __init dell_init(void)
goto fail_rfkill;
}

+ // Do not fail module if thermal modes not supported,
+ // just skip
+ ret = thermal_init();
+ if (ret)
+ goto fail_thermal;
+
if (quirks && quirks->touchpad_led)
touchpad_led_init(&platform_device->dev);

@@ -2317,6 +2537,8 @@ static int __init dell_init(void)
led_classdev_unregister(&mute_led_cdev);
fail_led:
dell_cleanup_rfkill();
+fail_thermal:
+ thermal_cleanup();
fail_rfkill:
platform_device_del(platform_device);
fail_platform_device2:
@@ -2344,6 +2566,7 @@ static void __exit dell_exit(void)
platform_device_unregister(platform_device);
platform_driver_unregister(&platform_driver);
}
+ thermal_cleanup();
}

/* dell-rbtn.c driver export functions which will not work correctly (and could
diff --git a/drivers/platform/x86/dell/dell-smbios.h b/drivers/platform/x86/dell/dell-smbios.h
index eb341bf000c6..585d042f1779 100644
--- a/drivers/platform/x86/dell/dell-smbios.h
+++ b/drivers/platform/x86/dell/dell-smbios.h
@@ -19,6 +19,7 @@
/* Classes and selects used only in kernel drivers */
#define CLASS_KBD_BACKLIGHT 4
#define SELECT_KBD_BACKLIGHT 11
+#define SELECT_THERMAL_MANAGEMENT 19

/* Tokens used in kernel drivers, any of these
* should be filtered from userspace access
--
2.42.0


2024-04-26 06:57:22

by Ilpo Järvinen

[permalink] [raw]
Subject: Re: [PATCH] platform/x86: dell-laptop: Implement platform_profile

On Thu, 25 Apr 2024, Lyndon Sanche wrote:

> Some Dell laptops support configuration of preset
> fan modes through smbios tables.
>
> If the platform supports these fan modes, set up
> platform_profile to change these modes. If not
> supported, skip enabling platform_profile.

These are too short lines, wrap at 72 (or 75) characters.

> Signed-off-by: Lyndon Sanche <[email protected]>
> ---
> drivers/platform/x86/dell/dell-laptop.c | 220 ++++++++++++++++++++++++
> drivers/platform/x86/dell/dell-smbios.h | 1 +
> 2 files changed, 221 insertions(+)
>
> diff --git a/drivers/platform/x86/dell/dell-laptop.c b/drivers/platform/x86/dell/dell-laptop.c
> index 42f7de2b4522..7f9c4e0e5ef5 100644
> --- a/drivers/platform/x86/dell/dell-laptop.c
> +++ b/drivers/platform/x86/dell/dell-laptop.c
> @@ -27,6 +27,7 @@
> #include <linux/i8042.h>
> #include <linux/debugfs.h>
> #include <linux/seq_file.h>
> +#include <linux/platform_profile.h>
> #include <acpi/video.h>
> #include "dell-rbtn.h"
> #include "dell-smbios.h"
> @@ -95,10 +96,18 @@ static struct backlight_device *dell_backlight_device;
> static struct rfkill *wifi_rfkill;
> static struct rfkill *bluetooth_rfkill;
> static struct rfkill *wwan_rfkill;
> +static struct platform_profile_handler *thermal_handler;
> static bool force_rfkill;
> static bool micmute_led_registered;
> static bool mute_led_registered;
>
> +enum thermal_mode_bits {
> + DELL_BALANCED = 0,
> + DELL_COOL_BOTTOM = 1,
> + DELL_QUIET = 2,
> + DELL_PERFORMANCE = 3,
> +};

It would seem more more natural to define these with BIT(x) as that's how
they're used in the code below?

> module_param(force_rfkill, bool, 0444);
> MODULE_PARM_DESC(force_rfkill, "enable rfkill on non whitelisted models");
>
> @@ -2199,6 +2208,211 @@ static int mute_led_set(struct led_classdev *led_cdev,
> return 0;
> }
>
> +// Derived from smbios-thermal-ctl
> +//
> +// cbClass 17
> +// cbSelect 19
> +// User Selectable Thermal Tables(USTT)
> +// cbArg1 determines the function to be performed
> +// cbArg1 0x0 = Get Thermal Information
> +// cbRES1 Standard return codes (0, -1, -2)
> +// cbRES2, byte 0 Bitmap of supported thermal modes. A mode is supported if its bit is set to 1
> +// Bit 0 Balanced
> +// Bit 1 Cool Bottom
> +// Bit 2 Quiet
> +// Bit 3 Performance
> +// cbRES2, byte 1 Bitmap of supported Active Acoustic Controller (AAC) modes. Each mode
> +// corresponds to the supported thermal modes in byte 0. A mode is supported if
> +// its bit is set to 1.
> +// Bit 0 AAC (Balanced)
> +// Bit 1 AAC (Cool Bottom
> +// Bit 2 AAC (Quiet)
> +// Bit 3 AAC (Performance)
> +// cbRes3, byte 0 Current Thermal Mode
> +// Bit 0 Balanced
> +// Bit 1 Cool Bottom
> +// Bit 2 Quiet
> +// Bit 3 Performanc
> +// cbRes3, byte 1 AAC Configuration type
> +// 0 Global (AAC enable/disable applies to all supported USTT modes)
> +// 1 USTT mode specific
> +// cbRes3, byte 2 Current Active Acoustic Controller (AAC) Mode
> +// If AAC Configuration Type is Global,
> +// 0 AAC mode disabled
> +// 1 AAC mode enabled
> +// If AAC Configuration Type is USTT mode specific (multiple bits may be set),
> +// Bit 0 AAC (Balanced)
> +// Bit 1 AAC (Cool Bottom
> +// Bit 2 AAC (Quiet)
> +// Bit 3 AAC (Performance)
> +// cbRes3, byte 3 Current Fan Failure Mode
> +// Bit 0 Minimal Fan Failure (at least one fan has failed, one fan working)
> +// Bit 1 Catastrophic Fan Failure (all fans have failed)
> +// cbArg1 0x1 (Set Thermal Information), both desired thermal mode and
> +// desired AAC mode shall be applied
> +// cbArg2, byte 0 Desired Thermal Mode to set (only one bit may be set for this parameter)
> +// Bit 0 Balanced
> +// Bit 1 Cool Bottom
> +// Bit 2 Quiet
> +// Bit 3 Performance
> +// cbArg2, byte 1 Desired Active Acoustic Controller (AAC) Mode to set
> +// If AAC Configuration Type is Global,
> +// 0 AAC mode disabled
> +// 1 AAC mode enabled
> +//
> +// If AAC Configuration Type is USTT mode specific (multiple bits may be set for this parameter),
> +// Bit 0 AAC (Balanced)
> +// Bit 1 AAC (Cool Bottom
> +// Bit 2 AAC (Quiet)
> +// Bit 3 AAC (Performance)

Please use

/*
*
*/

format for multiline comments.

Don't exceed 80 characters with comments.

> +static int thermal_get_mode(void)
> +{
> + struct calling_interface_buffer buffer;
> + int state;
> + int ret;
> +
> + dell_fill_request(&buffer, 0x0, 0, 0, 0);
> + ret = dell_send_request(&buffer, CLASS_INFO, SELECT_THERMAL_MANAGEMENT);
> + if (ret)
> + return ret;
> + state = buffer.output[2];
> + if ((state >> DELL_BALANCED) & 1)
> + return DELL_BALANCED;
> + else if ((state >> DELL_COOL_BOTTOM) & 1)
> + return DELL_COOL_BOTTOM;
> + else if ((state >> DELL_QUIET) & 1)
> + return DELL_QUIET;
> + else if ((state >> DELL_PERFORMANCE) & 1)
> + return DELL_PERFORMANCE;

When you convert defines to use BIT(), these become simpler.

> + else
> + return 0;
> +}
> +
> +static int thermal_get_supported_modes(int *supported_bits)
> +{
> + struct calling_interface_buffer buffer;
> + int ret;
> +
> + dell_fill_request(&buffer, 0x0, 0, 0, 0);
> + ret = dell_send_request(&buffer, CLASS_INFO, SELECT_THERMAL_MANAGEMENT);
> + if (ret)
> + return ret;
> + *supported_bits = buffer.output[1] & 0xF;

Add named define + use FIELD_GET() + add #include <linux/bitfield.h> if
not there already.

> + return 0;
> +}
> +
> +static int thermal_get_acc_mode(int *acc_mode)
> +{
> + struct calling_interface_buffer buffer;
> + int ret;
> +
> + dell_fill_request(&buffer, 0x0, 0, 0, 0);
> + ret = dell_send_request(&buffer, CLASS_INFO, SELECT_THERMAL_MANAGEMENT);
> + if (ret)
> + return ret;
> + *acc_mode = ((buffer.output[3] >> 8) & 0xFF);

Use named define + FIELD_GET()

> + return 0;
> +}
> +
> +static int thermal_set_mode(enum thermal_mode_bits state)
> +{
> + struct calling_interface_buffer buffer;
> + int ret;
> + int acc_mode;
> +
> + ret = thermal_get_acc_mode(&acc_mode);
> + if (ret)
> + return ret;
> +
> + dell_fill_request(&buffer, 0x1, (acc_mode << 8) | BIT(state), 0, 0);

Named define + FIELD_PREP(XX, acc_mode)

After converting the enum values to use BIT(), you can remove BIT() from
here.

> + ret = dell_send_request(&buffer, CLASS_INFO, SELECT_THERMAL_MANAGEMENT);
> + return ret;
> +}
> +
> +static int thermal_platform_profile_set(struct platform_profile_handler *pprof,
> + enum platform_profile_option profile)
> +{
> + int ret;
> +
> + switch (profile) {
> + case PLATFORM_PROFILE_BALANCED:
> + ret = thermal_set_mode(DELL_BALANCED);
> + break;
> + case PLATFORM_PROFILE_PERFORMANCE:
> + ret = thermal_set_mode(DELL_PERFORMANCE);
> + break;
> + case PLATFORM_PROFILE_QUIET:
> + ret = thermal_set_mode(DELL_QUIET);
> + break;
> + case PLATFORM_PROFILE_COOL:
> + ret = thermal_set_mode(DELL_COOL_BOTTOM);
> + break;
> + default:
> + return -EOPNOTSUPP;
> + }
> +
> + return ret;
> +}
> +
> +static int thermal_platform_profile_get(struct platform_profile_handler *pprof,
> + enum platform_profile_option *profile)
> +{
> + switch (thermal_get_mode()) {
> + case DELL_BALANCED:
> + *profile = PLATFORM_PROFILE_BALANCED;
> + break;
> + case DELL_PERFORMANCE:
> + *profile = PLATFORM_PROFILE_PERFORMANCE;
> + break;
> + case DELL_COOL_BOTTOM:
> + *profile = PLATFORM_PROFILE_COOL;
> + break;
> + case DELL_QUIET:
> + *profile = PLATFORM_PROFILE_QUIET;
> + break;
> + default:
> + return -EINVAL;
> + }
> +
> + return 0;
> +}
> +
> +int thermal_init(void)
> +{
> + int ret;
> + int supported_modes;
> +
> + ret = thermal_get_supported_modes(&supported_modes);
> +
> + if (ret != 0 || supported_modes == 0)

Don't leave empty lines between call and its error handling.

> + return -ENXIO;
> +
> + thermal_handler = kzalloc(sizeof(*thermal_handler), GFP_KERNEL);
> + if (!thermal_handler)
> + return -ENOMEM;
> + thermal_handler->profile_get = thermal_platform_profile_get;
> + thermal_handler->profile_set = thermal_platform_profile_set;
> +
> + if ((supported_modes >> DELL_QUIET) & 1)
> + set_bit(PLATFORM_PROFILE_QUIET, thermal_handler->choices);
> + if ((supported_modes >> DELL_COOL_BOTTOM) & 1)
> + set_bit(PLATFORM_PROFILE_COOL, thermal_handler->choices);
> + if ((supported_modes >> DELL_BALANCED) & 1)
> + set_bit(PLATFORM_PROFILE_BALANCED, thermal_handler->choices);
> + if ((supported_modes >> DELL_PERFORMANCE) & 1)

These too will get simpler when the values are using BIT().

> + set_bit(PLATFORM_PROFILE_PERFORMANCE, thermal_handler->choices);
> +
> + platform_profile_register(thermal_handler);
> +
> + return 0;
> +}
> +
> +void thermal_cleanup(void)
> +{
> + platform_profile_remove();

This should be called if thermal_init() failed, sysfs_remove_group() will
be called for a group that was never created and I don't think that's
okay.

> + kfree(thermal_handler);
> +}
> +
> static struct led_classdev mute_led_cdev = {
> .name = "platform::mute",
> .max_brightness = 1,
> @@ -2266,6 +2480,11 @@ static int __init dell_init(void)
> mute_led_registered = true;
> }
>
> + // Do not fail module if thermal modes not supported,
> + // just skip

Fits to one line.

> + if (thermal_init() != 0)
> + pr_warn("Unable to setup platform_profile, skipping");
> +
> if (acpi_video_get_backlight_type() != acpi_backlight_vendor)
> return 0;
>
> @@ -2344,6 +2563,7 @@ static void __exit dell_exit(void)
> platform_device_unregister(platform_device);
> platform_driver_unregister(&platform_driver);
> }
> + thermal_cleanup();
> }
>
> /* dell-rbtn.c driver export functions which will not work correctly (and could
> diff --git a/drivers/platform/x86/dell/dell-smbios.h b/drivers/platform/x86/dell/dell-smbios.h
> index eb341bf000c6..585d042f1779 100644
> --- a/drivers/platform/x86/dell/dell-smbios.h
> +++ b/drivers/platform/x86/dell/dell-smbios.h
> @@ -19,6 +19,7 @@
> /* Classes and selects used only in kernel drivers */
> #define CLASS_KBD_BACKLIGHT 4
> #define SELECT_KBD_BACKLIGHT 11
> +#define SELECT_THERMAL_MANAGEMENT 19
>
> /* Tokens used in kernel drivers, any of these
> * should be filtered from userspace access
>

--
i.


2024-04-26 09:23:17

by Ilpo Järvinen

[permalink] [raw]
Subject: Re: [PATCH v2] platform/x86: dell-laptop: Implement platform_profile

On Thu, 25 Apr 2024, Lyndon Sanche wrote:

> Some Dell laptops support configuration of preset
> fan modes through smbios tables.
>
> If the platform supports these fan modes, set up
> platform_profile to change these modes. If not
> supported, skip enabling platform_profile.
>
> Signed-off-by: Lyndon Sanche <[email protected]>
> ---

Two things:
- You're missing patch version history (put it below the --- line)
- Don't send updates so soon, give people time to comment. When I saw v1
for the first time, you had already posted the next version.

> +void thermal_cleanup(void)
> +{
> + platform_profile_remove();
> + kfree(thermal_handler);
> +}
> +
> static struct led_classdev mute_led_cdev = {
> .name = "platform::mute",
> .max_brightness = 1,
> @@ -2238,6 +2452,12 @@ static int __init dell_init(void)
> goto fail_rfkill;
> }
>
> + // Do not fail module if thermal modes not supported,
> + // just skip
> + ret = thermal_init();
> + if (ret)
> + goto fail_thermal;
> +
> if (quirks && quirks->touchpad_led)
> touchpad_led_init(&platform_device->dev);
>
> @@ -2317,6 +2537,8 @@ static int __init dell_init(void)
> led_classdev_unregister(&mute_led_cdev);
> fail_led:
> dell_cleanup_rfkill();
> +fail_thermal:
> + thermal_cleanup();
> fail_rfkill:
> platform_device_del(platform_device);
> fail_platform_device2:
> @@ -2344,6 +2566,7 @@ static void __exit dell_exit(void)
> platform_device_unregister(platform_device);
> platform_driver_unregister(&platform_driver);
> }
> + thermal_cleanup();

This is still not right, you'll still platform_profile_remove() even if
the init side call failed.

--
i.


2024-04-26 18:06:02

by Lyndon Sanche

[permalink] [raw]
Subject: Re: [PATCH v2] platform/x86: dell-laptop: Implement platform_profile



On Fri, Apr 26 2024 at 12:23:00 PM +03:00:00, Ilpo J?rvinen
<[email protected]> wrote:
> On Thu, 25 Apr 2024, Lyndon Sanche wrote:
>
>> Some Dell laptops support configuration of preset
>> fan modes through smbios tables.
>>
>> If the platform supports these fan modes, set up
>> platform_profile to change these modes. If not
>> supported, skip enabling platform_profile.
>>
>> Signed-off-by: Lyndon Sanche <[email protected]>
>> ---
>
> Two things:
> - You're missing patch version history (put it below the --- line)
> - Don't send updates so soon, give people time to comment. When I saw
> v1
> for the first time, you had already posted the next version.
>
>> +void thermal_cleanup(void)
>> +{
>> + platform_profile_remove();
>> + kfree(thermal_handler);
>> +}
>> +
>> static struct led_classdev mute_led_cdev = {
>> .name = "platform::mute",
>> .max_brightness = 1,
>> @@ -2238,6 +2452,12 @@ static int __init dell_init(void)
>> goto fail_rfkill;
>> }
>>
>> + // Do not fail module if thermal modes not supported,
>> + // just skip
>> + ret = thermal_init();
>> + if (ret)
>> + goto fail_thermal;
>> +
>> if (quirks && quirks->touchpad_led)
>> touchpad_led_init(&platform_device->dev);
>>
>> @@ -2317,6 +2537,8 @@ static int __init dell_init(void)
>> led_classdev_unregister(&mute_led_cdev);
>> fail_led:
>> dell_cleanup_rfkill();
>> +fail_thermal:
>> + thermal_cleanup();
>> fail_rfkill:
>> platform_device_del(platform_device);
>> fail_platform_device2:
>> @@ -2344,6 +2566,7 @@ static void __exit dell_exit(void)
>> platform_device_unregister(platform_device);
>> platform_driver_unregister(&platform_driver);
>> }
>> + thermal_cleanup();
>
> This is still not right, you'll still platform_profile_remove() even
> if
> the init side call failed.
>
> --
> i.
>

Thank you for your feedback. I agree with your comments and will add
more checking on whether certain cleanup actions are necessary.

Lyndon



2024-04-26 18:23:36

by Lyndon Sanche

[permalink] [raw]
Subject: Re: [PATCH] platform/x86: dell-laptop: Implement platform_profile



On Fri, Apr 26 2024 at 09:14:07 AM -07:00:00, srinivas pandruvada
<[email protected]> wrote:
>> Can you share output of acpidump tool to me? I want to make sure if
> there is some way the platform will bypass thermal table if you
> changed
> to some profile.
>
> Thanks,
> Srinivas

Hello Srinivas:

I used acpidump. For sake of completeness I ran acpidump with each of
the thermal modes enabled. The files are too large to provide here so I
uploaded them to a public gist:
https://gist.github.com/Lyndeno/65ade5a15f1f2cd07175256dc021f551

Please let me know if there is a more appropriate medium for sharing
files like this, and I will remember for next time.

Thank you,

Lyndon



2024-04-26 18:25:08

by srinivas pandruvada

[permalink] [raw]
Subject: Re: [PATCH] platform/x86: dell-laptop: Implement platform_profile

On Fri, 2024-04-26 at 12:23 -0600, Lyndon Sanche wrote:
>
>
> On Fri, Apr 26 2024 at 09:14:07 AM -07:00:00, srinivas pandruvada
> <[email protected]> wrote:
> > > Can you share output of acpidump tool to me? I want to make sure
> > > if
> > there is some way the platform will bypass thermal table if you
> > changed
> > to some profile.
> >
> > Thanks,
> > Srinivas
>
> Hello Srinivas:
>
> I used acpidump. For sake of completeness I ran acpidump with each of
> the thermal modes enabled. The files are too large to provide here so
> I
> uploaded them to a public gist:
> https://gist.github.com/Lyndeno/65ade5a15f1f2cd07175256dc021f551
>
> Please let me know if there is a more appropriate medium for sharing
> files like this, and I will remember for next time.

This is fine. Thanks for uploading.

-Srinivas

>
> Thank you,
>
> Lyndon
>
>


2024-04-26 20:17:15

by srinivas pandruvada

[permalink] [raw]
Subject: Re: [PATCH] platform/x86: dell-laptop: Implement platform_profile

On Thu, 2024-04-25 at 14:24 -0600, Lyndon Sanche wrote:
> On Thu, Apr 25, 2024, at 2:07 PM, Mario Limonciello wrote:
> > + Srinivas
> >
> > On 4/25/2024 12:27, Lyndon Sanche wrote:
> > > Some Dell laptops support configuration of preset
> > > fan modes through smbios tables.
> > >
> > > If the platform supports these fan modes, set up
> > > platform_profile to change these modes. If not
> > > supported, skip enabling platform_profile.
> > >
> > > Signed-off-by: Lyndon Sanche <[email protected]>
> > > ---
> >
> > When you developed this was it using a Dell Intel or Dell AMD
> > system?
> >
> > If it was an Intel system, did you test it with thermald installed
> > and
> > active?
> >
> > I'm wondering how all this stuff jives with the stuff that thermald
> > does.  I don't know if they fight for any of the same "resources".
>
> Thank you for your response.
>
> I did my development and testing on a Dell Intel system. Specifically
> the XPS 15 9560 with i7-7700HQ.
>
> I do have thermald running, though I admit I am not really aware of
> what exactly it does, besides being related to thermals in some way.
>
> I normally set the thermal mode with Dell's smbios-thermal-ctl
> program. I am not too sure all the values that the bios configures on
> it's own depending on the provided mode, so I am not sure if thermald
> conflicts. But my understanding is that would be out of scope of this
> driver, since we are only telling the bios what we want at a high
> level.
>
> Lyndon
Can you share output of acpidump tool to me? I want to make sure if
there is some way the platform will bypass thermal table if you changed
to some profile.

Thanks,
Srinivas

2024-04-29 16:59:16

by Lyndon Sanche

[permalink] [raw]
Subject: [PATCH v3] platform/x86: dell-laptop: Implement platform_profile

Some Dell laptops support configuration of preset fan modes through
smbios tables.

If the platform supports these fan modes, set up platform_profile to
change these modes. If not supported, skip enabling platform_profile.

Signed-off-by: Lyndon Sanche <[email protected]>
---
v3:
- Convert smbios-thermal-ctl docs to multiline comment and wrap
- Change thermal_mode_bits enum to directly be BIT() values
- Convert related code to use this
- Use FIELD_GET/PREP and GENNMASK for getting/setting thermal modes
- Correct offset for getting current ACC mode, setting offset
unchanged
- Check if thermal_handler is allocated before freeing and
unregistering platform_profile
v2:
- Wrap smbios-thermal-ctl comment
- Return proper error code when invalid state returned
- Simplify platform_profile_get returns
- Propogate ENOMEM error
---
drivers/platform/x86/dell/dell-laptop.c | 232 ++++++++++++++++++++++++
drivers/platform/x86/dell/dell-smbios.h | 1 +
2 files changed, 233 insertions(+)

diff --git a/drivers/platform/x86/dell/dell-laptop.c b/drivers/platform/x86/dell/dell-laptop.c
index 42f7de2b4522..fa58e7751d06 100644
--- a/drivers/platform/x86/dell/dell-laptop.c
+++ b/drivers/platform/x86/dell/dell-laptop.c
@@ -27,6 +27,8 @@
#include <linux/i8042.h>
#include <linux/debugfs.h>
#include <linux/seq_file.h>
+#include <linux/platform_profile.h>
+#include <linux/bitfield.h>
#include <acpi/video.h>
#include "dell-rbtn.h"
#include "dell-smbios.h"
@@ -95,6 +97,7 @@ static struct backlight_device *dell_backlight_device;
static struct rfkill *wifi_rfkill;
static struct rfkill *bluetooth_rfkill;
static struct rfkill *wwan_rfkill;
+static struct platform_profile_handler *thermal_handler;
static bool force_rfkill;
static bool micmute_led_registered;
static bool mute_led_registered;
@@ -2199,6 +2202,227 @@ static int mute_led_set(struct led_classdev *led_cdev,
return 0;
}

+/* Derived from smbios-thermal-ctl
+ *
+ * cbClass 17
+ * cbSelect 19
+ * User Selectable Thermal Tables(USTT)
+ * cbArg1 determines the function to be performed
+ * cbArg1 0x0 = Get Thermal Information
+ * cbRES1 Standard return codes (0, -1, -2)
+ * cbRES2, byte 0 Bitmap of supported thermal modes. A mode is supported if
+ * its bit is set to 1
+ * Bit 0 Balanced
+ * Bit 1 Cool Bottom
+ * Bit 2 Quiet
+ * Bit 3 Performance
+ * cbRES2, byte 1 Bitmap of supported Active Acoustic Controller (AAC) modes.
+ * Each mode corresponds to the supported thermal modes in
+ * byte 0. A mode is supported if its bit is set to 1.
+ * Bit 0 AAC (Balanced)
+ * Bit 1 AAC (Cool Bottom
+ * Bit 2 AAC (Quiet)
+ * Bit 3 AAC (Performance)
+ * cbRes3, byte 0 Current Thermal Mode
+ * Bit 0 Balanced
+ * Bit 1 Cool Bottom
+ * Bit 2 Quiet
+ * Bit 3 Performanc
+ * cbRes3, byte 1 AAC Configuration type
+ * 0 Global (AAC enable/disable applies to all supported USTT modes)
+ * 1 USTT mode specific
+ * cbRes3, byte 2 Current Active Acoustic Controller (AAC) Mode
+ * If AAC Configuration Type is Global,
+ * 0 AAC mode disabled
+ * 1 AAC mode enabled
+ * If AAC Configuration Type is USTT mode specific (multiple bits may be set),
+ * Bit 0 AAC (Balanced)
+ * Bit 1 AAC (Cool Bottom
+ * Bit 2 AAC (Quiet)
+ * Bit 3 AAC (Performance)
+ * cbRes3, byte 3 Current Fan Failure Mode
+ * Bit 0 Minimal Fan Failure (at least one fan has failed, one fan working)
+ * Bit 1 Catastrophic Fan Failure (all fans have failed)
+ * cbArg1 0x1 (Set Thermal Information), both desired thermal mode and
+ * desired AAC mode shall be applied
+ * cbArg2, byte 0 Desired Thermal Mode to set
+ * (only one bit may be set for this parameter)
+ * Bit 0 Balanced
+ * Bit 1 Cool Bottom
+ * Bit 2 Quiet
+ * Bit 3 Performance
+ * cbArg2, byte 1 Desired Active Acoustic Controller (AAC) Mode to set
+ * If AAC Configuration Type is Global,
+ * 0 AAC mode disabled
+ * 1 AAC mode enabled
+ *
+ * If AAC Configuration Type is USTT mode specific
+ * (multiple bits may be set for this parameter),
+ * Bit 0 AAC (Balanced)
+ * Bit 1 AAC (Cool Bottom
+ * Bit 2 AAC (Quiet)
+ * Bit 3 AAC (Performance)
+ */
+
+#define DELL_ACC_GET_FIELD GENMASK(19, 16)
+#define DELL_ACC_SET_FIELD GENMASK(11, 8)
+#define DELL_THERMAL_SUPPORTED GENMASK(3, 0)
+
+enum thermal_mode_bits {
+ DELL_BALANCED = BIT(0),
+ DELL_COOL_BOTTOM = BIT(1),
+ DELL_QUIET = BIT(2),
+ DELL_PERFORMANCE = BIT(3),
+};
+
+static int thermal_get_mode(void)
+{
+ struct calling_interface_buffer buffer;
+ int state;
+ int ret;
+
+ dell_fill_request(&buffer, 0x0, 0, 0, 0);
+ ret = dell_send_request(&buffer, CLASS_INFO, SELECT_THERMAL_MANAGEMENT);
+ if (ret)
+ return ret;
+ state = buffer.output[2];
+ if (state & DELL_BALANCED)
+ return DELL_BALANCED;
+ else if (state & DELL_COOL_BOTTOM)
+ return DELL_COOL_BOTTOM;
+ else if (state & DELL_QUIET)
+ return DELL_QUIET;
+ else if (state & DELL_PERFORMANCE)
+ return DELL_PERFORMANCE;
+ else
+ return -ENXIO;
+}
+
+static int thermal_get_supported_modes(int *supported_bits)
+{
+ struct calling_interface_buffer buffer;
+ int ret;
+
+ dell_fill_request(&buffer, 0x0, 0, 0, 0);
+ ret = dell_send_request(&buffer, CLASS_INFO, SELECT_THERMAL_MANAGEMENT);
+ if (ret)
+ return ret;
+ *supported_bits = FIELD_GET(DELL_THERMAL_SUPPORTED, buffer.output[1]);
+ return 0;
+}
+
+static int thermal_get_acc_mode(int *acc_mode)
+{
+ struct calling_interface_buffer buffer;
+ int ret;
+
+ dell_fill_request(&buffer, 0x0, 0, 0, 0);
+ ret = dell_send_request(&buffer, CLASS_INFO, SELECT_THERMAL_MANAGEMENT);
+ if (ret)
+ return ret;
+ *acc_mode = FIELD_GET(DELL_ACC_GET_FIELD, buffer.output[3]);
+ return 0;
+}
+
+static int thermal_set_mode(enum thermal_mode_bits state)
+{
+ struct calling_interface_buffer buffer;
+ int ret;
+ int acc_mode;
+
+ ret = thermal_get_acc_mode(&acc_mode);
+ if (ret)
+ return ret;
+
+ dell_fill_request(&buffer, 0x1, FIELD_PREP(DELL_ACC_SET_FIELD, acc_mode) | state, 0, 0);
+ ret = dell_send_request(&buffer, CLASS_INFO, SELECT_THERMAL_MANAGEMENT);
+ return ret;
+}
+
+static int thermal_platform_profile_set(struct platform_profile_handler *pprof,
+ enum platform_profile_option profile)
+{
+ switch (profile) {
+ case PLATFORM_PROFILE_BALANCED:
+ return thermal_set_mode(DELL_BALANCED);
+ case PLATFORM_PROFILE_PERFORMANCE:
+ return thermal_set_mode(DELL_PERFORMANCE);
+ case PLATFORM_PROFILE_QUIET:
+ return thermal_set_mode(DELL_QUIET);
+ case PLATFORM_PROFILE_COOL:
+ return thermal_set_mode(DELL_COOL_BOTTOM);
+ default:
+ return -EOPNOTSUPP;
+ }
+}
+
+static int thermal_platform_profile_get(struct platform_profile_handler *pprof,
+ enum platform_profile_option *profile)
+{
+ int ret = thermal_get_mode();
+
+ if (ret < 0)
+ return ret;
+
+ switch (ret) {
+ case DELL_BALANCED:
+ *profile = PLATFORM_PROFILE_BALANCED;
+ break;
+ case DELL_PERFORMANCE:
+ *profile = PLATFORM_PROFILE_PERFORMANCE;
+ break;
+ case DELL_COOL_BOTTOM:
+ *profile = PLATFORM_PROFILE_COOL;
+ break;
+ case DELL_QUIET:
+ *profile = PLATFORM_PROFILE_QUIET;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+int thermal_init(void)
+{
+ int ret;
+ int supported_modes;
+
+ ret = thermal_get_supported_modes(&supported_modes);
+ if (ret || !supported_modes)
+ return 0;
+
+ thermal_handler = kzalloc(sizeof(*thermal_handler), GFP_KERNEL);
+ if (!thermal_handler)
+ return -ENOMEM;
+ thermal_handler->profile_get = thermal_platform_profile_get;
+ thermal_handler->profile_set = thermal_platform_profile_set;
+
+ if (supported_modes & DELL_QUIET)
+ set_bit(PLATFORM_PROFILE_QUIET, thermal_handler->choices);
+ if (supported_modes & DELL_COOL_BOTTOM)
+ set_bit(PLATFORM_PROFILE_COOL, thermal_handler->choices);
+ if (supported_modes & DELL_BALANCED)
+ set_bit(PLATFORM_PROFILE_BALANCED, thermal_handler->choices);
+ if (supported_modes & DELL_PERFORMANCE)
+ set_bit(PLATFORM_PROFILE_PERFORMANCE, thermal_handler->choices);
+
+ // Clean up but do not fail
+ if (platform_profile_register(thermal_handler))
+ kfree(thermal_handler);
+
+ return 0;
+}
+
+void thermal_cleanup(void)
+{
+ if (thermal_handler) {
+ platform_profile_remove();
+ kfree(thermal_handler);
+ }
+}
+
static struct led_classdev mute_led_cdev = {
.name = "platform::mute",
.max_brightness = 1,
@@ -2238,6 +2462,11 @@ static int __init dell_init(void)
goto fail_rfkill;
}

+ // Do not fail module if thermal modes not supported, just skip
+ ret = thermal_init();
+ if (ret)
+ goto fail_thermal;
+
if (quirks && quirks->touchpad_led)
touchpad_led_init(&platform_device->dev);

@@ -2317,6 +2546,8 @@ static int __init dell_init(void)
led_classdev_unregister(&mute_led_cdev);
fail_led:
dell_cleanup_rfkill();
+fail_thermal:
+ thermal_cleanup();
fail_rfkill:
platform_device_del(platform_device);
fail_platform_device2:
@@ -2344,6 +2575,7 @@ static void __exit dell_exit(void)
platform_device_unregister(platform_device);
platform_driver_unregister(&platform_driver);
}
+ thermal_cleanup();
}

/* dell-rbtn.c driver export functions which will not work correctly (and could
diff --git a/drivers/platform/x86/dell/dell-smbios.h b/drivers/platform/x86/dell/dell-smbios.h
index eb341bf000c6..585d042f1779 100644
--- a/drivers/platform/x86/dell/dell-smbios.h
+++ b/drivers/platform/x86/dell/dell-smbios.h
@@ -19,6 +19,7 @@
/* Classes and selects used only in kernel drivers */
#define CLASS_KBD_BACKLIGHT 4
#define SELECT_KBD_BACKLIGHT 11
+#define SELECT_THERMAL_MANAGEMENT 19

/* Tokens used in kernel drivers, any of these
* should be filtered from userspace access
--
2.42.0


2024-04-29 17:45:59

by Mario Limonciello

[permalink] [raw]
Subject: Re: [PATCH v3] platform/x86: dell-laptop: Implement platform_profile

On 4/29/2024 11:48, Lyndon Sanche wrote:
> Some Dell laptops support configuration of preset fan modes through
> smbios tables.
>
> If the platform supports these fan modes, set up platform_profile to
> change these modes. If not supported, skip enabling platform_profile.
>
> Signed-off-by: Lyndon Sanche <[email protected]>
> ---
> v3:
> - Convert smbios-thermal-ctl docs to multiline comment and wrap
> - Change thermal_mode_bits enum to directly be BIT() values
> - Convert related code to use this
> - Use FIELD_GET/PREP and GENNMASK for getting/setting thermal modes
> - Correct offset for getting current ACC mode, setting offset
> unchanged
> - Check if thermal_handler is allocated before freeing and
> unregistering platform_profile
> v2:
> - Wrap smbios-thermal-ctl comment
> - Return proper error code when invalid state returned
> - Simplify platform_profile_get returns
> - Propogate ENOMEM error
> ---
> drivers/platform/x86/dell/dell-laptop.c | 232 ++++++++++++++++++++++++
> drivers/platform/x86/dell/dell-smbios.h | 1 +
> 2 files changed, 233 insertions(+)
>
> diff --git a/drivers/platform/x86/dell/dell-laptop.c b/drivers/platform/x86/dell/dell-laptop.c
> index 42f7de2b4522..fa58e7751d06 100644
> --- a/drivers/platform/x86/dell/dell-laptop.c
> +++ b/drivers/platform/x86/dell/dell-laptop.c
> @@ -27,6 +27,8 @@
> #include <linux/i8042.h>
> #include <linux/debugfs.h>
> #include <linux/seq_file.h>
> +#include <linux/platform_profile.h>
> +#include <linux/bitfield.h>

These should be inserted in alphabetical order.

> #include <acpi/video.h>
> #include "dell-rbtn.h"
> #include "dell-smbios.h"
> @@ -95,6 +97,7 @@ static struct backlight_device *dell_backlight_device;
> static struct rfkill *wifi_rfkill;
> static struct rfkill *bluetooth_rfkill;
> static struct rfkill *wwan_rfkill;
> +static struct platform_profile_handler *thermal_handler;
> static bool force_rfkill;
> static bool micmute_led_registered;
> static bool mute_led_registered;
> @@ -2199,6 +2202,227 @@ static int mute_led_set(struct led_classdev *led_cdev,
> return 0;
> }
>
> +/* Derived from smbios-thermal-ctl
> + *
> + * cbClass 17
> + * cbSelect 19
> + * User Selectable Thermal Tables(USTT)
> + * cbArg1 determines the function to be performed
> + * cbArg1 0x0 = Get Thermal Information
> + * cbRES1 Standard return codes (0, -1, -2)
> + * cbRES2, byte 0 Bitmap of supported thermal modes. A mode is supported if
> + * its bit is set to 1
> + * Bit 0 Balanced
> + * Bit 1 Cool Bottom
> + * Bit 2 Quiet
> + * Bit 3 Performance
> + * cbRES2, byte 1 Bitmap of supported Active Acoustic Controller (AAC) modes.
> + * Each mode corresponds to the supported thermal modes in
> + * byte 0. A mode is supported if its bit is set to 1.
> + * Bit 0 AAC (Balanced)
> + * Bit 1 AAC (Cool Bottom
> + * Bit 2 AAC (Quiet)
> + * Bit 3 AAC (Performance)
> + * cbRes3, byte 0 Current Thermal Mode
> + * Bit 0 Balanced
> + * Bit 1 Cool Bottom
> + * Bit 2 Quiet
> + * Bit 3 Performanc
> + * cbRes3, byte 1 AAC Configuration type
> + * 0 Global (AAC enable/disable applies to all supported USTT modes)
> + * 1 USTT mode specific
> + * cbRes3, byte 2 Current Active Acoustic Controller (AAC) Mode
> + * If AAC Configuration Type is Global,
> + * 0 AAC mode disabled
> + * 1 AAC mode enabled
> + * If AAC Configuration Type is USTT mode specific (multiple bits may be set),
> + * Bit 0 AAC (Balanced)
> + * Bit 1 AAC (Cool Bottom
> + * Bit 2 AAC (Quiet)
> + * Bit 3 AAC (Performance)
> + * cbRes3, byte 3 Current Fan Failure Mode
> + * Bit 0 Minimal Fan Failure (at least one fan has failed, one fan working)
> + * Bit 1 Catastrophic Fan Failure (all fans have failed)
> + * cbArg1 0x1 (Set Thermal Information), both desired thermal mode and
> + * desired AAC mode shall be applied
> + * cbArg2, byte 0 Desired Thermal Mode to set
> + * (only one bit may be set for this parameter)
> + * Bit 0 Balanced
> + * Bit 1 Cool Bottom
> + * Bit 2 Quiet
> + * Bit 3 Performance
> + * cbArg2, byte 1 Desired Active Acoustic Controller (AAC) Mode to set
> + * If AAC Configuration Type is Global,
> + * 0 AAC mode disabled
> + * 1 AAC mode enabled
> + *
> + * If AAC Configuration Type is USTT mode specific
> + * (multiple bits may be set for this parameter),
> + * Bit 0 AAC (Balanced)
> + * Bit 1 AAC (Cool Bottom
> + * Bit 2 AAC (Quiet)
> + * Bit 3 AAC (Performance)
> + */
> +
> +#define DELL_ACC_GET_FIELD GENMASK(19, 16)
> +#define DELL_ACC_SET_FIELD GENMASK(11, 8)
> +#define DELL_THERMAL_SUPPORTED GENMASK(3, 0)
> +
> +enum thermal_mode_bits {
> + DELL_BALANCED = BIT(0),
> + DELL_COOL_BOTTOM = BIT(1),
> + DELL_QUIET = BIT(2),
> + DELL_PERFORMANCE = BIT(3),
> +};
> +
> +static int thermal_get_mode(void)
> +{
> + struct calling_interface_buffer buffer;
> + int state;
> + int ret;
> +
> + dell_fill_request(&buffer, 0x0, 0, 0, 0);
> + ret = dell_send_request(&buffer, CLASS_INFO, SELECT_THERMAL_MANAGEMENT);
> + if (ret)
> + return ret;
> + state = buffer.output[2];
> + if (state & DELL_BALANCED)
> + return DELL_BALANCED;
> + else if (state & DELL_COOL_BOTTOM)
> + return DELL_COOL_BOTTOM;
> + else if (state & DELL_QUIET)
> + return DELL_QUIET;
> + else if (state & DELL_PERFORMANCE)
> + return DELL_PERFORMANCE;
> + else
> + return -ENXIO;
> +}
> +
> +static int thermal_get_supported_modes(int *supported_bits)
> +{
> + struct calling_interface_buffer buffer;
> + int ret;
> +
> + dell_fill_request(&buffer, 0x0, 0, 0, 0);
> + ret = dell_send_request(&buffer, CLASS_INFO, SELECT_THERMAL_MANAGEMENT);
> + if (ret)
> + return ret;
> + *supported_bits = FIELD_GET(DELL_THERMAL_SUPPORTED, buffer.output[1]);
> + return 0;
> +}
> +
> +static int thermal_get_acc_mode(int *acc_mode)
> +{
> + struct calling_interface_buffer buffer;
> + int ret;
> +
> + dell_fill_request(&buffer, 0x0, 0, 0, 0);
> + ret = dell_send_request(&buffer, CLASS_INFO, SELECT_THERMAL_MANAGEMENT);
> + if (ret)
> + return ret;
> + *acc_mode = FIELD_GET(DELL_ACC_GET_FIELD, buffer.output[3]);
> + return 0;
> +}
> +
> +static int thermal_set_mode(enum thermal_mode_bits state)
> +{
> + struct calling_interface_buffer buffer;
> + int ret;
> + int acc_mode;
> +
> + ret = thermal_get_acc_mode(&acc_mode);
> + if (ret)
> + return ret;
> +
> + dell_fill_request(&buffer, 0x1, FIELD_PREP(DELL_ACC_SET_FIELD, acc_mode) | state, 0, 0);
> + ret = dell_send_request(&buffer, CLASS_INFO, SELECT_THERMAL_MANAGEMENT);
> + return ret;
> +}
> +
> +static int thermal_platform_profile_set(struct platform_profile_handler *pprof,
> + enum platform_profile_option profile)
> +{
> + switch (profile) {
> + case PLATFORM_PROFILE_BALANCED:
> + return thermal_set_mode(DELL_BALANCED);
> + case PLATFORM_PROFILE_PERFORMANCE:
> + return thermal_set_mode(DELL_PERFORMANCE);
> + case PLATFORM_PROFILE_QUIET:
> + return thermal_set_mode(DELL_QUIET);
> + case PLATFORM_PROFILE_COOL:
> + return thermal_set_mode(DELL_COOL_BOTTOM);
> + default:
> + return -EOPNOTSUPP;
> + }
> +}
> +
> +static int thermal_platform_profile_get(struct platform_profile_handler *pprof,
> + enum platform_profile_option *profile)
> +{
> + int ret = thermal_get_mode();
> +
> + if (ret < 0)
> + return ret;
> +
> + switch (ret) {
> + case DELL_BALANCED:
> + *profile = PLATFORM_PROFILE_BALANCED;
> + break;
> + case DELL_PERFORMANCE:
> + *profile = PLATFORM_PROFILE_PERFORMANCE;
> + break;
> + case DELL_COOL_BOTTOM:
> + *profile = PLATFORM_PROFILE_COOL;
> + break;
> + case DELL_QUIET:
> + *profile = PLATFORM_PROFILE_QUIET;
> + break;
> + default:
> + return -EINVAL;
> + }
> +
> + return 0;
> +}
> +
> +int thermal_init(void)
> +{
> + int ret;
> + int supported_modes;
> +
> + ret = thermal_get_supported_modes(&supported_modes);
> + if (ret || !supported_modes)
> + return 0;
> +
> + thermal_handler = kzalloc(sizeof(*thermal_handler), GFP_KERNEL);
> + if (!thermal_handler)
> + return -ENOMEM;
> + thermal_handler->profile_get = thermal_platform_profile_get;
> + thermal_handler->profile_set = thermal_platform_profile_set;
> +
> + if (supported_modes & DELL_QUIET)
> + set_bit(PLATFORM_PROFILE_QUIET, thermal_handler->choices);
> + if (supported_modes & DELL_COOL_BOTTOM)
> + set_bit(PLATFORM_PROFILE_COOL, thermal_handler->choices);
> + if (supported_modes & DELL_BALANCED)
> + set_bit(PLATFORM_PROFILE_BALANCED, thermal_handler->choices);
> + if (supported_modes & DELL_PERFORMANCE)
> + set_bit(PLATFORM_PROFILE_PERFORMANCE, thermal_handler->choices);
> +
> + // Clean up but do not fail

Switch comment style to /* */

> + if (platform_profile_register(thermal_handler))
> + kfree(thermal_handler);

Don't you also want to return an error in this case? Because this means
that the platform supports thermal modes but it failed to setup due to
other issues.

It's different than the case of no supported modes in which case
returning 0 makes sense.

Maybe like this:


ret = platform_profile_register(thermal_handler);
if (ret)
kfree(thermal_handler);

return ret;


> +
> + return 0;
> +}
> +
> +void thermal_cleanup(void)
> +{
> + if (thermal_handler) {
> + platform_profile_remove();
> + kfree(thermal_handler);
> + }
> +}
> +
> static struct led_classdev mute_led_cdev = {
> .name = "platform::mute",
> .max_brightness = 1,
> @@ -2238,6 +2462,11 @@ static int __init dell_init(void)
> goto fail_rfkill;
> }
>
> + // Do not fail module if thermal modes not supported, just skip

Switch comment style to /* */

> + ret = thermal_init();
> + if (ret)
> + goto fail_thermal;
> +
> if (quirks && quirks->touchpad_led)
> touchpad_led_init(&platform_device->dev);
>
> @@ -2317,6 +2546,8 @@ static int __init dell_init(void)
> led_classdev_unregister(&mute_led_cdev);
> fail_led:
> dell_cleanup_rfkill();
> +fail_thermal:
> + thermal_cleanup();
> fail_rfkill:
> platform_device_del(platform_device);
> fail_platform_device2:
> @@ -2344,6 +2575,7 @@ static void __exit dell_exit(void)
> platform_device_unregister(platform_device);
> platform_driver_unregister(&platform_driver);
> }
> + thermal_cleanup();
> }
>
> /* dell-rbtn.c driver export functions which will not work correctly (and could
> diff --git a/drivers/platform/x86/dell/dell-smbios.h b/drivers/platform/x86/dell/dell-smbios.h
> index eb341bf000c6..585d042f1779 100644
> --- a/drivers/platform/x86/dell/dell-smbios.h
> +++ b/drivers/platform/x86/dell/dell-smbios.h
> @@ -19,6 +19,7 @@
> /* Classes and selects used only in kernel drivers */
> #define CLASS_KBD_BACKLIGHT 4
> #define SELECT_KBD_BACKLIGHT 11
> +#define SELECT_THERMAL_MANAGEMENT 19
>
> /* Tokens used in kernel drivers, any of these
> * should be filtered from userspace access


2024-04-29 18:04:26

by Mario Limonciello

[permalink] [raw]
Subject: Re: [PATCH v3] platform/x86: dell-laptop: Implement platform_profile

On 4/29/2024 12:45, Mario Limonciello wrote:
> On 4/29/2024 11:48, Lyndon Sanche wrote:
>> Some Dell laptops support configuration of preset fan modes through
>> smbios tables.
>>
>> If the platform supports these fan modes, set up platform_profile to
>> change these modes. If not supported, skip enabling platform_profile.
>>
>> Signed-off-by: Lyndon Sanche <[email protected]>
>> ---
>> v3:
>>   - Convert smbios-thermal-ctl docs to multiline comment and wrap
>>   - Change thermal_mode_bits enum to directly be BIT() values
>>    - Convert related code to use this
>>   - Use FIELD_GET/PREP and GENNMASK for getting/setting thermal modes
>>    - Correct offset for getting current ACC mode, setting offset
>>         unchanged
>>   - Check if thermal_handler is allocated before freeing and
>>      unregistering platform_profile
>> v2:
>>   - Wrap smbios-thermal-ctl comment
>>   - Return proper error code when invalid state returned
>>   - Simplify platform_profile_get returns
>>   - Propogate ENOMEM error
>> ---
>>   drivers/platform/x86/dell/dell-laptop.c | 232 ++++++++++++++++++++++++
>>   drivers/platform/x86/dell/dell-smbios.h |   1 +
>>   2 files changed, 233 insertions(+)
>>
>> diff --git a/drivers/platform/x86/dell/dell-laptop.c
>> b/drivers/platform/x86/dell/dell-laptop.c
>> index 42f7de2b4522..fa58e7751d06 100644
>> --- a/drivers/platform/x86/dell/dell-laptop.c
>> +++ b/drivers/platform/x86/dell/dell-laptop.c
>> @@ -27,6 +27,8 @@
>>   #include <linux/i8042.h>
>>   #include <linux/debugfs.h>
>>   #include <linux/seq_file.h>
>> +#include <linux/platform_profile.h>
>> +#include <linux/bitfield.h>
>
> These should be inserted in alphabetical order.
>
>>   #include <acpi/video.h>
>>   #include "dell-rbtn.h"
>>   #include "dell-smbios.h"
>> @@ -95,6 +97,7 @@ static struct backlight_device *dell_backlight_device;
>>   static struct rfkill *wifi_rfkill;
>>   static struct rfkill *bluetooth_rfkill;
>>   static struct rfkill *wwan_rfkill;
>> +static struct platform_profile_handler *thermal_handler;
>>   static bool force_rfkill;
>>   static bool micmute_led_registered;
>>   static bool mute_led_registered;
>> @@ -2199,6 +2202,227 @@ static int mute_led_set(struct led_classdev
>> *led_cdev,
>>       return 0;
>>   }
>> +/* Derived from smbios-thermal-ctl
>> + *
>> + * cbClass 17
>> + * cbSelect 19
>> + * User Selectable Thermal Tables(USTT)
>> + * cbArg1 determines the function to be performed
>> + * cbArg1 0x0 = Get Thermal Information
>> + *  cbRES1         Standard return codes (0, -1, -2)
>> + *  cbRES2, byte 0  Bitmap of supported thermal modes. A mode is
>> supported if
>> + *                  its bit is set to 1
>> + *     Bit 0 Balanced
>> + *     Bit 1 Cool Bottom
>> + *     Bit 2 Quiet
>> + *     Bit 3 Performance
>> + *  cbRES2, byte 1 Bitmap of supported Active Acoustic Controller
>> (AAC) modes.
>> + *                 Each mode corresponds to the supported thermal
>> modes in
>> + *                  byte 0. A mode is supported if its bit is set to 1.
>> + *     Bit 0 AAC (Balanced)
>> + *     Bit 1 AAC (Cool Bottom
>> + *     Bit 2 AAC (Quiet)
>> + *     Bit 3 AAC (Performance)
>> + *  cbRes3, byte 0 Current Thermal Mode
>> + *     Bit 0 Balanced
>> + *     Bit 1 Cool Bottom
>> + *     Bit 2 Quiet
>> + *     Bit 3 Performanc
>> + *  cbRes3, byte 1  AAC Configuration type
>> + *          0       Global (AAC enable/disable applies to all
>> supported USTT modes)
>> + *          1       USTT mode specific
>> + *  cbRes3, byte 2  Current Active Acoustic Controller (AAC) Mode
>> + *     If AAC Configuration Type is Global,
>> + *          0       AAC mode disabled
>> + *          1       AAC mode enabled
>> + *     If AAC Configuration Type is USTT mode specific (multiple bits
>> may be set),
>> + *          Bit 0 AAC (Balanced)
>> + *          Bit 1 AAC (Cool Bottom
>> + *          Bit 2 AAC (Quiet)
>> + *          Bit 3 AAC (Performance)
>> + *  cbRes3, byte 3  Current Fan Failure Mode
>> + *     Bit 0 Minimal Fan Failure (at least one fan has failed, one
>> fan working)
>> + *     Bit 1 Catastrophic Fan Failure (all fans have failed)
>> + *  cbArg1 0x1   (Set Thermal Information), both desired thermal mode
>> and
>> + *               desired AAC mode shall be applied
>> + *  cbArg2, byte 0  Desired Thermal Mode to set
>> + *                  (only one bit may be set for this parameter)
>> + *     Bit 0 Balanced
>> + *     Bit 1 Cool Bottom
>> + *     Bit 2 Quiet
>> + *     Bit 3 Performance
>> + *  cbArg2, byte 1  Desired Active Acoustic Controller (AAC) Mode to set
>> + *     If AAC Configuration Type is Global,
>> + *         0  AAC mode disabled
>> + *         1  AAC mode enabled
>> + *
>> + *     If AAC Configuration Type is USTT mode specific
>> + *     (multiple bits may be set for this parameter),
>> + *         Bit 0 AAC (Balanced)
>> + *         Bit 1 AAC (Cool Bottom
>> + *         Bit 2 AAC (Quiet)
>> + *         Bit 3 AAC (Performance)
>> + */
>> +
>> +#define DELL_ACC_GET_FIELD GENMASK(19, 16)
>> +#define DELL_ACC_SET_FIELD GENMASK(11, 8)
>> +#define DELL_THERMAL_SUPPORTED GENMASK(3, 0)
>> +
>> +enum thermal_mode_bits {
>> +    DELL_BALANCED = BIT(0),
>> +    DELL_COOL_BOTTOM = BIT(1),
>> +    DELL_QUIET = BIT(2),
>> +    DELL_PERFORMANCE = BIT(3),
>> +};
>> +
>> +static int thermal_get_mode(void)
>> +{
>> +    struct calling_interface_buffer buffer;
>> +    int state;
>> +    int ret;
>> +
>> +    dell_fill_request(&buffer, 0x0, 0, 0, 0);
>> +    ret = dell_send_request(&buffer, CLASS_INFO,
>> SELECT_THERMAL_MANAGEMENT);
>> +    if (ret)
>> +        return ret;
>> +    state = buffer.output[2];
>> +    if (state & DELL_BALANCED)
>> +        return DELL_BALANCED;
>> +    else if (state & DELL_COOL_BOTTOM)
>> +        return DELL_COOL_BOTTOM;
>> +    else if (state & DELL_QUIET)
>> +        return DELL_QUIET;
>> +    else if (state & DELL_PERFORMANCE)
>> +        return DELL_PERFORMANCE;
>> +    else
>> +        return -ENXIO;
>> +}
>> +
>> +static int thermal_get_supported_modes(int *supported_bits)
>> +{
>> +    struct calling_interface_buffer buffer;
>> +    int ret;
>> +
>> +    dell_fill_request(&buffer, 0x0, 0, 0, 0);
>> +    ret = dell_send_request(&buffer, CLASS_INFO,
>> SELECT_THERMAL_MANAGEMENT);
>> +    if (ret)
>> +        return ret;
>> +    *supported_bits = FIELD_GET(DELL_THERMAL_SUPPORTED,
>> buffer.output[1]);
>> +    return 0;
>> +}
>> +
>> +static int thermal_get_acc_mode(int *acc_mode)
>> +{
>> +    struct calling_interface_buffer buffer;
>> +    int ret;
>> +
>> +    dell_fill_request(&buffer, 0x0, 0, 0, 0);
>> +    ret = dell_send_request(&buffer, CLASS_INFO,
>> SELECT_THERMAL_MANAGEMENT);
>> +    if (ret)
>> +        return ret;
>> +    *acc_mode = FIELD_GET(DELL_ACC_GET_FIELD, buffer.output[3]);
>> +    return 0;
>> +}
>> +
>> +static int thermal_set_mode(enum thermal_mode_bits state)
>> +{
>> +    struct calling_interface_buffer buffer;
>> +    int ret;
>> +    int acc_mode;
>> +
>> +    ret = thermal_get_acc_mode(&acc_mode);
>> +    if (ret)
>> +        return ret;
>> +
>> +    dell_fill_request(&buffer, 0x1, FIELD_PREP(DELL_ACC_SET_FIELD,
>> acc_mode) | state, 0, 0);
>> +    ret = dell_send_request(&buffer, CLASS_INFO,
>> SELECT_THERMAL_MANAGEMENT);
>> +    return ret;
>> +}
>> +
>> +static int thermal_platform_profile_set(struct
>> platform_profile_handler *pprof,
>> +                    enum platform_profile_option profile)
>> +{
>> +    switch (profile) {
>> +    case PLATFORM_PROFILE_BALANCED:
>> +        return thermal_set_mode(DELL_BALANCED);
>> +    case PLATFORM_PROFILE_PERFORMANCE:
>> +        return thermal_set_mode(DELL_PERFORMANCE);
>> +    case PLATFORM_PROFILE_QUIET:
>> +        return thermal_set_mode(DELL_QUIET);
>> +    case PLATFORM_PROFILE_COOL:
>> +        return thermal_set_mode(DELL_COOL_BOTTOM);
>> +    default:
>> +        return -EOPNOTSUPP;
>> +    }
>> +}
>> +
>> +static int thermal_platform_profile_get(struct
>> platform_profile_handler *pprof,
>> +                    enum platform_profile_option *profile)
>> +{
>> +    int ret = thermal_get_mode();
>> +
>> +    if (ret < 0)
>> +        return ret;
>> +
>> +    switch (ret) {
>> +    case DELL_BALANCED:
>> +        *profile = PLATFORM_PROFILE_BALANCED;
>> +        break;
>> +    case DELL_PERFORMANCE:
>> +        *profile = PLATFORM_PROFILE_PERFORMANCE;
>> +        break;
>> +    case DELL_COOL_BOTTOM:
>> +        *profile = PLATFORM_PROFILE_COOL;
>> +        break;
>> +    case DELL_QUIET:
>> +        *profile = PLATFORM_PROFILE_QUIET;
>> +        break;
>> +    default:
>> +        return -EINVAL;
>> +    }
>> +
>> +    return 0;
>> +}
>> +
>> +int thermal_init(void)
>> +{
>> +    int ret;
>> +    int supported_modes;
>> +
>> +    ret = thermal_get_supported_modes(&supported_modes);
>> +    if (ret || !supported_modes)
>> +        return 0;
>> +
>> +    thermal_handler = kzalloc(sizeof(*thermal_handler), GFP_KERNEL);
>> +    if (!thermal_handler)
>> +        return -ENOMEM;
>> +    thermal_handler->profile_get = thermal_platform_profile_get;
>> +    thermal_handler->profile_set = thermal_platform_profile_set;
>> +
>> +    if (supported_modes & DELL_QUIET)
>> +        set_bit(PLATFORM_PROFILE_QUIET, thermal_handler->choices);
>> +    if (supported_modes & DELL_COOL_BOTTOM)
>> +        set_bit(PLATFORM_PROFILE_COOL, thermal_handler->choices);
>> +    if (supported_modes & DELL_BALANCED)
>> +        set_bit(PLATFORM_PROFILE_BALANCED, thermal_handler->choices);
>> +    if (supported_modes & DELL_PERFORMANCE)
>> +        set_bit(PLATFORM_PROFILE_PERFORMANCE, thermal_handler->choices);
>> +
>> +    // Clean up but do not fail
>
> Switch comment style to /* */
>
>> +    if (platform_profile_register(thermal_handler))
>> +        kfree(thermal_handler);
>
> Don't you also want to return an error in this case?  Because this means
> that the platform supports thermal modes but it failed to setup due to
> other issues.
>
> It's different than the case of no supported modes in which case
> returning 0 makes sense.
>
> Maybe like this:
>
>
> ret = platform_profile_register(thermal_handler);
> if (ret)
>     kfree(thermal_handler);
>
> return ret;
>
>
>> +
>> +    return 0;
>> +}
>> +
>> +void thermal_cleanup(void)
>> +{
>> +    if (thermal_handler) {
>> +        platform_profile_remove();
>> +        kfree(thermal_handler);
>> +    }
>> +}
>> +
>>   static struct led_classdev mute_led_cdev = {
>>       .name = "platform::mute",
>>       .max_brightness = 1,
>> @@ -2238,6 +2462,11 @@ static int __init dell_init(void)
>>           goto fail_rfkill;
>>       }
>> +    // Do not fail module if thermal modes not supported, just skip
>
> Switch comment style to /* */
>
>> +    ret = thermal_init();
>> +    if (ret)
>> +        goto fail_thermal;
>> +
>>       if (quirks && quirks->touchpad_led)
>>           touchpad_led_init(&platform_device->dev);
>> @@ -2317,6 +2546,8 @@ static int __init dell_init(void)
>>           led_classdev_unregister(&mute_led_cdev);
>>   fail_led:
>>       dell_cleanup_rfkill();
>> +fail_thermal:
>> +    thermal_cleanup();
>>   fail_rfkill:
>>       platform_device_del(platform_device);
>>   fail_platform_device2:
>> @@ -2344,6 +2575,7 @@ static void __exit dell_exit(void)
>>           platform_device_unregister(platform_device);
>>           platform_driver_unregister(&platform_driver);
>>       }
>> +    thermal_cleanup();
>>   }
>>   /* dell-rbtn.c driver export functions which will not work correctly
>> (and could
>> diff --git a/drivers/platform/x86/dell/dell-smbios.h
>> b/drivers/platform/x86/dell/dell-smbios.h
>> index eb341bf000c6..585d042f1779 100644
>> --- a/drivers/platform/x86/dell/dell-smbios.h
>> +++ b/drivers/platform/x86/dell/dell-smbios.h
>> @@ -19,6 +19,7 @@
>>   /* Classes and selects used only in kernel drivers */
>>   #define CLASS_KBD_BACKLIGHT 4
>>   #define SELECT_KBD_BACKLIGHT 11
>> +#define SELECT_THERMAL_MANAGEMENT 19

I think you should insert this into dell-smbios-base.c under
call_blacklist. This will prevent userspace from fighting with the
kernel on the same data when this code goes in.

>>   /* Tokens used in kernel drivers, any of these
>>    * should be filtered from userspace access
>


2024-04-29 21:26:02

by Lyndon Sanche

[permalink] [raw]
Subject: Re: [PATCH v3] platform/x86: dell-laptop: Implement platform_profile



On Mon, Apr 29 2024 at 12:51:31 PM -05:00:00, Mario Limonciello
<[email protected]> wrote:
> On 4/29/2024 12:45, Mario Limonciello wrote:
>> On 4/29/2024 11:48, Lyndon Sanche wrote:
>>> #define CLASS_KBD_BACKLIGHT 4
>>> #define SELECT_KBD_BACKLIGHT 11
>>> +#define SELECT_THERMAL_MANAGEMENT 19
>
> I think you should insert this into dell-smbios-base.c under
> call_blacklist. This will prevent userspace from fighting with the
> kernel on the same data when this code goes in.

Good idea, I have been using smbios-thermal-ctl for checking the state
when testing. I will include this in the patch, then smbios-thermal-ctl
cannot interfere.

Thanks,

Lyndon



2024-04-29 21:26:15

by Lyndon Sanche

[permalink] [raw]
Subject: Re: [PATCH v3] platform/x86: dell-laptop: Implement platform_profile



On Mon, Apr 29 2024 at 12:45:19 PM -05:00:00, Mario Limonciello
<[email protected]> wrote:
> On 4/29/2024 11:48, Lyndon Sanche wrote:
>> #include <linux/i8042.h>
>> #include <linux/debugfs.h>
>> #include <linux/seq_file.h>
>> +#include <linux/platform_profile.h>
>> +#include <linux/bitfield.h>
>
> These should be inserted in alphabetical order.

Agree

>> +
>> + // Clean up but do not fail
>
> Switch comment style to /* */

Agree

>
>> + if (platform_profile_register(thermal_handler))
>> + kfree(thermal_handler);
>
> Don't you also want to return an error in this case? Because this
> means that the platform supports thermal modes but it failed to setup
> due to other issues.
>
> It's different than the case of no supported modes in which case
> returning 0 makes sense.
>
> Maybe like this:
>
>
> ret = platform_profile_register(thermal_handler);
> if (ret)
> kfree(thermal_handler);
>
> return ret;

Good idea, I will propogate this error. Failure of module will then
occur on allocation or platform_profile error.

>
>
>>
>> goto fail_rfkill;
>> }
>> + // Do not fail module if thermal modes not supported, just skip
>
> Switch comment style to /* */

Agree.

Thank you for this feedback.

Lyndon
>



2024-04-30 10:31:37

by Ilpo Järvinen

[permalink] [raw]
Subject: Re: [PATCH v3] platform/x86: dell-laptop: Implement platform_profile

On Mon, 29 Apr 2024, Lyndon Sanche wrote:

> Some Dell laptops support configuration of preset fan modes through
> smbios tables.
>
> If the platform supports these fan modes, set up platform_profile to
> change these modes. If not supported, skip enabling platform_profile.
>
> Signed-off-by: Lyndon Sanche <[email protected]>
> ---
> v3:
> - Convert smbios-thermal-ctl docs to multiline comment and wrap
> - Change thermal_mode_bits enum to directly be BIT() values
> - Convert related code to use this
> - Use FIELD_GET/PREP and GENNMASK for getting/setting thermal modes
> - Correct offset for getting current ACC mode, setting offset
> unchanged
> - Check if thermal_handler is allocated before freeing and
> unregistering platform_profile
> v2:
> - Wrap smbios-thermal-ctl comment
> - Return proper error code when invalid state returned
> - Simplify platform_profile_get returns
> - Propogate ENOMEM error
> ---
> drivers/platform/x86/dell/dell-laptop.c | 232 ++++++++++++++++++++++++
> drivers/platform/x86/dell/dell-smbios.h | 1 +
> 2 files changed, 233 insertions(+)
>
> diff --git a/drivers/platform/x86/dell/dell-laptop.c b/drivers/platform/x86/dell/dell-laptop.c
> index 42f7de2b4522..fa58e7751d06 100644
> --- a/drivers/platform/x86/dell/dell-laptop.c
> +++ b/drivers/platform/x86/dell/dell-laptop.c
> @@ -27,6 +27,8 @@
> #include <linux/i8042.h>
> #include <linux/debugfs.h>
> #include <linux/seq_file.h>
> +#include <linux/platform_profile.h>
> +#include <linux/bitfield.h>
> #include <acpi/video.h>
> #include "dell-rbtn.h"
> #include "dell-smbios.h"
> @@ -95,6 +97,7 @@ static struct backlight_device *dell_backlight_device;
> static struct rfkill *wifi_rfkill;
> static struct rfkill *bluetooth_rfkill;
> static struct rfkill *wwan_rfkill;
> +static struct platform_profile_handler *thermal_handler;
> static bool force_rfkill;
> static bool micmute_led_registered;
> static bool mute_led_registered;
> @@ -2199,6 +2202,227 @@ static int mute_led_set(struct led_classdev *led_cdev,
> return 0;
> }
>
> +/* Derived from smbios-thermal-ctl
> + *
> + * cbClass 17
> + * cbSelect 19
> + * User Selectable Thermal Tables(USTT)
> + * cbArg1 determines the function to be performed
> + * cbArg1 0x0 = Get Thermal Information
> + * cbRES1 Standard return codes (0, -1, -2)
> + * cbRES2, byte 0 Bitmap of supported thermal modes. A mode is supported if
> + * its bit is set to 1
> + * Bit 0 Balanced
> + * Bit 1 Cool Bottom
> + * Bit 2 Quiet
> + * Bit 3 Performance
> + * cbRES2, byte 1 Bitmap of supported Active Acoustic Controller (AAC) modes.
> + * Each mode corresponds to the supported thermal modes in
> + * byte 0. A mode is supported if its bit is set to 1.
> + * Bit 0 AAC (Balanced)
> + * Bit 1 AAC (Cool Bottom
> + * Bit 2 AAC (Quiet)
> + * Bit 3 AAC (Performance)
> + * cbRes3, byte 0 Current Thermal Mode
> + * Bit 0 Balanced
> + * Bit 1 Cool Bottom
> + * Bit 2 Quiet
> + * Bit 3 Performanc
> + * cbRes3, byte 1 AAC Configuration type
> + * 0 Global (AAC enable/disable applies to all supported USTT modes)
> + * 1 USTT mode specific
> + * cbRes3, byte 2 Current Active Acoustic Controller (AAC) Mode
> + * If AAC Configuration Type is Global,
> + * 0 AAC mode disabled
> + * 1 AAC mode enabled
> + * If AAC Configuration Type is USTT mode specific (multiple bits may be set),
> + * Bit 0 AAC (Balanced)
> + * Bit 1 AAC (Cool Bottom
> + * Bit 2 AAC (Quiet)
> + * Bit 3 AAC (Performance)
> + * cbRes3, byte 3 Current Fan Failure Mode
> + * Bit 0 Minimal Fan Failure (at least one fan has failed, one fan working)
> + * Bit 1 Catastrophic Fan Failure (all fans have failed)
> + * cbArg1 0x1 (Set Thermal Information), both desired thermal mode and
> + * desired AAC mode shall be applied
> + * cbArg2, byte 0 Desired Thermal Mode to set
> + * (only one bit may be set for this parameter)
> + * Bit 0 Balanced
> + * Bit 1 Cool Bottom
> + * Bit 2 Quiet
> + * Bit 3 Performance
> + * cbArg2, byte 1 Desired Active Acoustic Controller (AAC) Mode to set
> + * If AAC Configuration Type is Global,
> + * 0 AAC mode disabled
> + * 1 AAC mode enabled
> + *
> + * If AAC Configuration Type is USTT mode specific
> + * (multiple bits may be set for this parameter),
> + * Bit 0 AAC (Balanced)
> + * Bit 1 AAC (Cool Bottom
> + * Bit 2 AAC (Quiet)
> + * Bit 3 AAC (Performance)
> + */
> +
> +#define DELL_ACC_GET_FIELD GENMASK(19, 16)
> +#define DELL_ACC_SET_FIELD GENMASK(11, 8)
> +#define DELL_THERMAL_SUPPORTED GENMASK(3, 0)

Please align these with tabs.

> +enum thermal_mode_bits {
> + DELL_BALANCED = BIT(0),
> + DELL_COOL_BOTTOM = BIT(1),
> + DELL_QUIET = BIT(2),
> + DELL_PERFORMANCE = BIT(3),

You need #include <linux/bits.h> for BIT().

> +};
> +
> +static int thermal_get_mode(void)
> +{
> + struct calling_interface_buffer buffer;
> + int state;
> + int ret;
> +
> + dell_fill_request(&buffer, 0x0, 0, 0, 0);
> + ret = dell_send_request(&buffer, CLASS_INFO, SELECT_THERMAL_MANAGEMENT);
> + if (ret)
> + return ret;
> + state = buffer.output[2];
> + if (state & DELL_BALANCED)
> + return DELL_BALANCED;
> + else if (state & DELL_COOL_BOTTOM)
> + return DELL_COOL_BOTTOM;
> + else if (state & DELL_QUIET)
> + return DELL_QUIET;
> + else if (state & DELL_PERFORMANCE)
> + return DELL_PERFORMANCE;
> + else
> + return -ENXIO;
> +}
> +
> +static int thermal_get_supported_modes(int *supported_bits)
> +{
> + struct calling_interface_buffer buffer;
> + int ret;
> +
> + dell_fill_request(&buffer, 0x0, 0, 0, 0);
> + ret = dell_send_request(&buffer, CLASS_INFO, SELECT_THERMAL_MANAGEMENT);
> + if (ret)
> + return ret;
> + *supported_bits = FIELD_GET(DELL_THERMAL_SUPPORTED, buffer.output[1]);
> + return 0;
> +}
> +
> +static int thermal_get_acc_mode(int *acc_mode)
> +{
> + struct calling_interface_buffer buffer;
> + int ret;
> +
> + dell_fill_request(&buffer, 0x0, 0, 0, 0);
> + ret = dell_send_request(&buffer, CLASS_INFO, SELECT_THERMAL_MANAGEMENT);
> + if (ret)
> + return ret;
> + *acc_mode = FIELD_GET(DELL_ACC_GET_FIELD, buffer.output[3]);
> + return 0;
> +}
> +
> +static int thermal_set_mode(enum thermal_mode_bits state)
> +{
> + struct calling_interface_buffer buffer;
> + int ret;
> + int acc_mode;
> +
> + ret = thermal_get_acc_mode(&acc_mode);
> + if (ret)
> + return ret;
> +
> + dell_fill_request(&buffer, 0x1, FIELD_PREP(DELL_ACC_SET_FIELD, acc_mode) | state, 0, 0);
> + ret = dell_send_request(&buffer, CLASS_INFO, SELECT_THERMAL_MANAGEMENT);
> + return ret;
> +}
> +
> +static int thermal_platform_profile_set(struct platform_profile_handler *pprof,
> + enum platform_profile_option profile)
> +{
> + switch (profile) {
> + case PLATFORM_PROFILE_BALANCED:
> + return thermal_set_mode(DELL_BALANCED);
> + case PLATFORM_PROFILE_PERFORMANCE:
> + return thermal_set_mode(DELL_PERFORMANCE);
> + case PLATFORM_PROFILE_QUIET:
> + return thermal_set_mode(DELL_QUIET);
> + case PLATFORM_PROFILE_COOL:
> + return thermal_set_mode(DELL_COOL_BOTTOM);
> + default:
> + return -EOPNOTSUPP;
> + }
> +}
> +
> +static int thermal_platform_profile_get(struct platform_profile_handler *pprof,
> + enum platform_profile_option *profile)
> +{
> + int ret = thermal_get_mode();
> +
> + if (ret < 0)

I think I already mentioned about this, change to:

int ret;

ret = thermal_get_mode();
if (ret < 0)

> + return ret;
> +
> + switch (ret) {
> + case DELL_BALANCED:
> + *profile = PLATFORM_PROFILE_BALANCED;
> + break;
> + case DELL_PERFORMANCE:
> + *profile = PLATFORM_PROFILE_PERFORMANCE;
> + break;
> + case DELL_COOL_BOTTOM:
> + *profile = PLATFORM_PROFILE_COOL;
> + break;
> + case DELL_QUIET:
> + *profile = PLATFORM_PROFILE_QUIET;
> + break;
> + default:
> + return -EINVAL;
> + }
> +
> + return 0;
> +}
> +
> +int thermal_init(void)
> +{
> + int ret;
> + int supported_modes;
> +
> + ret = thermal_get_supported_modes(&supported_modes);
> + if (ret || !supported_modes)
> + return 0;

I think you should propagate the error code differently from nothing
supported:

if (ret < 0)
return ret;
if (!supported_modes)
return 0;

--
i.

> +
> + thermal_handler = kzalloc(sizeof(*thermal_handler), GFP_KERNEL);
> + if (!thermal_handler)
> + return -ENOMEM;
> + thermal_handler->profile_get = thermal_platform_profile_get;
> + thermal_handler->profile_set = thermal_platform_profile_set;
> +
> + if (supported_modes & DELL_QUIET)
> + set_bit(PLATFORM_PROFILE_QUIET, thermal_handler->choices);
> + if (supported_modes & DELL_COOL_BOTTOM)
> + set_bit(PLATFORM_PROFILE_COOL, thermal_handler->choices);
> + if (supported_modes & DELL_BALANCED)
> + set_bit(PLATFORM_PROFILE_BALANCED, thermal_handler->choices);
> + if (supported_modes & DELL_PERFORMANCE)
> + set_bit(PLATFORM_PROFILE_PERFORMANCE, thermal_handler->choices);
> +
> + // Clean up but do not fail
> + if (platform_profile_register(thermal_handler))
> + kfree(thermal_handler);
> +
> + return 0;
> +}
> +
> +void thermal_cleanup(void)
> +{
> + if (thermal_handler) {
> + platform_profile_remove();
> + kfree(thermal_handler);
> + }
> +}
> +
> static struct led_classdev mute_led_cdev = {
> .name = "platform::mute",
> .max_brightness = 1,
> @@ -2238,6 +2462,11 @@ static int __init dell_init(void)
> goto fail_rfkill;
> }
>
> + // Do not fail module if thermal modes not supported, just skip
> + ret = thermal_init();
> + if (ret)
> + goto fail_thermal;
> +
> if (quirks && quirks->touchpad_led)
> touchpad_led_init(&platform_device->dev);
>
> @@ -2317,6 +2546,8 @@ static int __init dell_init(void)
> led_classdev_unregister(&mute_led_cdev);
> fail_led:
> dell_cleanup_rfkill();
> +fail_thermal:
> + thermal_cleanup();
> fail_rfkill:
> platform_device_del(platform_device);
> fail_platform_device2:
> @@ -2344,6 +2575,7 @@ static void __exit dell_exit(void)
> platform_device_unregister(platform_device);
> platform_driver_unregister(&platform_driver);
> }
> + thermal_cleanup();
> }
>
> /* dell-rbtn.c driver export functions which will not work correctly (and could
> diff --git a/drivers/platform/x86/dell/dell-smbios.h b/drivers/platform/x86/dell/dell-smbios.h
> index eb341bf000c6..585d042f1779 100644
> --- a/drivers/platform/x86/dell/dell-smbios.h
> +++ b/drivers/platform/x86/dell/dell-smbios.h
> @@ -19,6 +19,7 @@
> /* Classes and selects used only in kernel drivers */
> #define CLASS_KBD_BACKLIGHT 4
> #define SELECT_KBD_BACKLIGHT 11
> +#define SELECT_THERMAL_MANAGEMENT 19
>
> /* Tokens used in kernel drivers, any of these
> * should be filtered from userspace access
>

2024-04-30 15:38:02

by kernel test robot

[permalink] [raw]
Subject: Re: [PATCH v3] platform/x86: dell-laptop: Implement platform_profile

Hi Lyndon,

kernel test robot noticed the following build warnings:

[auto build test WARNING on linus/master]
[also build test WARNING on v6.9-rc6 next-20240430]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]

url: https://github.com/intel-lab-lkp/linux/commits/Lyndon-Sanche/platform-x86-dell-laptop-Implement-platform_profile/20240430-135932
base: linus/master
patch link: https://lore.kernel.org/r/20240429164844.7544-2-lsanche%40lyndeno.ca
patch subject: [PATCH v3] platform/x86: dell-laptop: Implement platform_profile
config: i386-allyesconfig (https://download.01.org/0day-ci/archive/20240430/[email protected]/config)
compiler: gcc-13 (Ubuntu 13.2.0-4ubuntu3) 13.2.0
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20240430/[email protected]/reproduce)

If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <[email protected]>
| Closes: https://lore.kernel.org/oe-kbuild-all/[email protected]/

All warnings (new ones prefixed by >>):

>> drivers/platform/x86/dell/dell-laptop.c:2387:5: warning: no previous prototype for 'thermal_init' [-Wmissing-prototypes]
2387 | int thermal_init(void)
| ^~~~~~~~~~~~
>> drivers/platform/x86/dell/dell-laptop.c:2418:6: warning: no previous prototype for 'thermal_cleanup' [-Wmissing-prototypes]
2418 | void thermal_cleanup(void)
| ^~~~~~~~~~~~~~~


vim +/thermal_init +2387 drivers/platform/x86/dell/dell-laptop.c

2386
> 2387 int thermal_init(void)
2388 {
2389 int ret;
2390 int supported_modes;
2391
2392 ret = thermal_get_supported_modes(&supported_modes);
2393 if (ret || !supported_modes)
2394 return 0;
2395
2396 thermal_handler = kzalloc(sizeof(*thermal_handler), GFP_KERNEL);
2397 if (!thermal_handler)
2398 return -ENOMEM;
2399 thermal_handler->profile_get = thermal_platform_profile_get;
2400 thermal_handler->profile_set = thermal_platform_profile_set;
2401
2402 if (supported_modes & DELL_QUIET)
2403 set_bit(PLATFORM_PROFILE_QUIET, thermal_handler->choices);
2404 if (supported_modes & DELL_COOL_BOTTOM)
2405 set_bit(PLATFORM_PROFILE_COOL, thermal_handler->choices);
2406 if (supported_modes & DELL_BALANCED)
2407 set_bit(PLATFORM_PROFILE_BALANCED, thermal_handler->choices);
2408 if (supported_modes & DELL_PERFORMANCE)
2409 set_bit(PLATFORM_PROFILE_PERFORMANCE, thermal_handler->choices);
2410
2411 // Clean up but do not fail
2412 if (platform_profile_register(thermal_handler))
2413 kfree(thermal_handler);
2414
2415 return 0;
2416 }
2417
> 2418 void thermal_cleanup(void)
2419 {
2420 if (thermal_handler) {
2421 platform_profile_remove();
2422 kfree(thermal_handler);
2423 }
2424 }
2425

--
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki

2024-04-30 18:46:34

by Lyndon Sanche

[permalink] [raw]
Subject: Re: [PATCH v3] platform/x86: dell-laptop: Implement platform_profile

On Tue, Apr 30, 2024, at 4:31 AM, Ilpo Järvinen wrote:
> On Mon, 29 Apr 2024, Lyndon Sanche wrote:
>> + */
>> +
>> +#define DELL_ACC_GET_FIELD GENMASK(19, 16)
>> +#define DELL_ACC_SET_FIELD GENMASK(11, 8)
>> +#define DELL_THERMAL_SUPPORTED GENMASK(3, 0)
>
> Please align these with tabs.
>

Agreed.

>> +enum thermal_mode_bits {
>> + DELL_BALANCED = BIT(0),
>> + DELL_COOL_BOTTOM = BIT(1),
>> + DELL_QUIET = BIT(2),
>> + DELL_PERFORMANCE = BIT(3),
>
> You need #include <linux/bits.h> for BIT().
>

Agreed.

>> + }
>> +}
>> +
>> +static int thermal_platform_profile_get(struct platform_profile_handler *pprof,
>> + enum platform_profile_option *profile)
>> +{
>> + int ret = thermal_get_mode();
>> +
>> + if (ret < 0)
>
> I think I already mentioned about this, change to:
>
> int ret;
>
> ret = thermal_get_mode();
> if (ret < 0)
>

I missed this.

>> + return ret;
>> +
>> + switch (ret) {
>> + case DELL_BALANCED:
>> + *profile = PLATFORM_PROFILE_BALANCED;
>> + break;
>> + case DELL_PERFORMANCE:
>> + *profile = PLATFORM_PROFILE_PERFORMANCE;
>> + break;
>> + case DELL_COOL_BOTTOM:
>> + *profile = PLATFORM_PROFILE_COOL;
>> + break;
>> + case DELL_QUIET:
>> + *profile = PLATFORM_PROFILE_QUIET;
>> + break;
>> + default:
>> + return -EINVAL;
>> + }
>> +
>> + return 0;
>> +}
>> +
>> +int thermal_init(void)
>> +{
>> + int ret;
>> + int supported_modes;
>> +
>> + ret = thermal_get_supported_modes(&supported_modes);
>> + if (ret || !supported_modes)
>> + return 0;
>
> I think you should propagate the error code differently from nothing
> supported:
>
> if (ret < 0)
> return ret;
> if (!supported_modes)
> return 0;
>

Agreed.

Thank you for your feedback.

Lyndon

2024-05-01 01:19:57

by Lyndon Sanche

[permalink] [raw]
Subject: [PATCH v4] platform/x86: dell-laptop: Implement platform_profile

Some Dell laptops support configuration of preset fan modes through
smbios tables.

If the platform supports these fan modes, set up platform_profile to
change these modes. If not supported, skip enabling platform_profile.

Signed-off-by: Lyndon Sanche <[email protected]>
---
v4:
- Make thermal_init and thermal_cleanup static
- Rearrange order of added includes, did not edit current includes
- Include bits.h
- Switch comment style
- Return error if platform_profile registering failed
- Add thermal calls to call_blacklist
- Align defines with tabs
- Correct separation of function and error handling
- Propagate error codes up
v3:
- Convert smbios-thermal-ctl docs to multiline comment and wrap
- Change thermal_mode_bits enum to directly be BIT() values
- Convert related code to use this
- Use FIELD_GET/PREP and GENNMASK for getting/setting thermal modes
- Correct offset for getting current ACC mode, setting offset
unchanged
- Check if thermal_handler is allocated before freeing and
unregistering platform_profile
v2:
- Wrap smbios-thermal-ctl comment
- Return proper error code when invalid state returned
- Simplify platform_profile_get returns
- Propogate ENOMEM error
---
drivers/platform/x86/dell/dell-laptop.c | 238 +++++++++++++++++++
drivers/platform/x86/dell/dell-smbios-base.c | 2 +
drivers/platform/x86/dell/dell-smbios.h | 1 +
3 files changed, 241 insertions(+)

diff --git a/drivers/platform/x86/dell/dell-laptop.c b/drivers/platform/x86/dell/dell-laptop.c
index 42f7de2b4522..530ee6079447 100644
--- a/drivers/platform/x86/dell/dell-laptop.c
+++ b/drivers/platform/x86/dell/dell-laptop.c
@@ -27,6 +27,9 @@
#include <linux/i8042.h>
#include <linux/debugfs.h>
#include <linux/seq_file.h>
+#include <linux/bitfield.h>
+#include <linux/bits.h>
+#include <linux/platform_profile.h>
#include <acpi/video.h>
#include "dell-rbtn.h"
#include "dell-smbios.h"
@@ -95,6 +98,7 @@ static struct backlight_device *dell_backlight_device;
static struct rfkill *wifi_rfkill;
static struct rfkill *bluetooth_rfkill;
static struct rfkill *wwan_rfkill;
+static struct platform_profile_handler *thermal_handler;
static bool force_rfkill;
static bool micmute_led_registered;
static bool mute_led_registered;
@@ -2199,6 +2203,232 @@ static int mute_led_set(struct led_classdev *led_cdev,
return 0;
}

+/* Derived from smbios-thermal-ctl
+ *
+ * cbClass 17
+ * cbSelect 19
+ * User Selectable Thermal Tables(USTT)
+ * cbArg1 determines the function to be performed
+ * cbArg1 0x0 = Get Thermal Information
+ * cbRES1 Standard return codes (0, -1, -2)
+ * cbRES2, byte 0 Bitmap of supported thermal modes. A mode is supported if
+ * its bit is set to 1
+ * Bit 0 Balanced
+ * Bit 1 Cool Bottom
+ * Bit 2 Quiet
+ * Bit 3 Performance
+ * cbRES2, byte 1 Bitmap of supported Active Acoustic Controller (AAC) modes.
+ * Each mode corresponds to the supported thermal modes in
+ * byte 0. A mode is supported if its bit is set to 1.
+ * Bit 0 AAC (Balanced)
+ * Bit 1 AAC (Cool Bottom
+ * Bit 2 AAC (Quiet)
+ * Bit 3 AAC (Performance)
+ * cbRes3, byte 0 Current Thermal Mode
+ * Bit 0 Balanced
+ * Bit 1 Cool Bottom
+ * Bit 2 Quiet
+ * Bit 3 Performanc
+ * cbRes3, byte 1 AAC Configuration type
+ * 0 Global (AAC enable/disable applies to all supported USTT modes)
+ * 1 USTT mode specific
+ * cbRes3, byte 2 Current Active Acoustic Controller (AAC) Mode
+ * If AAC Configuration Type is Global,
+ * 0 AAC mode disabled
+ * 1 AAC mode enabled
+ * If AAC Configuration Type is USTT mode specific (multiple bits may be set),
+ * Bit 0 AAC (Balanced)
+ * Bit 1 AAC (Cool Bottom
+ * Bit 2 AAC (Quiet)
+ * Bit 3 AAC (Performance)
+ * cbRes3, byte 3 Current Fan Failure Mode
+ * Bit 0 Minimal Fan Failure (at least one fan has failed, one fan working)
+ * Bit 1 Catastrophic Fan Failure (all fans have failed)
+ * cbArg1 0x1 (Set Thermal Information), both desired thermal mode and
+ * desired AAC mode shall be applied
+ * cbArg2, byte 0 Desired Thermal Mode to set
+ * (only one bit may be set for this parameter)
+ * Bit 0 Balanced
+ * Bit 1 Cool Bottom
+ * Bit 2 Quiet
+ * Bit 3 Performance
+ * cbArg2, byte 1 Desired Active Acoustic Controller (AAC) Mode to set
+ * If AAC Configuration Type is Global,
+ * 0 AAC mode disabled
+ * 1 AAC mode enabled
+ *
+ * If AAC Configuration Type is USTT mode specific
+ * (multiple bits may be set for this parameter),
+ * Bit 0 AAC (Balanced)
+ * Bit 1 AAC (Cool Bottom
+ * Bit 2 AAC (Quiet)
+ * Bit 3 AAC (Performance)
+ */
+
+#define DELL_ACC_GET_FIELD GENMASK(19, 16)
+#define DELL_ACC_SET_FIELD GENMASK(11, 8)
+#define DELL_THERMAL_SUPPORTED GENMASK(3, 0)
+
+enum thermal_mode_bits {
+ DELL_BALANCED = BIT(0),
+ DELL_COOL_BOTTOM = BIT(1),
+ DELL_QUIET = BIT(2),
+ DELL_PERFORMANCE = BIT(3),
+};
+
+static int thermal_get_mode(void)
+{
+ struct calling_interface_buffer buffer;
+ int state;
+ int ret;
+
+ dell_fill_request(&buffer, 0x0, 0, 0, 0);
+ ret = dell_send_request(&buffer, CLASS_INFO, SELECT_THERMAL_MANAGEMENT);
+ if (ret)
+ return ret;
+ state = buffer.output[2];
+ if (state & DELL_BALANCED)
+ return DELL_BALANCED;
+ else if (state & DELL_COOL_BOTTOM)
+ return DELL_COOL_BOTTOM;
+ else if (state & DELL_QUIET)
+ return DELL_QUIET;
+ else if (state & DELL_PERFORMANCE)
+ return DELL_PERFORMANCE;
+ else
+ return -ENXIO;
+}
+
+static int thermal_get_supported_modes(int *supported_bits)
+{
+ struct calling_interface_buffer buffer;
+ int ret;
+
+ dell_fill_request(&buffer, 0x0, 0, 0, 0);
+ ret = dell_send_request(&buffer, CLASS_INFO, SELECT_THERMAL_MANAGEMENT);
+ if (ret)
+ return ret;
+ *supported_bits = FIELD_GET(DELL_THERMAL_SUPPORTED, buffer.output[1]);
+ return 0;
+}
+
+static int thermal_get_acc_mode(int *acc_mode)
+{
+ struct calling_interface_buffer buffer;
+ int ret;
+
+ dell_fill_request(&buffer, 0x0, 0, 0, 0);
+ ret = dell_send_request(&buffer, CLASS_INFO, SELECT_THERMAL_MANAGEMENT);
+ if (ret)
+ return ret;
+ *acc_mode = FIELD_GET(DELL_ACC_GET_FIELD, buffer.output[3]);
+ return 0;
+}
+
+static int thermal_set_mode(enum thermal_mode_bits state)
+{
+ struct calling_interface_buffer buffer;
+ int ret;
+ int acc_mode;
+
+ ret = thermal_get_acc_mode(&acc_mode);
+ if (ret)
+ return ret;
+
+ dell_fill_request(&buffer, 0x1, FIELD_PREP(DELL_ACC_SET_FIELD, acc_mode) | state, 0, 0);
+ ret = dell_send_request(&buffer, CLASS_INFO, SELECT_THERMAL_MANAGEMENT);
+ return ret;
+}
+
+static int thermal_platform_profile_set(struct platform_profile_handler *pprof,
+ enum platform_profile_option profile)
+{
+ switch (profile) {
+ case PLATFORM_PROFILE_BALANCED:
+ return thermal_set_mode(DELL_BALANCED);
+ case PLATFORM_PROFILE_PERFORMANCE:
+ return thermal_set_mode(DELL_PERFORMANCE);
+ case PLATFORM_PROFILE_QUIET:
+ return thermal_set_mode(DELL_QUIET);
+ case PLATFORM_PROFILE_COOL:
+ return thermal_set_mode(DELL_COOL_BOTTOM);
+ default:
+ return -EOPNOTSUPP;
+ }
+}
+
+static int thermal_platform_profile_get(struct platform_profile_handler *pprof,
+ enum platform_profile_option *profile)
+{
+ int ret;
+
+ ret = thermal_get_mode();
+ if (ret < 0)
+ return ret;
+
+ switch (ret) {
+ case DELL_BALANCED:
+ *profile = PLATFORM_PROFILE_BALANCED;
+ break;
+ case DELL_PERFORMANCE:
+ *profile = PLATFORM_PROFILE_PERFORMANCE;
+ break;
+ case DELL_COOL_BOTTOM:
+ *profile = PLATFORM_PROFILE_COOL;
+ break;
+ case DELL_QUIET:
+ *profile = PLATFORM_PROFILE_QUIET;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int thermal_init(void)
+{
+ int ret;
+ int supported_modes;
+
+ /* If thermal modes not supported, exit without error */
+ ret = thermal_get_supported_modes(&supported_modes);
+ if (ret < 0)
+ return ret;
+ if (!supported_modes)
+ return 0;
+
+ thermal_handler = kzalloc(sizeof(*thermal_handler), GFP_KERNEL);
+ if (!thermal_handler)
+ return -ENOMEM;
+ thermal_handler->profile_get = thermal_platform_profile_get;
+ thermal_handler->profile_set = thermal_platform_profile_set;
+
+ if (supported_modes & DELL_QUIET)
+ set_bit(PLATFORM_PROFILE_QUIET, thermal_handler->choices);
+ if (supported_modes & DELL_COOL_BOTTOM)
+ set_bit(PLATFORM_PROFILE_COOL, thermal_handler->choices);
+ if (supported_modes & DELL_BALANCED)
+ set_bit(PLATFORM_PROFILE_BALANCED, thermal_handler->choices);
+ if (supported_modes & DELL_PERFORMANCE)
+ set_bit(PLATFORM_PROFILE_PERFORMANCE, thermal_handler->choices);
+
+ /* Clean up if failed */
+ ret = platform_profile_register(thermal_handler);
+ if (ret)
+ kfree(thermal_handler);
+
+ return ret;
+}
+
+static void thermal_cleanup(void)
+{
+ if (thermal_handler) {
+ platform_profile_remove();
+ kfree(thermal_handler);
+ }
+}
+
static struct led_classdev mute_led_cdev = {
.name = "platform::mute",
.max_brightness = 1,
@@ -2238,6 +2468,11 @@ static int __init dell_init(void)
goto fail_rfkill;
}

+ /* Do not fail module if thermal modes not supported, just skip */
+ ret = thermal_init();
+ if (ret)
+ goto fail_thermal;
+
if (quirks && quirks->touchpad_led)
touchpad_led_init(&platform_device->dev);

@@ -2317,6 +2552,8 @@ static int __init dell_init(void)
led_classdev_unregister(&mute_led_cdev);
fail_led:
dell_cleanup_rfkill();
+fail_thermal:
+ thermal_cleanup();
fail_rfkill:
platform_device_del(platform_device);
fail_platform_device2:
@@ -2344,6 +2581,7 @@ static void __exit dell_exit(void)
platform_device_unregister(platform_device);
platform_driver_unregister(&platform_driver);
}
+ thermal_cleanup();
}

/* dell-rbtn.c driver export functions which will not work correctly (and could
diff --git a/drivers/platform/x86/dell/dell-smbios-base.c b/drivers/platform/x86/dell/dell-smbios-base.c
index e61bfaf8b5c4..40aa4469b38b 100644
--- a/drivers/platform/x86/dell/dell-smbios-base.c
+++ b/drivers/platform/x86/dell/dell-smbios-base.c
@@ -9,6 +9,7 @@
* Based on documentation in the libsmbios package:
* Copyright (C) 2005-2014 Dell Inc.
*/
+#include "linux/wmi.h"
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt

#include <linux/kernel.h>
@@ -71,6 +72,7 @@ static struct smbios_call call_blacklist[] = {
/* handled by kernel: dell-laptop */
{0x0000, CLASS_INFO, SELECT_RFKILL},
{0x0000, CLASS_KBD_BACKLIGHT, SELECT_KBD_BACKLIGHT},
+ {0x0000, CLASS_INFO, SELECT_THERMAL_MANAGEMENT},
};

struct token_range {
diff --git a/drivers/platform/x86/dell/dell-smbios.h b/drivers/platform/x86/dell/dell-smbios.h
index eb341bf000c6..585d042f1779 100644
--- a/drivers/platform/x86/dell/dell-smbios.h
+++ b/drivers/platform/x86/dell/dell-smbios.h
@@ -19,6 +19,7 @@
/* Classes and selects used only in kernel drivers */
#define CLASS_KBD_BACKLIGHT 4
#define SELECT_KBD_BACKLIGHT 11
+#define SELECT_THERMAL_MANAGEMENT 19

/* Tokens used in kernel drivers, any of these
* should be filtered from userspace access
--
2.42.0


2024-05-01 01:36:37

by Pali Rohár

[permalink] [raw]
Subject: Re: [PATCH v4] platform/x86: dell-laptop: Implement platform_profile

On Tuesday 30 April 2024 19:14:52 Lyndon Sanche wrote:
> Some Dell laptops support configuration of preset fan modes through
> smbios tables.
>
> If the platform supports these fan modes, set up platform_profile to
> change these modes. If not supported, skip enabling platform_profile.
>
> Signed-off-by: Lyndon Sanche <[email protected]>
> ---
> v4:
> - Make thermal_init and thermal_cleanup static
> - Rearrange order of added includes, did not edit current includes
> - Include bits.h
> - Switch comment style
> - Return error if platform_profile registering failed
> - Add thermal calls to call_blacklist
> - Align defines with tabs
> - Correct separation of function and error handling
> - Propagate error codes up
> v3:
> - Convert smbios-thermal-ctl docs to multiline comment and wrap
> - Change thermal_mode_bits enum to directly be BIT() values
> - Convert related code to use this
> - Use FIELD_GET/PREP and GENNMASK for getting/setting thermal modes
> - Correct offset for getting current ACC mode, setting offset
> unchanged
> - Check if thermal_handler is allocated before freeing and
> unregistering platform_profile
> v2:
> - Wrap smbios-thermal-ctl comment
> - Return proper error code when invalid state returned
> - Simplify platform_profile_get returns
> - Propogate ENOMEM error
> ---
> drivers/platform/x86/dell/dell-laptop.c | 238 +++++++++++++++++++
> drivers/platform/x86/dell/dell-smbios-base.c | 2 +
> drivers/platform/x86/dell/dell-smbios.h | 1 +
> 3 files changed, 241 insertions(+)
>
> diff --git a/drivers/platform/x86/dell/dell-laptop.c b/drivers/platform/x86/dell/dell-laptop.c
> index 42f7de2b4522..530ee6079447 100644
> --- a/drivers/platform/x86/dell/dell-laptop.c
> +++ b/drivers/platform/x86/dell/dell-laptop.c
> @@ -27,6 +27,9 @@
> #include <linux/i8042.h>
> #include <linux/debugfs.h>
> #include <linux/seq_file.h>
> +#include <linux/bitfield.h>
> +#include <linux/bits.h>
> +#include <linux/platform_profile.h>
> #include <acpi/video.h>
> #include "dell-rbtn.h"
> #include "dell-smbios.h"
> @@ -95,6 +98,7 @@ static struct backlight_device *dell_backlight_device;
> static struct rfkill *wifi_rfkill;
> static struct rfkill *bluetooth_rfkill;
> static struct rfkill *wwan_rfkill;
> +static struct platform_profile_handler *thermal_handler;
> static bool force_rfkill;
> static bool micmute_led_registered;
> static bool mute_led_registered;
> @@ -2199,6 +2203,232 @@ static int mute_led_set(struct led_classdev *led_cdev,
> return 0;
> }
>
> +/* Derived from smbios-thermal-ctl
> + *
> + * cbClass 17
> + * cbSelect 19
> + * User Selectable Thermal Tables(USTT)
> + * cbArg1 determines the function to be performed
> + * cbArg1 0x0 = Get Thermal Information
> + * cbRES1 Standard return codes (0, -1, -2)
> + * cbRES2, byte 0 Bitmap of supported thermal modes. A mode is supported if
> + * its bit is set to 1
> + * Bit 0 Balanced
> + * Bit 1 Cool Bottom
> + * Bit 2 Quiet
> + * Bit 3 Performance
> + * cbRES2, byte 1 Bitmap of supported Active Acoustic Controller (AAC) modes.
> + * Each mode corresponds to the supported thermal modes in
> + * byte 0. A mode is supported if its bit is set to 1.
> + * Bit 0 AAC (Balanced)
> + * Bit 1 AAC (Cool Bottom
> + * Bit 2 AAC (Quiet)
> + * Bit 3 AAC (Performance)
> + * cbRes3, byte 0 Current Thermal Mode
> + * Bit 0 Balanced
> + * Bit 1 Cool Bottom
> + * Bit 2 Quiet
> + * Bit 3 Performanc
> + * cbRes3, byte 1 AAC Configuration type
> + * 0 Global (AAC enable/disable applies to all supported USTT modes)
> + * 1 USTT mode specific
> + * cbRes3, byte 2 Current Active Acoustic Controller (AAC) Mode
> + * If AAC Configuration Type is Global,
> + * 0 AAC mode disabled
> + * 1 AAC mode enabled
> + * If AAC Configuration Type is USTT mode specific (multiple bits may be set),
> + * Bit 0 AAC (Balanced)
> + * Bit 1 AAC (Cool Bottom
> + * Bit 2 AAC (Quiet)
> + * Bit 3 AAC (Performance)
> + * cbRes3, byte 3 Current Fan Failure Mode
> + * Bit 0 Minimal Fan Failure (at least one fan has failed, one fan working)
> + * Bit 1 Catastrophic Fan Failure (all fans have failed)
> + * cbArg1 0x1 (Set Thermal Information), both desired thermal mode and

Broken indentation. cbArg1 should have only one space after "*" and be
at the same level as the previous cbArg1 description.

And I would suggest to add a newline before cbArg1 as it start
description of the next command.

> + * desired AAC mode shall be applied
> + * cbArg2, byte 0 Desired Thermal Mode to set
> + * (only one bit may be set for this parameter)
> + * Bit 0 Balanced
> + * Bit 1 Cool Bottom
> + * Bit 2 Quiet
> + * Bit 3 Performance
> + * cbArg2, byte 1 Desired Active Acoustic Controller (AAC) Mode to set
> + * If AAC Configuration Type is Global,
> + * 0 AAC mode disabled
> + * 1 AAC mode enabled
> + *

And here I would suggest to remove empty line as the comment below
belongs to the AAC description above the empty line.

> + * If AAC Configuration Type is USTT mode specific
> + * (multiple bits may be set for this parameter),
> + * Bit 0 AAC (Balanced)
> + * Bit 1 AAC (Cool Bottom
> + * Bit 2 AAC (Quiet)
> + * Bit 3 AAC (Performance)
> + */
> +
> +#define DELL_ACC_GET_FIELD GENMASK(19, 16)
> +#define DELL_ACC_SET_FIELD GENMASK(11, 8)
> +#define DELL_THERMAL_SUPPORTED GENMASK(3, 0)
> +
> +enum thermal_mode_bits {
> + DELL_BALANCED = BIT(0),
> + DELL_COOL_BOTTOM = BIT(1),
> + DELL_QUIET = BIT(2),
> + DELL_PERFORMANCE = BIT(3),
> +};
> +
> +static int thermal_get_mode(void)
> +{
> + struct calling_interface_buffer buffer;
> + int state;
> + int ret;
> +
> + dell_fill_request(&buffer, 0x0, 0, 0, 0);
> + ret = dell_send_request(&buffer, CLASS_INFO, SELECT_THERMAL_MANAGEMENT);
> + if (ret)
> + return ret;
> + state = buffer.output[2];
> + if (state & DELL_BALANCED)
> + return DELL_BALANCED;
> + else if (state & DELL_COOL_BOTTOM)
> + return DELL_COOL_BOTTOM;
> + else if (state & DELL_QUIET)
> + return DELL_QUIET;
> + else if (state & DELL_PERFORMANCE)
> + return DELL_PERFORMANCE;
> + else
> + return -ENXIO;
> +}
> +
> +static int thermal_get_supported_modes(int *supported_bits)
> +{
> + struct calling_interface_buffer buffer;
> + int ret;
> +
> + dell_fill_request(&buffer, 0x0, 0, 0, 0);
> + ret = dell_send_request(&buffer, CLASS_INFO, SELECT_THERMAL_MANAGEMENT);
> + if (ret)
> + return ret;
> + *supported_bits = FIELD_GET(DELL_THERMAL_SUPPORTED, buffer.output[1]);
> + return 0;
> +}
> +
> +static int thermal_get_acc_mode(int *acc_mode)
> +{
> + struct calling_interface_buffer buffer;
> + int ret;
> +
> + dell_fill_request(&buffer, 0x0, 0, 0, 0);
> + ret = dell_send_request(&buffer, CLASS_INFO, SELECT_THERMAL_MANAGEMENT);
> + if (ret)
> + return ret;
> + *acc_mode = FIELD_GET(DELL_ACC_GET_FIELD, buffer.output[3]);
> + return 0;
> +}
> +
> +static int thermal_set_mode(enum thermal_mode_bits state)
> +{
> + struct calling_interface_buffer buffer;
> + int ret;
> + int acc_mode;
> +
> + ret = thermal_get_acc_mode(&acc_mode);
> + if (ret)
> + return ret;
> +
> + dell_fill_request(&buffer, 0x1, FIELD_PREP(DELL_ACC_SET_FIELD, acc_mode) | state, 0, 0);
> + ret = dell_send_request(&buffer, CLASS_INFO, SELECT_THERMAL_MANAGEMENT);
> + return ret;
> +}
> +
> +static int thermal_platform_profile_set(struct platform_profile_handler *pprof,
> + enum platform_profile_option profile)
> +{
> + switch (profile) {
> + case PLATFORM_PROFILE_BALANCED:
> + return thermal_set_mode(DELL_BALANCED);
> + case PLATFORM_PROFILE_PERFORMANCE:
> + return thermal_set_mode(DELL_PERFORMANCE);
> + case PLATFORM_PROFILE_QUIET:
> + return thermal_set_mode(DELL_QUIET);
> + case PLATFORM_PROFILE_COOL:
> + return thermal_set_mode(DELL_COOL_BOTTOM);
> + default:
> + return -EOPNOTSUPP;
> + }
> +}
> +
> +static int thermal_platform_profile_get(struct platform_profile_handler *pprof,
> + enum platform_profile_option *profile)
> +{
> + int ret;
> +
> + ret = thermal_get_mode();
> + if (ret < 0)
> + return ret;
> +
> + switch (ret) {
> + case DELL_BALANCED:
> + *profile = PLATFORM_PROFILE_BALANCED;
> + break;
> + case DELL_PERFORMANCE:
> + *profile = PLATFORM_PROFILE_PERFORMANCE;
> + break;
> + case DELL_COOL_BOTTOM:
> + *profile = PLATFORM_PROFILE_COOL;
> + break;
> + case DELL_QUIET:
> + *profile = PLATFORM_PROFILE_QUIET;
> + break;
> + default:
> + return -EINVAL;
> + }
> +
> + return 0;
> +}
> +
> +static int thermal_init(void)
> +{
> + int ret;
> + int supported_modes;
> +
> + /* If thermal modes not supported, exit without error */
> + ret = thermal_get_supported_modes(&supported_modes);
> + if (ret < 0)
> + return ret;
> + if (!supported_modes)
> + return 0;
> +
> + thermal_handler = kzalloc(sizeof(*thermal_handler), GFP_KERNEL);
> + if (!thermal_handler)
> + return -ENOMEM;
> + thermal_handler->profile_get = thermal_platform_profile_get;
> + thermal_handler->profile_set = thermal_platform_profile_set;
> +
> + if (supported_modes & DELL_QUIET)
> + set_bit(PLATFORM_PROFILE_QUIET, thermal_handler->choices);
> + if (supported_modes & DELL_COOL_BOTTOM)
> + set_bit(PLATFORM_PROFILE_COOL, thermal_handler->choices);
> + if (supported_modes & DELL_BALANCED)
> + set_bit(PLATFORM_PROFILE_BALANCED, thermal_handler->choices);
> + if (supported_modes & DELL_PERFORMANCE)
> + set_bit(PLATFORM_PROFILE_PERFORMANCE, thermal_handler->choices);
> +
> + /* Clean up if failed */
> + ret = platform_profile_register(thermal_handler);
> + if (ret)
> + kfree(thermal_handler);
> +
> + return ret;
> +}
> +
> +static void thermal_cleanup(void)
> +{
> + if (thermal_handler) {
> + platform_profile_remove();
> + kfree(thermal_handler);
> + }
> +}
> +
> static struct led_classdev mute_led_cdev = {
> .name = "platform::mute",
> .max_brightness = 1,
> @@ -2238,6 +2468,11 @@ static int __init dell_init(void)
> goto fail_rfkill;
> }
>
> + /* Do not fail module if thermal modes not supported, just skip */
> + ret = thermal_init();
> + if (ret)
> + goto fail_thermal;
> +
> if (quirks && quirks->touchpad_led)
> touchpad_led_init(&platform_device->dev);
>
> @@ -2317,6 +2552,8 @@ static int __init dell_init(void)
> led_classdev_unregister(&mute_led_cdev);
> fail_led:
> dell_cleanup_rfkill();
> +fail_thermal:
> + thermal_cleanup();
> fail_rfkill:
> platform_device_del(platform_device);
> fail_platform_device2:
> @@ -2344,6 +2581,7 @@ static void __exit dell_exit(void)
> platform_device_unregister(platform_device);
> platform_driver_unregister(&platform_driver);
> }
> + thermal_cleanup();
> }
>
> /* dell-rbtn.c driver export functions which will not work correctly (and could
> diff --git a/drivers/platform/x86/dell/dell-smbios-base.c b/drivers/platform/x86/dell/dell-smbios-base.c
> index e61bfaf8b5c4..40aa4469b38b 100644
> --- a/drivers/platform/x86/dell/dell-smbios-base.c
> +++ b/drivers/platform/x86/dell/dell-smbios-base.c
> @@ -9,6 +9,7 @@
> * Based on documentation in the libsmbios package:
> * Copyright (C) 2005-2014 Dell Inc.
> */
> +#include "linux/wmi.h"

Is this include file really used? Because only SELECT_THERMAL_MANAGEMENT
was added and it is in the dell-smbios.h. And others constants like
SELECT_KBD_BACKLIGHT did not needed it.

> #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
>
> #include <linux/kernel.h>
> @@ -71,6 +72,7 @@ static struct smbios_call call_blacklist[] = {
> /* handled by kernel: dell-laptop */
> {0x0000, CLASS_INFO, SELECT_RFKILL},
> {0x0000, CLASS_KBD_BACKLIGHT, SELECT_KBD_BACKLIGHT},
> + {0x0000, CLASS_INFO, SELECT_THERMAL_MANAGEMENT},
> };
>
> struct token_range {
> diff --git a/drivers/platform/x86/dell/dell-smbios.h b/drivers/platform/x86/dell/dell-smbios.h
> index eb341bf000c6..585d042f1779 100644
> --- a/drivers/platform/x86/dell/dell-smbios.h
> +++ b/drivers/platform/x86/dell/dell-smbios.h
> @@ -19,6 +19,7 @@
> /* Classes and selects used only in kernel drivers */
> #define CLASS_KBD_BACKLIGHT 4
> #define SELECT_KBD_BACKLIGHT 11
> +#define SELECT_THERMAL_MANAGEMENT 19
>
> /* Tokens used in kernel drivers, any of these
> * should be filtered from userspace access
> --
> 2.42.0
>

2024-05-01 01:43:10

by Lyndon Sanche

[permalink] [raw]
Subject: Re: [PATCH v4] platform/x86: dell-laptop: Implement platform_profile

On Tue, Apr 30, 2024, at 7:36 PM, Pali Rohár wrote:
> On Tuesday 30 April 2024 19:14:52 Lyndon Sanche wrote:
>> + * Bit 2 AAC (Quiet)
>> + * Bit 3 AAC (Performance)
>> + * cbRes3, byte 3 Current Fan Failure Mode
>> + * Bit 0 Minimal Fan Failure (at least one fan has failed, one fan working)
>> + * Bit 1 Catastrophic Fan Failure (all fans have failed)
>> + * cbArg1 0x1 (Set Thermal Information), both desired thermal mode and
>
> Broken indentation. cbArg1 should have only one space after "*" and be
> at the same level as the previous cbArg1 description.
>
> And I would suggest to add a newline before cbArg1 as it start
> description of the next command.
>

I will fix this.

>> + * desired AAC mode shall be applied
>> + * cbArg2, byte 0 Desired Thermal Mode to set
>> + * (only one bit may be set for this parameter)
>> + * Bit 0 Balanced
>> + * Bit 1 Cool Bottom
>> + * Bit 2 Quiet
>> + * Bit 3 Performance
>> + * cbArg2, byte 1 Desired Active Acoustic Controller (AAC) Mode to set
>> + * If AAC Configuration Type is Global,
>> + * 0 AAC mode disabled
>> + * 1 AAC mode enabled
>> + *
>
> And here I would suggest to remove empty line as the comment below
> belongs to the AAC description above the empty line.
>

Agreed.

>>
>> /* dell-rbtn.c driver export functions which will not work correctly (and could
>> diff --git a/drivers/platform/x86/dell/dell-smbios-base.c b/drivers/platform/x86/dell/dell-smbios-base.c
>> index e61bfaf8b5c4..40aa4469b38b 100644
>> --- a/drivers/platform/x86/dell/dell-smbios-base.c
>> +++ b/drivers/platform/x86/dell/dell-smbios-base.c
>> @@ -9,6 +9,7 @@
>> * Based on documentation in the libsmbios package:
>> * Copyright (C) 2005-2014 Dell Inc.
>> */
>> +#include "linux/wmi.h"
>
> Is this include file really used? Because only SELECT_THERMAL_MANAGEMENT
> was added and it is in the dell-smbios.h. And others constants like
> SELECT_KBD_BACKLIGHT did not needed it.
>

No it is not. It seems my IDE automatically inserted this. I glossed over it when committing it seems.

Thank you for your quick feedback.

Lyndon

2024-05-01 08:17:43

by kernel test robot

[permalink] [raw]
Subject: Re: [PATCH v3] platform/x86: dell-laptop: Implement platform_profile

Hi Lyndon,

kernel test robot noticed the following build warnings:

[auto build test WARNING on linus/master]
[also build test WARNING on v6.9-rc6 next-20240430]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]

url: https://github.com/intel-lab-lkp/linux/commits/Lyndon-Sanche/platform-x86-dell-laptop-Implement-platform_profile/20240430-135932
base: linus/master
patch link: https://lore.kernel.org/r/20240429164844.7544-2-lsanche%40lyndeno.ca
patch subject: [PATCH v3] platform/x86: dell-laptop: Implement platform_profile
config: i386-buildonly-randconfig-001-20240501 (https://download.01.org/0day-ci/archive/20240501/[email protected]/config)
compiler: clang version 18.1.4 (https://github.com/llvm/llvm-project e6c3289804a67ea0bb6a86fadbe454dd93b8d855)
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20240501/[email protected]/reproduce)

If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <[email protected]>
| Closes: https://lore.kernel.org/oe-kbuild-all/[email protected]/

All warnings (new ones prefixed by >>):

>> drivers/platform/x86/dell/dell-laptop.c:2387:5: warning: no previous prototype for function 'thermal_init' [-Wmissing-prototypes]
2387 | int thermal_init(void)
| ^
drivers/platform/x86/dell/dell-laptop.c:2387:1: note: declare 'static' if the function is not intended to be used outside of this translation unit
2387 | int thermal_init(void)
| ^
| static
>> drivers/platform/x86/dell/dell-laptop.c:2418:6: warning: no previous prototype for function 'thermal_cleanup' [-Wmissing-prototypes]
2418 | void thermal_cleanup(void)
| ^
drivers/platform/x86/dell/dell-laptop.c:2418:1: note: declare 'static' if the function is not intended to be used outside of this translation unit
2418 | void thermal_cleanup(void)
| ^
| static
2 warnings generated.


vim +/thermal_init +2387 drivers/platform/x86/dell/dell-laptop.c

2386
> 2387 int thermal_init(void)
2388 {
2389 int ret;
2390 int supported_modes;
2391
2392 ret = thermal_get_supported_modes(&supported_modes);
2393 if (ret || !supported_modes)
2394 return 0;
2395
2396 thermal_handler = kzalloc(sizeof(*thermal_handler), GFP_KERNEL);
2397 if (!thermal_handler)
2398 return -ENOMEM;
2399 thermal_handler->profile_get = thermal_platform_profile_get;
2400 thermal_handler->profile_set = thermal_platform_profile_set;
2401
2402 if (supported_modes & DELL_QUIET)
2403 set_bit(PLATFORM_PROFILE_QUIET, thermal_handler->choices);
2404 if (supported_modes & DELL_COOL_BOTTOM)
2405 set_bit(PLATFORM_PROFILE_COOL, thermal_handler->choices);
2406 if (supported_modes & DELL_BALANCED)
2407 set_bit(PLATFORM_PROFILE_BALANCED, thermal_handler->choices);
2408 if (supported_modes & DELL_PERFORMANCE)
2409 set_bit(PLATFORM_PROFILE_PERFORMANCE, thermal_handler->choices);
2410
2411 // Clean up but do not fail
2412 if (platform_profile_register(thermal_handler))
2413 kfree(thermal_handler);
2414
2415 return 0;
2416 }
2417
> 2418 void thermal_cleanup(void)
2419 {
2420 if (thermal_handler) {
2421 platform_profile_remove();
2422 kfree(thermal_handler);
2423 }
2424 }
2425

--
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki

2024-05-01 16:36:06

by kernel test robot

[permalink] [raw]
Subject: Re: [PATCH v3] platform/x86: dell-laptop: Implement platform_profile

Hi Lyndon,

kernel test robot noticed the following build errors:

[auto build test ERROR on linus/master]
[also build test ERROR on v6.9-rc6 next-20240501]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]

url: https://github.com/intel-lab-lkp/linux/commits/Lyndon-Sanche/platform-x86-dell-laptop-Implement-platform_profile/20240430-135932
base: linus/master
patch link: https://lore.kernel.org/r/20240429164844.7544-2-lsanche%40lyndeno.ca
patch subject: [PATCH v3] platform/x86: dell-laptop: Implement platform_profile
config: x86_64-buildonly-randconfig-001-20240501 (https://download.01.org/0day-ci/archive/20240502/[email protected]/config)
compiler: gcc-9 (Ubuntu 9.5.0-4ubuntu2) 9.5.0
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20240502/[email protected]/reproduce)

If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <[email protected]>
| Closes: https://lore.kernel.org/oe-kbuild-all/[email protected]/

All errors (new ones prefixed by >>, old ones prefixed by <<):

WARNING: modpost: missing MODULE_DESCRIPTION() in drivers/gpu/drm/tests/drm_probe_helper_test.o
WARNING: modpost: missing MODULE_DESCRIPTION() in drivers/gpu/drm/tests/drm_rect_test.o
WARNING: modpost: missing MODULE_DESCRIPTION() in drivers/gpu/drm/gud/gud.o
WARNING: modpost: missing MODULE_DESCRIPTION() in drivers/gpu/drm/udl/udl.o
WARNING: modpost: missing MODULE_DESCRIPTION() in drivers/base/regmap/regmap-kunit.o
WARNING: modpost: missing MODULE_DESCRIPTION() in drivers/base/regmap/regmap-ram.o
WARNING: modpost: missing MODULE_DESCRIPTION() in drivers/base/regmap/regmap-raw-ram.o
WARNING: modpost: missing MODULE_DESCRIPTION() in drivers/base/regmap/regmap-spmi.o
WARNING: modpost: missing MODULE_DESCRIPTION() in drivers/mfd/pcf50633-gpio.o
WARNING: modpost: missing MODULE_DESCRIPTION() in drivers/dax/dax.o
WARNING: modpost: missing MODULE_DESCRIPTION() in drivers/firewire/firewire-uapi-test.o
WARNING: modpost: missing MODULE_DESCRIPTION() in drivers/usb/misc/isight_firmware.o
WARNING: modpost: missing MODULE_DESCRIPTION() in drivers/usb/mon/usbmon.o
WARNING: modpost: missing MODULE_DESCRIPTION() in drivers/usb/chipidea/ci_hdrc_msm.o
WARNING: modpost: missing MODULE_DESCRIPTION() in drivers/usb/gadget/libcomposite.o
WARNING: modpost: missing MODULE_DESCRIPTION() in drivers/usb/gadget/function/usb_f_acm.o
WARNING: modpost: missing MODULE_DESCRIPTION() in drivers/usb/gadget/function/usb_f_ss_lb.o
WARNING: modpost: missing MODULE_DESCRIPTION() in drivers/usb/gadget/function/u_serial.o
WARNING: modpost: missing MODULE_DESCRIPTION() in drivers/usb/gadget/function/usb_f_serial.o
WARNING: modpost: missing MODULE_DESCRIPTION() in drivers/usb/gadget/function/u_ether.o
WARNING: modpost: missing MODULE_DESCRIPTION() in drivers/usb/gadget/function/usb_f_ncm.o
WARNING: modpost: missing MODULE_DESCRIPTION() in drivers/usb/gadget/function/usb_f_ecm.o
WARNING: modpost: missing MODULE_DESCRIPTION() in drivers/usb/gadget/function/usb_f_mass_storage.o
WARNING: modpost: missing MODULE_DESCRIPTION() in drivers/usb/gadget/function/usb_f_printer.o
WARNING: modpost: missing MODULE_DESCRIPTION() in drivers/usb/gadget/function/usb_f_tcm.o
WARNING: modpost: missing MODULE_DESCRIPTION() in drivers/usb/gadget/legacy/g_zero.o
WARNING: modpost: missing MODULE_DESCRIPTION() in drivers/input/touchscreen/cyttsp_i2c_common.o
WARNING: modpost: missing MODULE_DESCRIPTION() in drivers/input/tests/input_test.o
WARNING: modpost: missing MODULE_DESCRIPTION() in drivers/rtc/lib_test.o
WARNING: modpost: missing MODULE_DESCRIPTION() in drivers/rtc/rtc-goldfish.o
WARNING: modpost: missing MODULE_DESCRIPTION() in drivers/i2c/busses/i2c-ali1563.o
WARNING: modpost: missing MODULE_DESCRIPTION() in drivers/hwmon/corsair-cpro.o
WARNING: modpost: missing MODULE_DESCRIPTION() in drivers/watchdog/menz69_wdt.o
WARNING: modpost: missing MODULE_DESCRIPTION() in drivers/mmc/core/mmc_core.o
WARNING: modpost: missing MODULE_DESCRIPTION() in drivers/mmc/core/sdio_uart.o
WARNING: modpost: missing MODULE_DESCRIPTION() in drivers/hid/hid.o
WARNING: modpost: missing MODULE_DESCRIPTION() in drivers/hid/hid-a4tech.o
WARNING: modpost: missing MODULE_DESCRIPTION() in drivers/hid/hid-apple.o
WARNING: modpost: missing MODULE_DESCRIPTION() in drivers/hid/hid-aureal.o
WARNING: modpost: missing MODULE_DESCRIPTION() in drivers/hid/hid-betopff.o
WARNING: modpost: missing MODULE_DESCRIPTION() in drivers/hid/hid-bigbenff.o
WARNING: modpost: missing MODULE_DESCRIPTION() in drivers/hid/hid-cherry.o
WARNING: modpost: missing MODULE_DESCRIPTION() in drivers/hid/hid-chicony.o
WARNING: modpost: missing MODULE_DESCRIPTION() in drivers/hid/hid-dr.o
WARNING: modpost: missing MODULE_DESCRIPTION() in drivers/hid/hid-emsff.o
WARNING: modpost: missing MODULE_DESCRIPTION() in drivers/hid/hid-elecom.o
WARNING: modpost: missing MODULE_DESCRIPTION() in drivers/hid/hid-elo.o
WARNING: modpost: missing MODULE_DESCRIPTION() in drivers/hid/hid-holtek-kbd.o
WARNING: modpost: missing MODULE_DESCRIPTION() in drivers/hid/hid-holtek-mouse.o
WARNING: modpost: missing MODULE_DESCRIPTION() in drivers/hid/hid-ite.o
WARNING: modpost: missing MODULE_DESCRIPTION() in drivers/hid/hid-keytouch.o
WARNING: modpost: missing MODULE_DESCRIPTION() in drivers/hid/hid-lcpower.o
WARNING: modpost: missing MODULE_DESCRIPTION() in drivers/hid/hid-letsketch.o
WARNING: modpost: missing MODULE_DESCRIPTION() in drivers/hid/hid-logitech.o
WARNING: modpost: missing MODULE_DESCRIPTION() in drivers/hid/hid-lg-g15.o
WARNING: modpost: missing MODULE_DESCRIPTION() in drivers/hid/hid-magicmouse.o
WARNING: modpost: missing MODULE_DESCRIPTION() in drivers/hid/hid-maltron.o
WARNING: modpost: missing MODULE_DESCRIPTION() in drivers/hid/hid-mf.o
WARNING: modpost: missing MODULE_DESCRIPTION() in drivers/hid/hid-megaworld.o
WARNING: modpost: missing MODULE_DESCRIPTION() in drivers/hid/hid-microsoft.o
WARNING: modpost: missing MODULE_DESCRIPTION() in drivers/hid/hid-ntrig.o
WARNING: modpost: missing MODULE_DESCRIPTION() in drivers/hid/hid-ortek.o
WARNING: modpost: missing MODULE_DESCRIPTION() in drivers/hid/hid-pl.o
WARNING: modpost: missing MODULE_DESCRIPTION() in drivers/hid/hid-razer.o
WARNING: modpost: missing MODULE_DESCRIPTION() in drivers/hid/hid-redragon.o
WARNING: modpost: missing MODULE_DESCRIPTION() in drivers/hid/hid-retrode.o
WARNING: modpost: missing MODULE_DESCRIPTION() in drivers/hid/hid-saitek.o
WARNING: modpost: missing MODULE_DESCRIPTION() in drivers/hid/hid-semitek.o
WARNING: modpost: missing MODULE_DESCRIPTION() in drivers/hid/hid-sony.o
WARNING: modpost: missing MODULE_DESCRIPTION() in drivers/hid/hid-speedlink.o
WARNING: modpost: missing MODULE_DESCRIPTION() in drivers/hid/hid-steam.o
WARNING: modpost: missing MODULE_DESCRIPTION() in drivers/hid/hid-steelseries.o
WARNING: modpost: missing MODULE_DESCRIPTION() in drivers/hid/hid-sunplus.o
WARNING: modpost: missing MODULE_DESCRIPTION() in drivers/hid/hid-gaff.o
WARNING: modpost: missing MODULE_DESCRIPTION() in drivers/hid/hid-tmff.o
WARNING: modpost: missing MODULE_DESCRIPTION() in drivers/hid/hid-tivo.o
WARNING: modpost: missing MODULE_DESCRIPTION() in drivers/hid/hid-twinhan.o
WARNING: modpost: missing MODULE_DESCRIPTION() in drivers/hid/hid-uclogic.o
WARNING: modpost: missing MODULE_DESCRIPTION() in drivers/hid/hid-zydacron.o
WARNING: modpost: missing MODULE_DESCRIPTION() in drivers/hid/hid-waltop.o
WARNING: modpost: missing MODULE_DESCRIPTION() in drivers/greybus/gb-es2.o
WARNING: modpost: missing MODULE_DESCRIPTION() in drivers/staging/greybus/gb-bootrom.o
WARNING: modpost: missing MODULE_DESCRIPTION() in drivers/staging/greybus/gb-hid.o
WARNING: modpost: missing MODULE_DESCRIPTION() in drivers/staging/greybus/gb-loopback.o
WARNING: modpost: missing MODULE_DESCRIPTION() in drivers/staging/greybus/gb-power-supply.o
WARNING: modpost: missing MODULE_DESCRIPTION() in drivers/staging/greybus/gb-gbphy.o
WARNING: modpost: missing MODULE_DESCRIPTION() in drivers/staging/greybus/gb-gpio.o
WARNING: modpost: missing MODULE_DESCRIPTION() in drivers/staging/greybus/gb-usb.o
WARNING: modpost: missing MODULE_DESCRIPTION() in drivers/platform/x86/intel/speed_select_if/isst_if_common.o
WARNING: modpost: missing MODULE_DESCRIPTION() in drivers/platform/goldfish/goldfish_pipe.o
WARNING: modpost: missing MODULE_DESCRIPTION() in drivers/devfreq/governor_powersave.o
WARNING: modpost: missing MODULE_DESCRIPTION() in drivers/hwtracing/intel_th/intel_th_msu_sink.o
WARNING: modpost: missing MODULE_DESCRIPTION() in drivers/siox/siox-bus-gpio.o
WARNING: modpost: missing MODULE_DESCRIPTION() in drivers/uio/uio.o
WARNING: modpost: missing MODULE_DESCRIPTION() in drivers/uio/uio_cif.o
WARNING: modpost: missing MODULE_DESCRIPTION() in drivers/uio/uio_netx.o
WARNING: modpost: missing MODULE_DESCRIPTION() in drivers/dca/dca.o
WARNING: modpost: missing MODULE_DESCRIPTION() in samples/configfs/configfs_sample.o
WARNING: modpost: missing MODULE_DESCRIPTION() in samples/kprobes/kprobe_example.o
WARNING: modpost: missing MODULE_DESCRIPTION() in samples/kprobes/kretprobe_example.o
>> ERROR: modpost: "platform_profile_register" [drivers/platform/x86/dell/dell-laptop.ko] undefined!
>> ERROR: modpost: "platform_profile_remove" [drivers/platform/x86/dell/dell-laptop.ko] undefined!

--
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki

2024-05-01 17:08:48

by kernel test robot

[permalink] [raw]
Subject: Re: [PATCH v3] platform/x86: dell-laptop: Implement platform_profile

Hi Lyndon,

kernel test robot noticed the following build warnings:

[auto build test WARNING on linus/master]
[also build test WARNING on v6.9-rc6 next-20240501]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]

url: https://github.com/intel-lab-lkp/linux/commits/Lyndon-Sanche/platform-x86-dell-laptop-Implement-platform_profile/20240430-135932
base: linus/master
patch link: https://lore.kernel.org/r/20240429164844.7544-2-lsanche%40lyndeno.ca
patch subject: [PATCH v3] platform/x86: dell-laptop: Implement platform_profile
config: x86_64-randconfig-r122-20240501 (https://download.01.org/0day-ci/archive/20240502/[email protected]/config)
compiler: clang version 18.1.4 (https://github.com/llvm/llvm-project e6c3289804a67ea0bb6a86fadbe454dd93b8d855)
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20240502/[email protected]/reproduce)

If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <[email protected]>
| Closes: https://lore.kernel.org/oe-kbuild-all/[email protected]/

sparse warnings: (new ones prefixed by >>)
>> drivers/platform/x86/dell/dell-laptop.c:2418:6: sparse: sparse: symbol 'thermal_cleanup' was not declared. Should it be static?

vim +/thermal_cleanup +2418 drivers/platform/x86/dell/dell-laptop.c

2386
> 2387 int thermal_init(void)
2388 {
2389 int ret;
2390 int supported_modes;
2391
2392 ret = thermal_get_supported_modes(&supported_modes);
2393 if (ret || !supported_modes)
2394 return 0;
2395
2396 thermal_handler = kzalloc(sizeof(*thermal_handler), GFP_KERNEL);
2397 if (!thermal_handler)
2398 return -ENOMEM;
2399 thermal_handler->profile_get = thermal_platform_profile_get;
2400 thermal_handler->profile_set = thermal_platform_profile_set;
2401
2402 if (supported_modes & DELL_QUIET)
2403 set_bit(PLATFORM_PROFILE_QUIET, thermal_handler->choices);
2404 if (supported_modes & DELL_COOL_BOTTOM)
2405 set_bit(PLATFORM_PROFILE_COOL, thermal_handler->choices);
2406 if (supported_modes & DELL_BALANCED)
2407 set_bit(PLATFORM_PROFILE_BALANCED, thermal_handler->choices);
2408 if (supported_modes & DELL_PERFORMANCE)
2409 set_bit(PLATFORM_PROFILE_PERFORMANCE, thermal_handler->choices);
2410
2411 // Clean up but do not fail
2412 if (platform_profile_register(thermal_handler))
2413 kfree(thermal_handler);
2414
2415 return 0;
2416 }
2417
> 2418 void thermal_cleanup(void)
2419 {
2420 if (thermal_handler) {
2421 platform_profile_remove();
2422 kfree(thermal_handler);
2423 }
2424 }
2425

--
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki

2024-05-01 21:59:46

by Lyndon Sanche

[permalink] [raw]
Subject: [PATCH v5] platform/x86: dell-laptop: Implement platform_profile

Some Dell laptops support configuration of preset fan modes through
smbios tables.

If the platform supports these fan modes, set up platform_profile to
change these modes. If not supported, skip enabling platform_profile.

Signed-off-by: Lyndon Sanche <[email protected]>
---
v5:
- Fix indent in smbios-thermal-ctl comment
- Remove linux/wmi.h include
- Add 'select ACPI_PLATFORM_PROFILE' to Dell KConfig
v4:
- Make thermal_init and thermal_cleanup static
- Rearrange order of added includes, did not edit current includes
- Include bits.h
- Switch comment style
- Return error if platform_profile registering failed
- Add thermal calls to call_blacklist
- Align defines with tabs
- Correct separation of function and error handling
- Propagate error codes up
v3:
- Convert smbios-thermal-ctl docs to multiline comment and wrap
- Change thermal_mode_bits enum to directly be BIT() values
- Convert related code to use this
- Use FIELD_GET/PREP and GENNMASK for getting/setting thermal modes
- Correct offset for getting current ACC mode, setting offset
unchanged
- Check if thermal_handler is allocated before freeing and
unregistering platform_profile
v2:
- Wrap smbios-thermal-ctl comment
- Return proper error code when invalid state returned
- Simplify platform_profile_get returns
- Propogate ENOMEM error
---
drivers/platform/x86/dell/Kconfig | 1 +
drivers/platform/x86/dell/dell-laptop.c | 238 +++++++++++++++++++
drivers/platform/x86/dell/dell-smbios-base.c | 1 +
drivers/platform/x86/dell/dell-smbios.h | 1 +
4 files changed, 241 insertions(+)

diff --git a/drivers/platform/x86/dell/Kconfig b/drivers/platform/x86/dell/Kconfig
index bd9f445974cc..5195ad59b44d 100644
--- a/drivers/platform/x86/dell/Kconfig
+++ b/drivers/platform/x86/dell/Kconfig
@@ -57,6 +57,7 @@ config DELL_LAPTOP
select POWER_SUPPLY
select LEDS_CLASS
select NEW_LEDS
+ select ACPI_PLATFORM_PROFILE
help
This driver adds support for rfkill and backlight control to Dell
laptops (except for some models covered by the Compal driver).
diff --git a/drivers/platform/x86/dell/dell-laptop.c b/drivers/platform/x86/dell/dell-laptop.c
index 42f7de2b4522..dc530a4f5047 100644
--- a/drivers/platform/x86/dell/dell-laptop.c
+++ b/drivers/platform/x86/dell/dell-laptop.c
@@ -27,6 +27,9 @@
#include <linux/i8042.h>
#include <linux/debugfs.h>
#include <linux/seq_file.h>
+#include <linux/bitfield.h>
+#include <linux/bits.h>
+#include <linux/platform_profile.h>
#include <acpi/video.h>
#include "dell-rbtn.h"
#include "dell-smbios.h"
@@ -95,6 +98,7 @@ static struct backlight_device *dell_backlight_device;
static struct rfkill *wifi_rfkill;
static struct rfkill *bluetooth_rfkill;
static struct rfkill *wwan_rfkill;
+static struct platform_profile_handler *thermal_handler;
static bool force_rfkill;
static bool micmute_led_registered;
static bool mute_led_registered;
@@ -2199,6 +2203,232 @@ static int mute_led_set(struct led_classdev *led_cdev,
return 0;
}

+/* Derived from smbios-thermal-ctl
+ *
+ * cbClass 17
+ * cbSelect 19
+ * User Selectable Thermal Tables(USTT)
+ * cbArg1 determines the function to be performed
+ * cbArg1 0x0 = Get Thermal Information
+ * cbRES1 Standard return codes (0, -1, -2)
+ * cbRES2, byte 0 Bitmap of supported thermal modes. A mode is supported if
+ * its bit is set to 1
+ * Bit 0 Balanced
+ * Bit 1 Cool Bottom
+ * Bit 2 Quiet
+ * Bit 3 Performance
+ * cbRES2, byte 1 Bitmap of supported Active Acoustic Controller (AAC) modes.
+ * Each mode corresponds to the supported thermal modes in
+ * byte 0. A mode is supported if its bit is set to 1.
+ * Bit 0 AAC (Balanced)
+ * Bit 1 AAC (Cool Bottom
+ * Bit 2 AAC (Quiet)
+ * Bit 3 AAC (Performance)
+ * cbRes3, byte 0 Current Thermal Mode
+ * Bit 0 Balanced
+ * Bit 1 Cool Bottom
+ * Bit 2 Quiet
+ * Bit 3 Performanc
+ * cbRes3, byte 1 AAC Configuration type
+ * 0 Global (AAC enable/disable applies to all supported USTT modes)
+ * 1 USTT mode specific
+ * cbRes3, byte 2 Current Active Acoustic Controller (AAC) Mode
+ * If AAC Configuration Type is Global,
+ * 0 AAC mode disabled
+ * 1 AAC mode enabled
+ * If AAC Configuration Type is USTT mode specific (multiple bits may be set),
+ * Bit 0 AAC (Balanced)
+ * Bit 1 AAC (Cool Bottom
+ * Bit 2 AAC (Quiet)
+ * Bit 3 AAC (Performance)
+ * cbRes3, byte 3 Current Fan Failure Mode
+ * Bit 0 Minimal Fan Failure (at least one fan has failed, one fan working)
+ * Bit 1 Catastrophic Fan Failure (all fans have failed)
+ *
+ * cbArg1 0x1 (Set Thermal Information), both desired thermal mode and
+ * desired AAC mode shall be applied
+ * cbArg2, byte 0 Desired Thermal Mode to set
+ * (only one bit may be set for this parameter)
+ * Bit 0 Balanced
+ * Bit 1 Cool Bottom
+ * Bit 2 Quiet
+ * Bit 3 Performance
+ * cbArg2, byte 1 Desired Active Acoustic Controller (AAC) Mode to set
+ * If AAC Configuration Type is Global,
+ * 0 AAC mode disabled
+ * 1 AAC mode enabled
+ * If AAC Configuration Type is USTT mode specific
+ * (multiple bits may be set for this parameter),
+ * Bit 0 AAC (Balanced)
+ * Bit 1 AAC (Cool Bottom
+ * Bit 2 AAC (Quiet)
+ * Bit 3 AAC (Performance)
+ */
+
+#define DELL_ACC_GET_FIELD GENMASK(19, 16)
+#define DELL_ACC_SET_FIELD GENMASK(11, 8)
+#define DELL_THERMAL_SUPPORTED GENMASK(3, 0)
+
+enum thermal_mode_bits {
+ DELL_BALANCED = BIT(0),
+ DELL_COOL_BOTTOM = BIT(1),
+ DELL_QUIET = BIT(2),
+ DELL_PERFORMANCE = BIT(3),
+};
+
+static int thermal_get_mode(void)
+{
+ struct calling_interface_buffer buffer;
+ int state;
+ int ret;
+
+ dell_fill_request(&buffer, 0x0, 0, 0, 0);
+ ret = dell_send_request(&buffer, CLASS_INFO, SELECT_THERMAL_MANAGEMENT);
+ if (ret)
+ return ret;
+ state = buffer.output[2];
+ if (state & DELL_BALANCED)
+ return DELL_BALANCED;
+ else if (state & DELL_COOL_BOTTOM)
+ return DELL_COOL_BOTTOM;
+ else if (state & DELL_QUIET)
+ return DELL_QUIET;
+ else if (state & DELL_PERFORMANCE)
+ return DELL_PERFORMANCE;
+ else
+ return -ENXIO;
+}
+
+static int thermal_get_supported_modes(int *supported_bits)
+{
+ struct calling_interface_buffer buffer;
+ int ret;
+
+ dell_fill_request(&buffer, 0x0, 0, 0, 0);
+ ret = dell_send_request(&buffer, CLASS_INFO, SELECT_THERMAL_MANAGEMENT);
+ if (ret)
+ return ret;
+ *supported_bits = FIELD_GET(DELL_THERMAL_SUPPORTED, buffer.output[1]);
+ return 0;
+}
+
+static int thermal_get_acc_mode(int *acc_mode)
+{
+ struct calling_interface_buffer buffer;
+ int ret;
+
+ dell_fill_request(&buffer, 0x0, 0, 0, 0);
+ ret = dell_send_request(&buffer, CLASS_INFO, SELECT_THERMAL_MANAGEMENT);
+ if (ret)
+ return ret;
+ *acc_mode = FIELD_GET(DELL_ACC_GET_FIELD, buffer.output[3]);
+ return 0;
+}
+
+static int thermal_set_mode(enum thermal_mode_bits state)
+{
+ struct calling_interface_buffer buffer;
+ int ret;
+ int acc_mode;
+
+ ret = thermal_get_acc_mode(&acc_mode);
+ if (ret)
+ return ret;
+
+ dell_fill_request(&buffer, 0x1, FIELD_PREP(DELL_ACC_SET_FIELD, acc_mode) | state, 0, 0);
+ ret = dell_send_request(&buffer, CLASS_INFO, SELECT_THERMAL_MANAGEMENT);
+ return ret;
+}
+
+static int thermal_platform_profile_set(struct platform_profile_handler *pprof,
+ enum platform_profile_option profile)
+{
+ switch (profile) {
+ case PLATFORM_PROFILE_BALANCED:
+ return thermal_set_mode(DELL_BALANCED);
+ case PLATFORM_PROFILE_PERFORMANCE:
+ return thermal_set_mode(DELL_PERFORMANCE);
+ case PLATFORM_PROFILE_QUIET:
+ return thermal_set_mode(DELL_QUIET);
+ case PLATFORM_PROFILE_COOL:
+ return thermal_set_mode(DELL_COOL_BOTTOM);
+ default:
+ return -EOPNOTSUPP;
+ }
+}
+
+static int thermal_platform_profile_get(struct platform_profile_handler *pprof,
+ enum platform_profile_option *profile)
+{
+ int ret;
+
+ ret = thermal_get_mode();
+ if (ret < 0)
+ return ret;
+
+ switch (ret) {
+ case DELL_BALANCED:
+ *profile = PLATFORM_PROFILE_BALANCED;
+ break;
+ case DELL_PERFORMANCE:
+ *profile = PLATFORM_PROFILE_PERFORMANCE;
+ break;
+ case DELL_COOL_BOTTOM:
+ *profile = PLATFORM_PROFILE_COOL;
+ break;
+ case DELL_QUIET:
+ *profile = PLATFORM_PROFILE_QUIET;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int thermal_init(void)
+{
+ int ret;
+ int supported_modes;
+
+ /* If thermal modes not supported, exit without error */
+ ret = thermal_get_supported_modes(&supported_modes);
+ if (ret < 0)
+ return ret;
+ if (!supported_modes)
+ return 0;
+
+ thermal_handler = kzalloc(sizeof(*thermal_handler), GFP_KERNEL);
+ if (!thermal_handler)
+ return -ENOMEM;
+ thermal_handler->profile_get = thermal_platform_profile_get;
+ thermal_handler->profile_set = thermal_platform_profile_set;
+
+ if (supported_modes & DELL_QUIET)
+ set_bit(PLATFORM_PROFILE_QUIET, thermal_handler->choices);
+ if (supported_modes & DELL_COOL_BOTTOM)
+ set_bit(PLATFORM_PROFILE_COOL, thermal_handler->choices);
+ if (supported_modes & DELL_BALANCED)
+ set_bit(PLATFORM_PROFILE_BALANCED, thermal_handler->choices);
+ if (supported_modes & DELL_PERFORMANCE)
+ set_bit(PLATFORM_PROFILE_PERFORMANCE, thermal_handler->choices);
+
+ /* Clean up if failed */
+ ret = platform_profile_register(thermal_handler);
+ if (ret)
+ kfree(thermal_handler);
+
+ return ret;
+}
+
+static void thermal_cleanup(void)
+{
+ if (thermal_handler) {
+ platform_profile_remove();
+ kfree(thermal_handler);
+ }
+}
+
static struct led_classdev mute_led_cdev = {
.name = "platform::mute",
.max_brightness = 1,
@@ -2238,6 +2468,11 @@ static int __init dell_init(void)
goto fail_rfkill;
}

+ /* Do not fail module if thermal modes not supported, just skip */
+ ret = thermal_init();
+ if (ret)
+ goto fail_thermal;
+
if (quirks && quirks->touchpad_led)
touchpad_led_init(&platform_device->dev);

@@ -2317,6 +2552,8 @@ static int __init dell_init(void)
led_classdev_unregister(&mute_led_cdev);
fail_led:
dell_cleanup_rfkill();
+fail_thermal:
+ thermal_cleanup();
fail_rfkill:
platform_device_del(platform_device);
fail_platform_device2:
@@ -2344,6 +2581,7 @@ static void __exit dell_exit(void)
platform_device_unregister(platform_device);
platform_driver_unregister(&platform_driver);
}
+ thermal_cleanup();
}

/* dell-rbtn.c driver export functions which will not work correctly (and could
diff --git a/drivers/platform/x86/dell/dell-smbios-base.c b/drivers/platform/x86/dell/dell-smbios-base.c
index e61bfaf8b5c4..5bc2e394dd1c 100644
--- a/drivers/platform/x86/dell/dell-smbios-base.c
+++ b/drivers/platform/x86/dell/dell-smbios-base.c
@@ -71,6 +71,7 @@ static struct smbios_call call_blacklist[] = {
/* handled by kernel: dell-laptop */
{0x0000, CLASS_INFO, SELECT_RFKILL},
{0x0000, CLASS_KBD_BACKLIGHT, SELECT_KBD_BACKLIGHT},
+ {0x0000, CLASS_INFO, SELECT_THERMAL_MANAGEMENT},
};

struct token_range {
diff --git a/drivers/platform/x86/dell/dell-smbios.h b/drivers/platform/x86/dell/dell-smbios.h
index eb341bf000c6..585d042f1779 100644
--- a/drivers/platform/x86/dell/dell-smbios.h
+++ b/drivers/platform/x86/dell/dell-smbios.h
@@ -19,6 +19,7 @@
/* Classes and selects used only in kernel drivers */
#define CLASS_KBD_BACKLIGHT 4
#define SELECT_KBD_BACKLIGHT 11
+#define SELECT_THERMAL_MANAGEMENT 19

/* Tokens used in kernel drivers, any of these
* should be filtered from userspace access
--
2.42.0


2024-05-03 10:20:59

by kernel test robot

[permalink] [raw]
Subject: Re: [PATCH v5] platform/x86: dell-laptop: Implement platform_profile

Hi Lyndon,

kernel test robot noticed the following build warnings:

[auto build test WARNING on linus/master]
[also build test WARNING on v6.9-rc6 next-20240503]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]

url: https://github.com/intel-lab-lkp/linux/commits/Lyndon-Sanche/platform-x86-dell-laptop-Implement-platform_profile/20240502-060146
base: linus/master
patch link: https://lore.kernel.org/r/20240501215829.4991-2-lsanche%40lyndeno.ca
patch subject: [PATCH v5] platform/x86: dell-laptop: Implement platform_profile
config: i386-kismet-CONFIG_ACPI_PLATFORM_PROFILE-CONFIG_DELL_LAPTOP-0-0 (https://download.01.org/0day-ci/archive/20240503/[email protected]/config)
reproduce: (https://download.01.org/0day-ci/archive/20240503/[email protected]/reproduce)

If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <[email protected]>
| Closes: https://lore.kernel.org/oe-kbuild-all/[email protected]/

kismet warnings: (new ones prefixed by >>)
>> kismet: WARNING: unmet direct dependencies detected for ACPI_PLATFORM_PROFILE when selected by DELL_LAPTOP
WARNING: unmet direct dependencies detected for ACPI_PLATFORM_PROFILE
Depends on [n]: ACPI [=n]
Selected by [y]:
- DELL_LAPTOP [=y] && X86_PLATFORM_DEVICES [=y] && X86_PLATFORM_DRIVERS_DELL [=y] && DMI [=y] && BACKLIGHT_CLASS_DEVICE [=y] && (ACPI_VIDEO [=n] || ACPI_VIDEO [=n]=n) && (RFKILL [=n] || RFKILL [=n]=n) && (DELL_WMI [=n] || DELL_WMI [=n]=n) && SERIO_I8042 [=y] && DELL_SMBIOS [=y]

--
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki

2024-05-03 21:20:12

by Armin Wolf

[permalink] [raw]
Subject: Re: [PATCH v5] platform/x86: dell-laptop: Implement platform_profile

Am 01.05.24 um 23:58 schrieb Lyndon Sanche:

> Some Dell laptops support configuration of preset fan modes through
> smbios tables.
>
> If the platform supports these fan modes, set up platform_profile to
> change these modes. If not supported, skip enabling platform_profile.
>
> Signed-off-by: Lyndon Sanche <[email protected]>
> ---
> v5:
> - Fix indent in smbios-thermal-ctl comment
> - Remove linux/wmi.h include
> - Add 'select ACPI_PLATFORM_PROFILE' to Dell KConfig
> v4:
> - Make thermal_init and thermal_cleanup static
> - Rearrange order of added includes, did not edit current includes
> - Include bits.h
> - Switch comment style
> - Return error if platform_profile registering failed
> - Add thermal calls to call_blacklist
> - Align defines with tabs
> - Correct separation of function and error handling
> - Propagate error codes up
> v3:
> - Convert smbios-thermal-ctl docs to multiline comment and wrap
> - Change thermal_mode_bits enum to directly be BIT() values
> - Convert related code to use this
> - Use FIELD_GET/PREP and GENNMASK for getting/setting thermal modes
> - Correct offset for getting current ACC mode, setting offset
> unchanged
> - Check if thermal_handler is allocated before freeing and
> unregistering platform_profile
> v2:
> - Wrap smbios-thermal-ctl comment
> - Return proper error code when invalid state returned
> - Simplify platform_profile_get returns
> - Propogate ENOMEM error
> ---
> drivers/platform/x86/dell/Kconfig | 1 +
> drivers/platform/x86/dell/dell-laptop.c | 238 +++++++++++++++++++
> drivers/platform/x86/dell/dell-smbios-base.c | 1 +
> drivers/platform/x86/dell/dell-smbios.h | 1 +
> 4 files changed, 241 insertions(+)
>
> diff --git a/drivers/platform/x86/dell/Kconfig b/drivers/platform/x86/dell/Kconfig
> index bd9f445974cc..5195ad59b44d 100644
> --- a/drivers/platform/x86/dell/Kconfig
> +++ b/drivers/platform/x86/dell/Kconfig
> @@ -57,6 +57,7 @@ config DELL_LAPTOP
> select POWER_SUPPLY
> select LEDS_CLASS
> select NEW_LEDS
> + select ACPI_PLATFORM_PROFILE
> help
> This driver adds support for rfkill and backlight control to Dell
> laptops (except for some models covered by the Compal driver).
> diff --git a/drivers/platform/x86/dell/dell-laptop.c b/drivers/platform/x86/dell/dell-laptop.c
> index 42f7de2b4522..dc530a4f5047 100644
> --- a/drivers/platform/x86/dell/dell-laptop.c
> +++ b/drivers/platform/x86/dell/dell-laptop.c
> @@ -27,6 +27,9 @@
> #include <linux/i8042.h>
> #include <linux/debugfs.h>
> #include <linux/seq_file.h>
> +#include <linux/bitfield.h>
> +#include <linux/bits.h>
> +#include <linux/platform_profile.h>
> #include <acpi/video.h>
> #include "dell-rbtn.h"
> #include "dell-smbios.h"
> @@ -95,6 +98,7 @@ static struct backlight_device *dell_backlight_device;
> static struct rfkill *wifi_rfkill;
> static struct rfkill *bluetooth_rfkill;
> static struct rfkill *wwan_rfkill;
> +static struct platform_profile_handler *thermal_handler;
> static bool force_rfkill;
> static bool micmute_led_registered;
> static bool mute_led_registered;
> @@ -2199,6 +2203,232 @@ static int mute_led_set(struct led_classdev *led_cdev,
> return 0;
> }
>
> +/* Derived from smbios-thermal-ctl
> + *
> + * cbClass 17
> + * cbSelect 19
> + * User Selectable Thermal Tables(USTT)
> + * cbArg1 determines the function to be performed
> + * cbArg1 0x0 = Get Thermal Information
> + * cbRES1 Standard return codes (0, -1, -2)
> + * cbRES2, byte 0 Bitmap of supported thermal modes. A mode is supported if
> + * its bit is set to 1
> + * Bit 0 Balanced
> + * Bit 1 Cool Bottom
> + * Bit 2 Quiet
> + * Bit 3 Performance
> + * cbRES2, byte 1 Bitmap of supported Active Acoustic Controller (AAC) modes.
> + * Each mode corresponds to the supported thermal modes in
> + * byte 0. A mode is supported if its bit is set to 1.
> + * Bit 0 AAC (Balanced)
> + * Bit 1 AAC (Cool Bottom
> + * Bit 2 AAC (Quiet)
> + * Bit 3 AAC (Performance)
> + * cbRes3, byte 0 Current Thermal Mode
> + * Bit 0 Balanced
> + * Bit 1 Cool Bottom
> + * Bit 2 Quiet
> + * Bit 3 Performanc
> + * cbRes3, byte 1 AAC Configuration type
> + * 0 Global (AAC enable/disable applies to all supported USTT modes)
> + * 1 USTT mode specific
> + * cbRes3, byte 2 Current Active Acoustic Controller (AAC) Mode
> + * If AAC Configuration Type is Global,
> + * 0 AAC mode disabled
> + * 1 AAC mode enabled
> + * If AAC Configuration Type is USTT mode specific (multiple bits may be set),
> + * Bit 0 AAC (Balanced)
> + * Bit 1 AAC (Cool Bottom
> + * Bit 2 AAC (Quiet)
> + * Bit 3 AAC (Performance)
> + * cbRes3, byte 3 Current Fan Failure Mode
> + * Bit 0 Minimal Fan Failure (at least one fan has failed, one fan working)
> + * Bit 1 Catastrophic Fan Failure (all fans have failed)
> + *
> + * cbArg1 0x1 (Set Thermal Information), both desired thermal mode and
> + * desired AAC mode shall be applied
> + * cbArg2, byte 0 Desired Thermal Mode to set
> + * (only one bit may be set for this parameter)
> + * Bit 0 Balanced
> + * Bit 1 Cool Bottom
> + * Bit 2 Quiet
> + * Bit 3 Performance
> + * cbArg2, byte 1 Desired Active Acoustic Controller (AAC) Mode to set
> + * If AAC Configuration Type is Global,
> + * 0 AAC mode disabled
> + * 1 AAC mode enabled
> + * If AAC Configuration Type is USTT mode specific
> + * (multiple bits may be set for this parameter),
> + * Bit 0 AAC (Balanced)
> + * Bit 1 AAC (Cool Bottom
> + * Bit 2 AAC (Quiet)
> + * Bit 3 AAC (Performance)
> + */
> +
> +#define DELL_ACC_GET_FIELD GENMASK(19, 16)
> +#define DELL_ACC_SET_FIELD GENMASK(11, 8)
> +#define DELL_THERMAL_SUPPORTED GENMASK(3, 0)
> +
> +enum thermal_mode_bits {
> + DELL_BALANCED = BIT(0),
> + DELL_COOL_BOTTOM = BIT(1),
> + DELL_QUIET = BIT(2),
> + DELL_PERFORMANCE = BIT(3),
> +};
> +
> +static int thermal_get_mode(void)
> +{
> + struct calling_interface_buffer buffer;
> + int state;
> + int ret;
> +
> + dell_fill_request(&buffer, 0x0, 0, 0, 0);
> + ret = dell_send_request(&buffer, CLASS_INFO, SELECT_THERMAL_MANAGEMENT);
> + if (ret)
> + return ret;
> + state = buffer.output[2];
> + if (state & DELL_BALANCED)
> + return DELL_BALANCED;
> + else if (state & DELL_COOL_BOTTOM)
> + return DELL_COOL_BOTTOM;
> + else if (state & DELL_QUIET)
> + return DELL_QUIET;
> + else if (state & DELL_PERFORMANCE)
> + return DELL_PERFORMANCE;
> + else
> + return -ENXIO;
> +}
> +
> +static int thermal_get_supported_modes(int *supported_bits)
> +{
> + struct calling_interface_buffer buffer;
> + int ret;
> +
> + dell_fill_request(&buffer, 0x0, 0, 0, 0);
> + ret = dell_send_request(&buffer, CLASS_INFO, SELECT_THERMAL_MANAGEMENT);
> + if (ret)
> + return ret;
> + *supported_bits = FIELD_GET(DELL_THERMAL_SUPPORTED, buffer.output[1]);
> + return 0;
> +}
> +
> +static int thermal_get_acc_mode(int *acc_mode)
> +{
> + struct calling_interface_buffer buffer;
> + int ret;
> +
> + dell_fill_request(&buffer, 0x0, 0, 0, 0);
> + ret = dell_send_request(&buffer, CLASS_INFO, SELECT_THERMAL_MANAGEMENT);
> + if (ret)
> + return ret;
> + *acc_mode = FIELD_GET(DELL_ACC_GET_FIELD, buffer.output[3]);
> + return 0;
> +}
> +
> +static int thermal_set_mode(enum thermal_mode_bits state)
> +{
> + struct calling_interface_buffer buffer;
> + int ret;
> + int acc_mode;
> +
> + ret = thermal_get_acc_mode(&acc_mode);
> + if (ret)
> + return ret;
> +
> + dell_fill_request(&buffer, 0x1, FIELD_PREP(DELL_ACC_SET_FIELD, acc_mode) | state, 0, 0);
> + ret = dell_send_request(&buffer, CLASS_INFO, SELECT_THERMAL_MANAGEMENT);
> + return ret;
> +}
> +
> +static int thermal_platform_profile_set(struct platform_profile_handler *pprof,
> + enum platform_profile_option profile)
> +{
> + switch (profile) {
> + case PLATFORM_PROFILE_BALANCED:
> + return thermal_set_mode(DELL_BALANCED);
> + case PLATFORM_PROFILE_PERFORMANCE:
> + return thermal_set_mode(DELL_PERFORMANCE);
> + case PLATFORM_PROFILE_QUIET:
> + return thermal_set_mode(DELL_QUIET);
> + case PLATFORM_PROFILE_COOL:
> + return thermal_set_mode(DELL_COOL_BOTTOM);
> + default:
> + return -EOPNOTSUPP;
> + }
> +}
> +
> +static int thermal_platform_profile_get(struct platform_profile_handler *pprof,
> + enum platform_profile_option *profile)
> +{
> + int ret;
> +
> + ret = thermal_get_mode();
> + if (ret < 0)
> + return ret;
> +
> + switch (ret) {
> + case DELL_BALANCED:
> + *profile = PLATFORM_PROFILE_BALANCED;
> + break;
> + case DELL_PERFORMANCE:
> + *profile = PLATFORM_PROFILE_PERFORMANCE;
> + break;
> + case DELL_COOL_BOTTOM:
> + *profile = PLATFORM_PROFILE_COOL;
> + break;
> + case DELL_QUIET:
> + *profile = PLATFORM_PROFILE_QUIET;
> + break;
> + default:
> + return -EINVAL;
> + }
> +
> + return 0;
> +}
> +
> +static int thermal_init(void)
> +{
> + int ret;
> + int supported_modes;
> +
> + /* If thermal modes not supported, exit without error */
> + ret = thermal_get_supported_modes(&supported_modes);
> + if (ret < 0)
> + return ret;

Hi,

some older models might not support the USTT commands, which would prevent dell-laptop
from loading on such machines.
Since dell-smbios-base already knows which commands are supported (stored in da_supported_commands),
maybe you can add a function for checking if a certain class of commands is supported and
skip thermal_init() if the USTT commands are not supported.

Thanks,
Armin Wolf

> + if (!supported_modes)
> + return 0;
> +
> + thermal_handler = kzalloc(sizeof(*thermal_handler), GFP_KERNEL);
> + if (!thermal_handler)
> + return -ENOMEM;
> + thermal_handler->profile_get = thermal_platform_profile_get;
> + thermal_handler->profile_set = thermal_platform_profile_set;
> +
> + if (supported_modes & DELL_QUIET)
> + set_bit(PLATFORM_PROFILE_QUIET, thermal_handler->choices);
> + if (supported_modes & DELL_COOL_BOTTOM)
> + set_bit(PLATFORM_PROFILE_COOL, thermal_handler->choices);
> + if (supported_modes & DELL_BALANCED)
> + set_bit(PLATFORM_PROFILE_BALANCED, thermal_handler->choices);
> + if (supported_modes & DELL_PERFORMANCE)
> + set_bit(PLATFORM_PROFILE_PERFORMANCE, thermal_handler->choices);
> +
> + /* Clean up if failed */
> + ret = platform_profile_register(thermal_handler);
> + if (ret)
> + kfree(thermal_handler);
> +
> + return ret;
> +}
> +
> +static void thermal_cleanup(void)
> +{
> + if (thermal_handler) {
> + platform_profile_remove();
> + kfree(thermal_handler);
> + }
> +}
> +
> static struct led_classdev mute_led_cdev = {
> .name = "platform::mute",
> .max_brightness = 1,
> @@ -2238,6 +2468,11 @@ static int __init dell_init(void)
> goto fail_rfkill;
> }
>
> + /* Do not fail module if thermal modes not supported, just skip */
> + ret = thermal_init();
> + if (ret)
> + goto fail_thermal;
> +
> if (quirks && quirks->touchpad_led)
> touchpad_led_init(&platform_device->dev);
>
> @@ -2317,6 +2552,8 @@ static int __init dell_init(void)
> led_classdev_unregister(&mute_led_cdev);
> fail_led:
> dell_cleanup_rfkill();
> +fail_thermal:
> + thermal_cleanup();
> fail_rfkill:
> platform_device_del(platform_device);
> fail_platform_device2:
> @@ -2344,6 +2581,7 @@ static void __exit dell_exit(void)
> platform_device_unregister(platform_device);
> platform_driver_unregister(&platform_driver);
> }
> + thermal_cleanup();
> }
>
> /* dell-rbtn.c driver export functions which will not work correctly (and could
> diff --git a/drivers/platform/x86/dell/dell-smbios-base.c b/drivers/platform/x86/dell/dell-smbios-base.c
> index e61bfaf8b5c4..5bc2e394dd1c 100644
> --- a/drivers/platform/x86/dell/dell-smbios-base.c
> +++ b/drivers/platform/x86/dell/dell-smbios-base.c
> @@ -71,6 +71,7 @@ static struct smbios_call call_blacklist[] = {
> /* handled by kernel: dell-laptop */
> {0x0000, CLASS_INFO, SELECT_RFKILL},
> {0x0000, CLASS_KBD_BACKLIGHT, SELECT_KBD_BACKLIGHT},
> + {0x0000, CLASS_INFO, SELECT_THERMAL_MANAGEMENT},
> };
>
> struct token_range {
> diff --git a/drivers/platform/x86/dell/dell-smbios.h b/drivers/platform/x86/dell/dell-smbios.h
> index eb341bf000c6..585d042f1779 100644
> --- a/drivers/platform/x86/dell/dell-smbios.h
> +++ b/drivers/platform/x86/dell/dell-smbios.h
> @@ -19,6 +19,7 @@
> /* Classes and selects used only in kernel drivers */
> #define CLASS_KBD_BACKLIGHT 4
> #define SELECT_KBD_BACKLIGHT 11
> +#define SELECT_THERMAL_MANAGEMENT 19
>
> /* Tokens used in kernel drivers, any of these
> * should be filtered from userspace access

2024-05-04 01:00:18

by Lyndon Sanche

[permalink] [raw]
Subject: Re: [PATCH v5] platform/x86: dell-laptop: Implement platform_profile



On Fri, May 3 2024 at 11:19:07 PM +02:00:00, Armin Wolf
<[email protected]> wrote:
> Am 01.05.24 um 23:58 schrieb Lyndon Sanche:
>> +static int thermal_init(void)
>> +{
>> + int ret;
>> + int supported_modes;
>> +
>> + /* If thermal modes not supported, exit without error */
>> + ret = thermal_get_supported_modes(&supported_modes);
>> + if (ret < 0)
>> + return ret;
>
> Hi,
>
> some older models might not support the USTT commands, which would
> prevent dell-laptop
> from loading on such machines.
> Since dell-smbios-base already knows which commands are supported
> (stored in da_supported_commands),
> maybe you can add a function for checking if a certain class of
> commands is supported and
> skip thermal_init() if the USTT commands are not supported.
>
> Thanks,
> Armin Wolf

This is a good idea, I will have a look at dell-smbios-base to see
exactly how I can check for support. If support is not available,
thermal_init will skip or return 0 (depending on where I put the check).

Thanks,

Lyndon



2024-05-04 01:04:21

by Lyndon Sanche

[permalink] [raw]
Subject: Re: [PATCH v5] platform/x86: dell-laptop: Implement platform_profile



On Fri, May 3 2024 at 06:19:18 PM +08:00:00, kernel test robot
<[email protected]> wrote:
> Hi Lyndon,
>
> kernel test robot noticed the following build warnings:
>
> [auto build test WARNING on linus/master]
> [also build test WARNING on v6.9-rc6 next-20240503]
> [If your patch is applied to the wrong git tree, kindly drop us a
> note.
> And when submitting patch, we suggest to use '--base' as documented in
> https://git-scm.com/docs/git-format-patch#_base_tree_information]
>
> url:
> https://github.com/intel-lab-lkp/linux/commits/Lyndon-Sanche/platform-x86-dell-laptop-Implement-platform_profile/20240502-060146
> base: linus/master
> patch link:
> https://lore.kernel.org/r/20240501215829.4991-2-lsanche%40lyndeno.ca
> patch subject: [PATCH v5] platform/x86: dell-laptop: Implement
> platform_profile
> config:
> i386-kismet-CONFIG_ACPI_PLATFORM_PROFILE-CONFIG_DELL_LAPTOP-0-0
> (https://download.01.org/0day-ci/archive/20240503/[email protected]/config)
> reproduce:
> (https://download.01.org/0day-ci/archive/20240503/[email protected]/reproduce)
>
> If you fix the issue in a separate patch/commit (i.e. not just a new
> version of
> the same patch/commit), kindly add following tags
> | Reported-by: kernel test robot <[email protected]>
> | Closes:
> https://lore.kernel.org/oe-kbuild-all/[email protected]/
>
> kismet warnings: (new ones prefixed by >>)
>>> kismet: WARNING: unmet direct dependencies detected for
>>> ACPI_PLATFORM_PROFILE when selected by DELL_LAPTOP
> WARNING: unmet direct dependencies detected for
> ACPI_PLATFORM_PROFILE
> Depends on [n]: ACPI [=n]
> Selected by [y]:
> - DELL_LAPTOP [=y] && X86_PLATFORM_DEVICES [=y] &&
> X86_PLATFORM_DRIVERS_DELL [=y] && DMI [=y] && BACKLIGHT_CLASS_DEVICE
> [=y] && (ACPI_VIDEO [=n] || ACPI_VIDEO [=n]=n) && (RFKILL [=n] ||
> RFKILL [=n]=n) && (DELL_WMI [=n] || DELL_WMI [=n]=n) && SERIO_I8042
> [=y] && DELL_SMBIOS [=y]
>
> --
> 0-DAY CI Kernel Test Service
> https://github.com/intel/lkp-tests/wiki

I will try reproducing this test on my machine, to avoid spamming the
mailing list with the same error over and over.








2024-05-06 10:18:20

by Hans de Goede

[permalink] [raw]
Subject: Re: [PATCH v5] platform/x86: dell-laptop: Implement platform_profile

Hi Lyndon,

Thank you for your patch!

On 5/4/24 3:03 AM, Lyndon Sanche wrote:
>
>
> On Fri, May 3 2024 at 06:19:18 PM +08:00:00, kernel test robot <[email protected]> wrote:
>> Hi Lyndon,
>>
>> kernel test robot noticed the following build warnings:
>>
>> [auto build test WARNING on linus/master]
>> [also build test WARNING on v6.9-rc6 next-20240503]
>> [If your patch is applied to the wrong git tree, kindly drop us a note.
>> And when submitting patch, we suggest to use '--base' as documented in
>> https://git-scm.com/docs/git-format-patch#_base_tree_information]
>>
>> url:    https://github.com/intel-lab-lkp/linux/commits/Lyndon-Sanche/platform-x86-dell-laptop-Implement-platform_profile/20240502-060146
>> base:   linus/master
>> patch link:    https://lore.kernel.org/r/20240501215829.4991-2-lsanche%40lyndeno.ca
>> patch subject: [PATCH v5] platform/x86: dell-laptop: Implement platform_profile
>> config: i386-kismet-CONFIG_ACPI_PLATFORM_PROFILE-CONFIG_DELL_LAPTOP-0-0 (https://download.01.org/0day-ci/archive/20240503/[email protected]/config)
>> reproduce: (https://download.01.org/0day-ci/archive/20240503/[email protected]/reproduce)
>>
>> If you fix the issue in a separate patch/commit (i.e. not just a new version of
>> the same patch/commit), kindly add following tags
>> | Reported-by: kernel test robot <[email protected]>
>> | Closes: https://lore.kernel.org/oe-kbuild-all/[email protected]/
>>
>> kismet warnings: (new ones prefixed by >>)
>>>>  kismet: WARNING: unmet direct dependencies detected for ACPI_PLATFORM_PROFILE when selected by DELL_LAPTOP
>>    WARNING: unmet direct dependencies detected for ACPI_PLATFORM_PROFILE
>>      Depends on [n]: ACPI [=n]
>>      Selected by [y]:
>>      - DELL_LAPTOP [=y] && X86_PLATFORM_DEVICES [=y] && X86_PLATFORM_DRIVERS_DELL [=y] && DMI [=y] && BACKLIGHT_CLASS_DEVICE [=y] && (ACPI_VIDEO [=n] || ACPI_VIDEO [=n]=n) && (RFKILL [=n] || RFKILL [=n]=n) && (DELL_WMI [=n] || DELL_WMI [=n]=n) && SERIO_I8042 [=y] && DELL_SMBIOS [=y]
>>
>> --
>> 0-DAY CI Kernel Test Service
>> https://github.com/intel/lkp-tests/wiki
>
> I will try reproducing this test on my machine, to avoid spamming the mailing list with the same error over and over.

No need to reproduce this. When you select something in Kconfig you must ensure
that the item doing the selecting depends on all the dependencies of what you
are selecting.

IOW if you add this change to your next version then that should fix this:

diff --git a/drivers/platform/x86/dell/Kconfig b/drivers/platform/x86/dell/Kconfig
index bd9f445974cc..d18fbc6a5fbf 100644
--- a/drivers/platform/x86/dell/Kconfig
+++ b/drivers/platform/x86/dell/Kconfig
@@ -47,6 +47,7 @@ config DCDBAS
config DELL_LAPTOP
tristate "Dell Laptop Extras"
default m
+ depends on ACPI
depends on DMI
depends on BACKLIGHT_CLASS_DEVICE
depends on ACPI_VIDEO || ACPI_VIDEO = n

And please also address Armin's remark about making sure that failure
to initialize platform_profile support should not cause the entire driver
to fail to probe.

I see that Armin suggests to check da_supported_commands for this,
this is a good idea but atm this is private to dell-smbios-base. So
you will first need to do a small preparation patch adding a small:

bool dell_laptop_check_supported_cmds(struct calling_interface_buffer *buffer)
{
return da_supported_commands & (1 << buffer->cmd_class);
}
EXPORT_SYMBOL_GPL(dell_laptop_check_supported_cmds):

helper for this.

If this check fails (returns false) make the code not register
the platform_profile() while allowing probe() to continue / succeed,
please do not log anything in this case (or use dev_dbg())

If this check succeeds but subsequent dell_smbios_call()'s
fail during probe, then it is ok to log an error but please
still let probe() continue / succeed (without registering
a platform_profile handler).

Regards,

Hans



2024-05-07 16:30:33

by Lyndon Sanche

[permalink] [raw]
Subject: Re: [PATCH v5] platform/x86: dell-laptop: Implement platform_profile



On Mon, May 6 2024 at 12:18:05 PM +02:00:00, Hans de Goede
<[email protected]> wrote:
> Hi Lyndon,
>
> Thank you for your patch!
>
> On 5/4/24 3:03 AM, Lyndon Sanche wrote:
>>
>>
>> On Fri, May 3 2024 at 06:19:18 PM +08:00:00, kernel test robot
>> <[email protected]> wrote:
>>> Hi Lyndon,
>>>
>>> kernel test robot noticed the following build warnings:
>>>
>>> [auto build test WARNING on linus/master]
>>> [also build test WARNING on v6.9-rc6 next-20240503]
>>> [If your patch is applied to the wrong git tree, kindly drop us a
>>> note.
>>> And when submitting patch, we suggest to use '--base' as
>>> documented in
>>> https://git-scm.com/docs/git-format-patch#_base_tree_information]
>>>
>>> url:
>>> https://github.com/intel-lab-lkp/linux/commits/Lyndon-Sanche/platform-x86-dell-laptop-Implement-platform_profile/20240502-060146
>>> base: linus/master
>>> patch link:
>>> https://lore.kernel.org/r/20240501215829.4991-2-lsanche%40lyndeno.ca
>>> patch subject: [PATCH v5] platform/x86: dell-laptop: Implement
>>> platform_profile
>>> config:
>>> i386-kismet-CONFIG_ACPI_PLATFORM_PROFILE-CONFIG_DELL_LAPTOP-0-0
>>> (https://download.01.org/0day-ci/archive/20240503/[email protected]/config)
>>> reproduce:
>>> (https://download.01.org/0day-ci/archive/20240503/[email protected]/reproduce)
>>>
>>> If you fix the issue in a separate patch/commit (i.e. not just a
>>> new version of
>>> the same patch/commit), kindly add following tags
>>> | Reported-by: kernel test robot <[email protected]>
>>> | Closes:
>>> https://lore.kernel.org/oe-kbuild-all/[email protected]/
>>>
>>> kismet warnings: (new ones prefixed by >>)
>>>>> kismet: WARNING: unmet direct dependencies detected for
>>>>> ACPI_PLATFORM_PROFILE when selected by DELL_LAPTOP
>>> WARNING: unmet direct dependencies detected for
>>> ACPI_PLATFORM_PROFILE
>>> Depends on [n]: ACPI [=n]
>>> Selected by [y]:
>>> - DELL_LAPTOP [=y] && X86_PLATFORM_DEVICES [=y] &&
>>> X86_PLATFORM_DRIVERS_DELL [=y] && DMI [=y] &&
>>> BACKLIGHT_CLASS_DEVICE [=y] && (ACPI_VIDEO [=n] || ACPI_VIDEO
>>> [=n]=n) && (RFKILL [=n] || RFKILL [=n]=n) && (DELL_WMI [=n] ||
>>> DELL_WMI [=n]=n) && SERIO_I8042 [=y] && DELL_SMBIOS [=y]
>>>
>>> --
>>> 0-DAY CI Kernel Test Service
>>> https://github.com/intel/lkp-tests/wiki
>>
>> I will try reproducing this test on my machine, to avoid spamming
>> the mailing list with the same error over and over.
>
> No need to reproduce this. When you select something in Kconfig you
> must ensure
> that the item doing the selecting depends on all the dependencies of
> what you
> are selecting.
>
> IOW if you add this change to your next version then that should fix
> this:
>
> diff --git a/drivers/platform/x86/dell/Kconfig
> b/drivers/platform/x86/dell/Kconfig
> index bd9f445974cc..d18fbc6a5fbf 100644
> --- a/drivers/platform/x86/dell/Kconfig
> +++ b/drivers/platform/x86/dell/Kconfig
> @@ -47,6 +47,7 @@ config DCDBAS
> config DELL_LAPTOP
> tristate "Dell Laptop Extras"
> default m
> + depends on ACPI
> depends on DMI
> depends on BACKLIGHT_CLASS_DEVICE
> depends on ACPI_VIDEO || ACPI_VIDEO = n
>
> And please also address Armin's remark about making sure that failure
> to initialize platform_profile support should not cause the entire
> driver
> to fail to probe.
>
> I see that Armin suggests to check da_supported_commands for this,
> this is a good idea but atm this is private to dell-smbios-base. So
> you will first need to do a small preparation patch adding a small:
>
> bool dell_laptop_check_supported_cmds(struct calling_interface_buffer
> *buffer)
> {
> return da_supported_commands & (1 << buffer->cmd_class);
> }
> EXPORT_SYMBOL_GPL(dell_laptop_check_supported_cmds):
>
> helper for this.
>
> If this check fails (returns false) make the code not register
> the platform_profile() while allowing probe() to continue / succeed,
> please do not log anything in this case (or use dev_dbg())
>
> If this check succeeds but subsequent dell_smbios_call()'s
> fail during probe, then it is ok to log an error but please
> still let probe() continue / succeed (without registering
> a platform_profile handler).
>
> Regards,
>
> Hans
>
>
Hello Hans:

Thank you very much for your feedback and suggestions! I have been busy
the past few days, but will be able to tackle this this week. These are
good ideas which I plan to implement.

Thank you,

Lyndon



2024-05-08 14:26:57

by Shen, Yijun

[permalink] [raw]
Subject: RE: [PATCH v5] platform/x86: dell-laptop: Implement platform_profile

Hi Lyndon,

Thanks for working on this patch.


Internal Use - Confidential
+AD4- -----Original Message-----
+AD4- From: Lyndon Sanche +ADw-lsanche+AEA-lyndeno.ca+AD4-
+AD4- Sent: Thursday, May 2, 2024 5:58 AM
+AD4- To: lsanche+AEA-lyndeno.ca
+AD4- Cc: mario.limonciello+AEA-amd.com+ADs- pali+AEA-kernel.org+ADs- W+AF8-Armin+AEA-gmx.de+ADs-
+AD4- srinivas.pandruvada+AEA-linux.intel.com+ADs- ilpo.jarvinen+AEA-linux.intel.com+ADs-
+AD4- lkp+AEA-intel.com+ADs- Hans de Goede +ADw-hdegoede+AEA-redhat.com+AD4AOw- Matthew Garrett
+AD4- +ADw-mjg59+AEA-srcf.ucam.org+AD4AOw- Jonathan Corbet +ADw-corbet+AEA-lwn.net+AD4AOw- Heiner Kallweit
+AD4- +ADw-hkallweit1+AEA-gmail.com+AD4AOw- Vegard Nossum +ADw-vegard.nossum+AEA-oracle.com+AD4AOw-
+AD4- platform-driver-x86+AEA-vger.kernel.org+ADs- linux-kernel+AEA-vger.kernel.org+ADs- Dell Client
+AD4- Kernel +ADw-Dell.Client.Kernel+AEA-dell.com+AD4-
+AD4- Subject: +AFs-PATCH v5+AF0- platform/x86: dell-laptop: Implement platform+AF8-profile
+AD4-
+AD4-
+AD4- +AFs-EXTERNAL EMAIL+AF0-
+AD4-
+AD4- Some Dell laptops support configuration of preset fan modes through smbios
+AD4- tables.
+AD4-
+AD4- If the platform supports these fan modes, set up platform+AF8-profile to change
+AD4- these modes. If not supported, skip enabling platform+AF8-profile.
+AD4-
+AD4- Signed-off-by: Lyndon Sanche +ADw-lsanche+AEA-lyndeno.ca+AD4-
+AD4- ---
+AD4- v5:
+AD4- - Fix indent in smbios-thermal-ctl comment
+AD4- - Remove linux/wmi.h include
+AD4- - Add 'select ACPI+AF8-PLATFORM+AF8-PROFILE' to Dell KConfig
+AD4- v4:
+AD4- - Make thermal+AF8-init and thermal+AF8-cleanup static
+AD4- - Rearrange order of added includes, did not edit current includes
+AD4- - Include bits.h
+AD4- - Switch comment style
+AD4- - Return error if platform+AF8-profile registering failed
+AD4- - Add thermal calls to call+AF8-blacklist
+AD4- - Align defines with tabs
+AD4- - Correct separation of function and error handling
+AD4- - Propagate error codes up
+AD4- v3:
+AD4- - Convert smbios-thermal-ctl docs to multiline comment and wrap
+AD4- - Change thermal+AF8-mode+AF8-bits enum to directly be BIT() values
+AD4- - Convert related code to use this
+AD4- - Use FIELD+AF8-GET/PREP and GENNMASK for getting/setting thermal modes
+AD4- - Correct offset for getting current ACC mode, setting offset
+AD4- unchanged
+AD4- - Check if thermal+AF8-handler is allocated before freeing and
+AD4- unregistering platform+AF8-profile
+AD4- v2:
+AD4- - Wrap smbios-thermal-ctl comment
+AD4- - Return proper error code when invalid state returned
+AD4- - Simplify platform+AF8-profile+AF8-get returns
+AD4- - Propogate ENOMEM error
+AD4- ---

Dell side has an initial testing with this patch on some laptops, it looks good. While changing the platform profile:
1. The corresponding USTT option in BIOS will be changed.
2. thermald will not be impacted. The related PSVT and ITMT will be loaded.
Some Dell DTs does not have the USTT, Dell'll have a check if nothing is broken.

Additional, with this patch, follow behavior is found:
1. For example, the platform profile is quiet.
2. Reboot the system and change the USTT to performance.
3. Boot to desktop, the platform profile is +ACI-quiet+ACI-, the USTT will be changed back to +ACI-quiet+ACI-.
This looks like not a proper user experience. The platform profile should honor the BIOS setting, aka, the platform profile should be switched to +ACI-performance+ACI-.

+AD4- drivers/platform/x86/dell/Kconfig +AHw- 1 +-
+AD4- drivers/platform/x86/dell/dell-laptop.c +AHw- 238 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-
+AD4- drivers/platform/x86/dell/dell-smbios-base.c +AHw- 1 +-
+AD4- drivers/platform/x86/dell/dell-smbios.h +AHw- 1 +-
+AD4- 4 files changed, 241 insertions(+-)
+AD4-
+AD4- diff --git a/drivers/platform/x86/dell/Kconfig
+AD4- b/drivers/platform/x86/dell/Kconfig
+AD4- index bd9f445974cc..5195ad59b44d 100644
+AD4- --- a/drivers/platform/x86/dell/Kconfig
+AD4- +-+-+- b/drivers/platform/x86/dell/Kconfig
+AD4- +AEAAQA- -57,6 +-57,7 +AEAAQA- config DELL+AF8-LAPTOP
+AD4- select POWER+AF8-SUPPLY
+AD4- select LEDS+AF8-CLASS
+AD4- select NEW+AF8-LEDS
+AD4- +- select ACPI+AF8-PLATFORM+AF8-PROFILE
+AD4- help
+AD4- This driver adds support for rfkill and backlight control to Dell
+AD4- laptops (except for some models covered by the Compal driver).
+AD4- diff --git a/drivers/platform/x86/dell/dell-laptop.c
+AD4- b/drivers/platform/x86/dell/dell-laptop.c
+AD4- index 42f7de2b4522..dc530a4f5047 100644
+AD4- --- a/drivers/platform/x86/dell/dell-laptop.c
+AD4- +-+-+- b/drivers/platform/x86/dell/dell-laptop.c
+AD4- +AEAAQA- -27,6 +-27,9 +AEAAQA-
+AD4- +ACM-include +ADw-linux/i8042.h+AD4-
+AD4- +ACM-include +ADw-linux/debugfs.h+AD4-
+AD4- +ACM-include +ADw-linux/seq+AF8-file.h+AD4-
+AD4- +-+ACM-include +ADw-linux/bitfield.h+AD4-
+AD4- +-+ACM-include +ADw-linux/bits.h+AD4-
+AD4- +-+ACM-include +ADw-linux/platform+AF8-profile.h+AD4-
+AD4- +ACM-include +ADw-acpi/video.h+AD4-
+AD4- +ACM-include +ACI-dell-rbtn.h+ACI-
+AD4- +ACM-include +ACI-dell-smbios.h+ACI-
+AD4- +AEAAQA- -95,6 +-98,7 +AEAAQA- static struct backlight+AF8-device +ACo-dell+AF8-backlight+AF8-device+ADs-
+AD4- static struct rfkill +ACo-wifi+AF8-rfkill+ADs- static struct rfkill +ACo-bluetooth+AF8-rfkill+ADs- static struct
+AD4- rfkill +ACo-wwan+AF8-rfkill+ADs-
+AD4- +-static struct platform+AF8-profile+AF8-handler +ACo-thermal+AF8-handler+ADs-
+AD4- static bool force+AF8-rfkill+ADs-
+AD4- static bool micmute+AF8-led+AF8-registered+ADs-
+AD4- static bool mute+AF8-led+AF8-registered+ADs-
+AD4- +AEAAQA- -2199,6 +-2203,232 +AEAAQA- static int mute+AF8-led+AF8-set(struct led+AF8-classdev
+AD4- +ACo-led+AF8-cdev,
+AD4- return 0+ADs-
+AD4- +AH0-
+AD4-
+AD4- +-/+ACo- Derived from smbios-thermal-ctl
+AD4- +- +ACo-
+AD4- +- +ACo- cbClass 17
+AD4- +- +ACo- cbSelect 19
+AD4- +- +ACo- User Selectable Thermal Tables(USTT)
+AD4- +- +ACo- cbArg1 determines the function to be performed
+AD4- +- +ACo- cbArg1 0x0 +AD0- Get Thermal Information
+AD4- +- +ACo- cbRES1 Standard return codes (0, -1, -2)
+AD4- +- +ACo- cbRES2, byte 0 Bitmap of supported thermal modes. A mode is
+AD4- supported if
+AD4- +- +ACo- its bit is set to 1
+AD4- +- +ACo- Bit 0 Balanced
+AD4- +- +ACo- Bit 1 Cool Bottom
+AD4- +- +ACo- Bit 2 Quiet
+AD4- +- +ACo- Bit 3 Performance
+AD4- +- +ACo- cbRES2, byte 1 Bitmap of supported Active Acoustic Controller (AAC)
+AD4- modes.
+AD4- +- +ACo- Each mode corresponds to the supported thermal modes in
+AD4- +- +ACo- byte 0. A mode is supported if its bit is set to 1.
+AD4- +- +ACo- Bit 0 AAC (Balanced)
+AD4- +- +ACo- Bit 1 AAC (Cool Bottom
+AD4- +- +ACo- Bit 2 AAC (Quiet)
+AD4- +- +ACo- Bit 3 AAC (Performance)
+AD4- +- +ACo- cbRes3, byte 0 Current Thermal Mode
+AD4- +- +ACo- Bit 0 Balanced
+AD4- +- +ACo- Bit 1 Cool Bottom
+AD4- +- +ACo- Bit 2 Quiet
+AD4- +- +ACo- Bit 3 Performanc
+AD4- +- +ACo- cbRes3, byte 1 AAC Configuration type
+AD4- +- +ACo- 0 Global (AAC enable/disable applies to all supported USTT
+AD4- modes)
+AD4- +- +ACo- 1 USTT mode specific
+AD4- +- +ACo- cbRes3, byte 2 Current Active Acoustic Controller (AAC) Mode
+AD4- +- +ACo- If AAC Configuration Type is Global,
+AD4- +- +ACo- 0 AAC mode disabled
+AD4- +- +ACo- 1 AAC mode enabled
+AD4- +- +ACo- If AAC Configuration Type is USTT mode specific (multiple bits may be
+AD4- set),
+AD4- +- +ACo- Bit 0 AAC (Balanced)
+AD4- +- +ACo- Bit 1 AAC (Cool Bottom
+AD4- +- +ACo- Bit 2 AAC (Quiet)
+AD4- +- +ACo- Bit 3 AAC (Performance)
+AD4- +- +ACo- cbRes3, byte 3 Current Fan Failure Mode
+AD4- +- +ACo- Bit 0 Minimal Fan Failure (at least one fan has failed, one fan working)
+AD4- +- +ACo- Bit 1 Catastrophic Fan Failure (all fans have failed)
+AD4- +- +ACo-
+AD4- +- +ACo- cbArg1 0x1 (Set Thermal Information), both desired thermal mode and
+AD4- +- +ACo- desired AAC mode shall be applied
+AD4- +- +ACo- cbArg2, byte 0 Desired Thermal Mode to set
+AD4- +- +ACo- (only one bit may be set for this parameter)
+AD4- +- +ACo- Bit 0 Balanced
+AD4- +- +ACo- Bit 1 Cool Bottom
+AD4- +- +ACo- Bit 2 Quiet
+AD4- +- +ACo- Bit 3 Performance
+AD4- +- +ACo- cbArg2, byte 1 Desired Active Acoustic Controller (AAC) Mode to set
+AD4- +- +ACo- If AAC Configuration Type is Global,
+AD4- +- +ACo- 0 AAC mode disabled
+AD4- +- +ACo- 1 AAC mode enabled
+AD4- +- +ACo- If AAC Configuration Type is USTT mode specific
+AD4- +- +ACo- (multiple bits may be set for this parameter),
+AD4- +- +ACo- Bit 0 AAC (Balanced)
+AD4- +- +ACo- Bit 1 AAC (Cool Bottom
+AD4- +- +ACo- Bit 2 AAC (Quiet)
+AD4- +- +ACo- Bit 3 AAC (Performance)
+AD4- +- +ACo-/
+AD4- +-
+AD4- +-+ACM-define DELL+AF8-ACC+AF8-GET+AF8-FIELD GENMASK(19, 16)
+AD4- +-+ACM-define DELL+AF8-ACC+AF8-SET+AF8-FIELD GENMASK(11, 8)
+AD4- +-+ACM-define DELL+AF8-THERMAL+AF8-SUPPORTED GENMASK(3, 0)
+AD4- +-
+AD4- +-enum thermal+AF8-mode+AF8-bits +AHs-
+AD4- +- DELL+AF8-BALANCED +AD0- BIT(0),
+AD4- +- DELL+AF8-COOL+AF8-BOTTOM +AD0- BIT(1),
+AD4- +- DELL+AF8-QUIET +AD0- BIT(2),
+AD4- +- DELL+AF8-PERFORMANCE +AD0- BIT(3),
+AD4- +-+AH0AOw-
+AD4- +-
+AD4- +-static int thermal+AF8-get+AF8-mode(void)
+AD4- +-+AHs-
+AD4- +- struct calling+AF8-interface+AF8-buffer buffer+ADs-
+AD4- +- int state+ADs-
+AD4- +- int ret+ADs-
+AD4- +-
+AD4- +- dell+AF8-fill+AF8-request(+ACY-buffer, 0x0, 0, 0, 0)+ADs-
+AD4- +- ret +AD0- dell+AF8-send+AF8-request(+ACY-buffer, CLASS+AF8-INFO,
+AD4- SELECT+AF8-THERMAL+AF8-MANAGEMENT)+ADs-
+AD4- +- if (ret)
+AD4- +- return ret+ADs-
+AD4- +- state +AD0- buffer.output+AFs-2+AF0AOw-
+AD4- +- if (state +ACY- DELL+AF8-BALANCED)
+AD4- +- return DELL+AF8-BALANCED+ADs-
+AD4- +- else if (state +ACY- DELL+AF8-COOL+AF8-BOTTOM)
+AD4- +- return DELL+AF8-COOL+AF8-BOTTOM+ADs-
+AD4- +- else if (state +ACY- DELL+AF8-QUIET)
+AD4- +- return DELL+AF8-QUIET+ADs-
+AD4- +- else if (state +ACY- DELL+AF8-PERFORMANCE)
+AD4- +- return DELL+AF8-PERFORMANCE+ADs-
+AD4- +- else
+AD4- +- return -ENXIO+ADs-
+AD4- +-+AH0-
+AD4- +-
+AD4- +-static int thermal+AF8-get+AF8-supported+AF8-modes(int +ACo-supported+AF8-bits) +AHs-
+AD4- +- struct calling+AF8-interface+AF8-buffer buffer+ADs-
+AD4- +- int ret+ADs-
+AD4- +-
+AD4- +- dell+AF8-fill+AF8-request(+ACY-buffer, 0x0, 0, 0, 0)+ADs-
+AD4- +- ret +AD0- dell+AF8-send+AF8-request(+ACY-buffer, CLASS+AF8-INFO,
+AD4- SELECT+AF8-THERMAL+AF8-MANAGEMENT)+ADs-
+AD4- +- if (ret)
+AD4- +- return ret+ADs-
+AD4- +- +ACo-supported+AF8-bits +AD0- FIELD+AF8-GET(DELL+AF8-THERMAL+AF8-SUPPORTED,
+AD4- buffer.output+AFs-1+AF0-)+ADs-
+AD4- +- return 0+ADs-
+AD4- +-+AH0-
+AD4- +-
+AD4- +-static int thermal+AF8-get+AF8-acc+AF8-mode(int +ACo-acc+AF8-mode) +AHs-
+AD4- +- struct calling+AF8-interface+AF8-buffer buffer+ADs-
+AD4- +- int ret+ADs-
+AD4- +-
+AD4- +- dell+AF8-fill+AF8-request(+ACY-buffer, 0x0, 0, 0, 0)+ADs-
+AD4- +- ret +AD0- dell+AF8-send+AF8-request(+ACY-buffer, CLASS+AF8-INFO,
+AD4- SELECT+AF8-THERMAL+AF8-MANAGEMENT)+ADs-
+AD4- +- if (ret)
+AD4- +- return ret+ADs-
+AD4- +- +ACo-acc+AF8-mode +AD0- FIELD+AF8-GET(DELL+AF8-ACC+AF8-GET+AF8-FIELD, buffer.output+AFs-3+AF0-)+ADs-
+AD4- +- return 0+ADs-
+AD4- +-+AH0-
+AD4- +-
+AD4- +-static int thermal+AF8-set+AF8-mode(enum thermal+AF8-mode+AF8-bits state) +AHs-
+AD4- +- struct calling+AF8-interface+AF8-buffer buffer+ADs-
+AD4- +- int ret+ADs-
+AD4- +- int acc+AF8-mode+ADs-
+AD4- +-
+AD4- +- ret +AD0- thermal+AF8-get+AF8-acc+AF8-mode(+ACY-acc+AF8-mode)+ADs-
+AD4- +- if (ret)
+AD4- +- return ret+ADs-
+AD4- +-
+AD4- +- dell+AF8-fill+AF8-request(+ACY-buffer, 0x1, FIELD+AF8-PREP(DELL+AF8-ACC+AF8-SET+AF8-FIELD,
+AD4- acc+AF8-mode) +AHw- state, 0, 0)+ADs-
+AD4- +- ret +AD0- dell+AF8-send+AF8-request(+ACY-buffer, CLASS+AF8-INFO,
+AD4- SELECT+AF8-THERMAL+AF8-MANAGEMENT)+ADs-
+AD4- +- return ret+ADs-
+AD4- +-+AH0-
+AD4- +-
+AD4- +-static int thermal+AF8-platform+AF8-profile+AF8-set(struct platform+AF8-profile+AF8-handler
+AD4- +ACo-pprof,
+AD4- +- enum platform+AF8-profile+AF8-option
+AD4- profile) +AHs-
+AD4- +- switch (profile) +AHs-
+AD4- +- case PLATFORM+AF8-PROFILE+AF8-BALANCED:
+AD4- +- return thermal+AF8-set+AF8-mode(DELL+AF8-BALANCED)+ADs-
+AD4- +- case PLATFORM+AF8-PROFILE+AF8-PERFORMANCE:
+AD4- +- return thermal+AF8-set+AF8-mode(DELL+AF8-PERFORMANCE)+ADs-
+AD4- +- case PLATFORM+AF8-PROFILE+AF8-QUIET:
+AD4- +- return thermal+AF8-set+AF8-mode(DELL+AF8-QUIET)+ADs-
+AD4- +- case PLATFORM+AF8-PROFILE+AF8-COOL:
+AD4- +- return thermal+AF8-set+AF8-mode(DELL+AF8-COOL+AF8-BOTTOM)+ADs-
+AD4- +- default:
+AD4- +- return -EOPNOTSUPP+ADs-
+AD4- +- +AH0-
+AD4- +-+AH0-
+AD4- +-
+AD4- +-static int thermal+AF8-platform+AF8-profile+AF8-get(struct platform+AF8-profile+AF8-handler
+AD4- +ACo-pprof,
+AD4- +- enum platform+AF8-profile+AF8-option
+AD4- +ACo-profile) +AHs-
+AD4- +- int ret+ADs-
+AD4- +-
+AD4- +- ret +AD0- thermal+AF8-get+AF8-mode()+ADs-
+AD4- +- if (ret +ADw- 0)
+AD4- +- return ret+ADs-
+AD4- +-
+AD4- +- switch (ret) +AHs-
+AD4- +- case DELL+AF8-BALANCED:
+AD4- +- +ACo-profile +AD0- PLATFORM+AF8-PROFILE+AF8-BALANCED+ADs-
+AD4- +- break+ADs-
+AD4- +- case DELL+AF8-PERFORMANCE:
+AD4- +- +ACo-profile +AD0- PLATFORM+AF8-PROFILE+AF8-PERFORMANCE+ADs-
+AD4- +- break+ADs-
+AD4- +- case DELL+AF8-COOL+AF8-BOTTOM:
+AD4- +- +ACo-profile +AD0- PLATFORM+AF8-PROFILE+AF8-COOL+ADs-
+AD4- +- break+ADs-
+AD4- +- case DELL+AF8-QUIET:
+AD4- +- +ACo-profile +AD0- PLATFORM+AF8-PROFILE+AF8-QUIET+ADs-
+AD4- +- break+ADs-
+AD4- +- default:
+AD4- +- return -EINVAL+ADs-
+AD4- +- +AH0-
+AD4- +-
+AD4- +- return 0+ADs-
+AD4- +-+AH0-
+AD4- +-
+AD4- +-static int thermal+AF8-init(void)
+AD4- +-+AHs-
+AD4- +- int ret+ADs-
+AD4- +- int supported+AF8-modes+ADs-
+AD4- +-
+AD4- +- /+ACo- If thermal modes not supported, exit without error +ACo-/
+AD4- +- ret +AD0- thermal+AF8-get+AF8-supported+AF8-modes(+ACY-supported+AF8-modes)+ADs-
+AD4- +- if (ret +ADw- 0)
+AD4- +- return ret+ADs-
+AD4- +- if (+ACE-supported+AF8-modes)
+AD4- +- return 0+ADs-
+AD4- +-
+AD4- +- thermal+AF8-handler +AD0- kzalloc(sizeof(+ACo-thermal+AF8-handler), GFP+AF8-KERNEL)+ADs-
+AD4- +- if (+ACE-thermal+AF8-handler)
+AD4- +- return -ENOMEM+ADs-
+AD4- +- thermal+AF8-handler-+AD4-profile+AF8-get +AD0- thermal+AF8-platform+AF8-profile+AF8-get+ADs-
+AD4- +- thermal+AF8-handler-+AD4-profile+AF8-set +AD0- thermal+AF8-platform+AF8-profile+AF8-set+ADs-
+AD4- +-
+AD4- +- if (supported+AF8-modes +ACY- DELL+AF8-QUIET)
+AD4- +- set+AF8-bit(PLATFORM+AF8-PROFILE+AF8-QUIET, thermal+AF8-handler-
+AD4- +AD4-choices)+ADs-
+AD4- +- if (supported+AF8-modes +ACY- DELL+AF8-COOL+AF8-BOTTOM)
+AD4- +- set+AF8-bit(PLATFORM+AF8-PROFILE+AF8-COOL, thermal+AF8-handler-
+AD4- +AD4-choices)+ADs-
+AD4- +- if (supported+AF8-modes +ACY- DELL+AF8-BALANCED)
+AD4- +- set+AF8-bit(PLATFORM+AF8-PROFILE+AF8-BALANCED, thermal+AF8-handler-
+AD4- +AD4-choices)+ADs-
+AD4- +- if (supported+AF8-modes +ACY- DELL+AF8-PERFORMANCE)
+AD4- +- set+AF8-bit(PLATFORM+AF8-PROFILE+AF8-PERFORMANCE,
+AD4- thermal+AF8-handler-+AD4-choices)+ADs-
+AD4- +-
+AD4- +- /+ACo- Clean up if failed +ACo-/
+AD4- +- ret +AD0- platform+AF8-profile+AF8-register(thermal+AF8-handler)+ADs-
+AD4- +- if (ret)
+AD4- +- kfree(thermal+AF8-handler)+ADs-
+AD4- +-
+AD4- +- return ret+ADs-
+AD4- +-+AH0-
+AD4- +-
+AD4- +-static void thermal+AF8-cleanup(void)
+AD4- +-+AHs-
+AD4- +- if (thermal+AF8-handler) +AHs-
+AD4- +- platform+AF8-profile+AF8-remove()+ADs-
+AD4- +- kfree(thermal+AF8-handler)+ADs-
+AD4- +- +AH0-
+AD4- +-+AH0-
+AD4- +-
+AD4- static struct led+AF8-classdev mute+AF8-led+AF8-cdev +AD0- +AHs-
+AD4- .name +AD0- +ACI-platform::mute+ACI-,
+AD4- .max+AF8-brightness +AD0- 1,
+AD4- +AEAAQA- -2238,6 +-2468,11 +AEAAQA- static int +AF8AXw-init dell+AF8-init(void)
+AD4- goto fail+AF8-rfkill+ADs-
+AD4- +AH0-
+AD4-
+AD4- +- /+ACo- Do not fail module if thermal modes not supported, just skip +ACo-/
+AD4- +- ret +AD0- thermal+AF8-init()+ADs-
+AD4- +- if (ret)
+AD4- +- goto fail+AF8-thermal+ADs-
+AD4- +-
+AD4- if (quirks +ACYAJg- quirks-+AD4-touchpad+AF8-led)
+AD4- touchpad+AF8-led+AF8-init(+ACY-platform+AF8-device-+AD4-dev)+ADs-
+AD4-
+AD4- +AEAAQA- -2317,6 +-2552,8 +AEAAQA- static int +AF8AXw-init dell+AF8-init(void)
+AD4- led+AF8-classdev+AF8-unregister(+ACY-mute+AF8-led+AF8-cdev)+ADs-
+AD4- fail+AF8-led:
+AD4- dell+AF8-cleanup+AF8-rfkill()+ADs-
+AD4- +-fail+AF8-thermal:
+AD4- +- thermal+AF8-cleanup()+ADs-
+AD4- fail+AF8-rfkill:
+AD4- platform+AF8-device+AF8-del(platform+AF8-device)+ADs-
+AD4- fail+AF8-platform+AF8-device2:
+AD4- +AEAAQA- -2344,6 +-2581,7 +AEAAQA- static void +AF8AXw-exit dell+AF8-exit(void)
+AD4- platform+AF8-device+AF8-unregister(platform+AF8-device)+ADs-
+AD4- platform+AF8-driver+AF8-unregister(+ACY-platform+AF8-driver)+ADs-
+AD4- +AH0-
+AD4- +- thermal+AF8-cleanup()+ADs-
+AD4- +AH0-
+AD4-
+AD4- /+ACo- dell-rbtn.c driver export functions which will not work correctly (and could
+AD4- diff --git a/drivers/platform/x86/dell/dell-smbios-base.c
+AD4- b/drivers/platform/x86/dell/dell-smbios-base.c
+AD4- index e61bfaf8b5c4..5bc2e394dd1c 100644
+AD4- --- a/drivers/platform/x86/dell/dell-smbios-base.c
+AD4- +-+-+- b/drivers/platform/x86/dell/dell-smbios-base.c
+AD4- +AEAAQA- -71,6 +-71,7 +AEAAQA- static struct smbios+AF8-call call+AF8-blacklist+AFsAXQ- +AD0- +AHs-
+AD4- /+ACo- handled by kernel: dell-laptop +ACo-/
+AD4- +AHs-0x0000, CLASS+AF8-INFO, SELECT+AF8-RFKILL+AH0-,
+AD4- +AHs-0x0000, CLASS+AF8-KBD+AF8-BACKLIGHT, SELECT+AF8-KBD+AF8-BACKLIGHT+AH0-,
+AD4- +- +AHs-0x0000, CLASS+AF8-INFO, SELECT+AF8-THERMAL+AF8-MANAGEMENT+AH0-,
+AD4- +AH0AOw-
+AD4-
+AD4- struct token+AF8-range +AHs-
+AD4- diff --git a/drivers/platform/x86/dell/dell-smbios.h
+AD4- b/drivers/platform/x86/dell/dell-smbios.h
+AD4- index eb341bf000c6..585d042f1779 100644
+AD4- --- a/drivers/platform/x86/dell/dell-smbios.h
+AD4- +-+-+- b/drivers/platform/x86/dell/dell-smbios.h
+AD4- +AEAAQA- -19,6 +-19,7 +AEAAQA-
+AD4- /+ACo- Classes and selects used only in kernel drivers +ACo-/ +ACM-define
+AD4- CLASS+AF8-KBD+AF8-BACKLIGHT 4 +ACM-define SELECT+AF8-KBD+AF8-BACKLIGHT 11
+AD4- +-+ACM-define SELECT+AF8-THERMAL+AF8-MANAGEMENT 19
+AD4-
+AD4- /+ACo- Tokens used in kernel drivers, any of these
+AD4- +ACo- should be filtered from userspace access
+AD4- --
+AD4- 2.42.0


2024-05-08 15:53:59

by Mario Limonciello

[permalink] [raw]
Subject: Re: RE: [PATCH v5] platform/x86: dell-laptop: Implement platform_profile

On 5/8/2024 09:24, Shen, Yijun wrote:
> Hi Lyndon,
>
> Thanks for working on this patch.
>
>>
> Dell side has an initial testing with this patch on some laptops, it looks good. While changing the platform profile:
> 1. The corresponding USTT option in BIOS will be changed.
> 2. thermald will not be impacted. The related PSVT and ITMT will be loaded.
> Some Dell DTs does not have the USTT, Dell'll have a check if nothing is broken.

Hi Alex!

Have you had a check both on both your AMD laptops and workstations too,
or just the Intel ones? I think it would be good to make sure it's
getting the correct experience in both cases.

>
> Additional, with this patch, follow behavior is found:
> 1. For example, the platform profile is quiet.
> 2. Reboot the system and change the USTT to performance.
> 3. Boot to desktop, the platform profile is "quiet", the USTT will be changed back to "quiet".
> This looks like not a proper user experience. The platform profile should honor the BIOS setting, aka, the platform profile should be switched to "performance".
>

I agree, this sounds like the initial profile needs to be read from the
BIOS settings too.

Furthermore I wanted to ask is there also a WMI setting that corresponds
to this that dell-wmi-sysman offers? I'm wondering if both should be
probed in case the SMBIOS one goes away one day. Or should that one
just be used as preference?

It seems like maybe ThermalManagement corresponds. There was some test
data in fwupd for it:

https://github.com/fwupd/fwupd/tree/main/libfwupdplugin/tests/bios-attrs/dell-xps13-9310/dell-wmi-sysman/attributes/ThermalManagement

2024-05-09 15:12:31

by Lyndon Sanche

[permalink] [raw]
Subject: Re: [PATCH v5] platform/x86: dell-laptop: Implement platform_profile

On Wed, May 8, 2024, at 8:24 AM, Shen, Yijun wrote:
> Hi Lyndon,
>
> Thanks for working on this patch.
>
>
> Internal Use - Confidential
>> -----Original Message-----
>> From: Lyndon Sanche <[email protected]>
>> Sent: Thursday, May 2, 2024 5:58 AM
>> To: [email protected]
>> Cc: [email protected]; [email protected]; [email protected];
>> [email protected]; [email protected];
>> [email protected]; Hans de Goede <[email protected]>; Matthew Garrett
>> <[email protected]>; Jonathan Corbet <[email protected]>; Heiner Kallweit
>> <[email protected]>; Vegard Nossum <[email protected]>;
>> [email protected]; [email protected]; Dell Client
>> Kernel <[email protected]>
>> Subject: [PATCH v5] platform/x86: dell-laptop: Implement platform_profile
>>
>>
>> [EXTERNAL EMAIL]
>>
>> Some Dell laptops support configuration of preset fan modes through smbios
>> tables.
>>
>> If the platform supports these fan modes, set up platform_profile to change
>> these modes. If not supported, skip enabling platform_profile.
>>
>> Signed-off-by: Lyndon Sanche <[email protected]>
>> ---
>> v5:
>> - Fix indent in smbios-thermal-ctl comment
>> - Remove linux/wmi.h include
>> - Add 'select ACPI_PLATFORM_PROFILE' to Dell KConfig
>> v4:
>> - Make thermal_init and thermal_cleanup static
>> - Rearrange order of added includes, did not edit current includes
>> - Include bits.h
>> - Switch comment style
>> - Return error if platform_profile registering failed
>> - Add thermal calls to call_blacklist
>> - Align defines with tabs
>> - Correct separation of function and error handling
>> - Propagate error codes up
>> v3:
>> - Convert smbios-thermal-ctl docs to multiline comment and wrap
>> - Change thermal_mode_bits enum to directly be BIT() values
>> - Convert related code to use this
>> - Use FIELD_GET/PREP and GENNMASK for getting/setting thermal modes
>> - Correct offset for getting current ACC mode, setting offset
>> unchanged
>> - Check if thermal_handler is allocated before freeing and
>> unregistering platform_profile
>> v2:
>> - Wrap smbios-thermal-ctl comment
>> - Return proper error code when invalid state returned
>> - Simplify platform_profile_get returns
>> - Propogate ENOMEM error
>> ---
>
> Dell side has an initial testing with this patch on some laptops, it
> looks good. While changing the platform profile:
> 1. The corresponding USTT option in BIOS will be changed.
> 2. thermald will not be impacted. The related PSVT and ITMT will be
> loaded.
> Some Dell DTs does not have the USTT, Dell'll have a check if nothing
> is broken.
>
> Additional, with this patch, follow behavior is found:
> 1. For example, the platform profile is quiet.
> 2. Reboot the system and change the USTT to performance.
> 3. Boot to desktop, the platform profile is "quiet", the USTT will be
> changed back to "quiet".
> This looks like not a proper user experience. The platform profile
> should honor the BIOS setting, aka, the platform profile should be
> switched to "performance".

Hello:

Thank you for your email. This is definitely undesirable behaviour, I will have a look at the code to see why this is happening. Does it always revert to quiet on boot, or always the mode that you had switched to prior to reboot?

Do you happen to have power-profiles-daemon or something similar running? My understanding is it remembers profiles across reboots, this could potentially also revert the profile back to what it was. See this release for details:
https://gitlab.freedesktop.org/upower/power-profiles-daemon/-/releases/0.9.0

I will assume there is a bug in my code at this point. I will test with and without ppd running on my system to see if it changes across reboots.

Are USTT settings exposed in your BIOS configuration menu? On my laptop they are not and I have to use smbios-thermal-ctl.

Thank you,

Lyndon

2024-05-11 01:49:41

by Lyndon Sanche

[permalink] [raw]
Subject: Re: [PATCH v5] platform/x86: dell-laptop: Implement platform_profile



On Thu, May 9 2024 at 09:10:51 AM -06:00:00, Lyndon Sanche
<[email protected]> wrote:
> On Wed, May 8, 2024, at 8:24 AM, Shen, Yijun wrote:
>> Hi Lyndon,
>>
>> Thanks for working on this patch.
>>
>>
>> Dell side has an initial testing with this patch on some laptops,
>> it
>> looks good. While changing the platform profile:
>> 1. The corresponding USTT option in BIOS will be changed.
>> 2. thermald will not be impacted. The related PSVT and ITMT will be
>> loaded.
>> Some Dell DTs does not have the USTT, Dell'll have a check if
>> nothing
>> is broken.
>>
>> Additional, with this patch, follow behavior is found:
>> 1. For example, the platform profile is quiet.
>> 2. Reboot the system and change the USTT to performance.
>> 3. Boot to desktop, the platform profile is "quiet", the USTT will
>> be
>> changed back to "quiet".
>> This looks like not a proper user experience. The platform profile
>> should honor the BIOS setting, aka, the platform profile should be
>> switched to "performance".
>
> Hello:
>
> Thank you for your email. This is definitely undesirable behaviour, I
> will have a look at the code to see why this is happening. Does it
> always revert to quiet on boot, or always the mode that you had
> switched to prior to reboot?
>
> Do you happen to have power-profiles-daemon or something similar
> running? My understanding is it remembers profiles across reboots,
> this could potentially also revert the profile back to what it was.
> See this release for details:
> https://gitlab.freedesktop.org/upower/power-profiles-daemon/-/releases/0.9.0
>
> I will assume there is a bug in my code at this point. I will test
> with and without ppd running on my system to see if it changes across
> reboots.
>
> Are USTT settings exposed in your BIOS configuration menu? On my
> laptop they are not and I have to use smbios-thermal-ctl.
>
> Thank you,
>
> Lyndon

Hi Yijun:

I tested this on my computer (XPS 9560). I do not have access to the
USTT settings in the BIOS screen so to substitute that, I booted
without the patch and set the USTT manually using smbios-thermal-ctl.
Here are my findings:

Scenario #1: Without power-profiles-daemon (ppd) running

1. Boot with patch, set platform_profile to quiet
2. Boot without patch applied (no platform_profile)
- smbios-thermal-ctl confirms USTT is set to quiet
- use smbios-thermal-ctl to set USTT to performance
- confirm set to performance
3. Boot with patch again
- platform_profile is set to performance

Scenario #2: With ppd running
1. Boot with patch, set platform_profile to performance with ppd
- Confirm platform_profile is performance
2. Boot without patch applied (no platform_profile)
- smbios-thermal-ctl confirms USTT is set to performance
- ppd reverts to balanced (only controlling intel_pstate in this case)
- use smbios-thermal-ctl to set USTT to quiet
- confirm set to quiet
3. Boot with patch again
- platform_profile and ppd is set to performance

In my case, the setting in the smbios is honored if it was switched
with another method. When using a userspace program that manipulates
the platform_profile, the program seems to remember the previous state
and switch to that.

So I do not think there is a bug in this patch related to this issue,
at least in my case. Please let me know if you have any questions.

Thanks,

Lyndon





2024-05-11 02:38:49

by Lyndon Sanche

[permalink] [raw]
Subject: [PATCH v6 0/2] platform/x86: dell-laptop: Implement platform_profile

Some Dell laptops support configuration of preset fan modes through
smbios tables.

If the platform supports these fan modes, set up platform_profile to
change these modes. If not supported, skip enabling platform_profile.

v6:
- Add ACPI dependency for dell-laptop
- Add and use helper symbol for checking supported commands
v5:
- Fix indent in smbios-thermal-ctl comment
- Remove linux/wmi.h include
- Add 'select ACPI_PLATFORM_PROFILE' to Dell KConfig
v4:
- Make thermal_init and thermal_cleanup static
- Rearrange order of added includes, did not edit current includes
- Include bits.h
- Switch comment style
- Return error if platform_profile registering failed
- Add thermal calls to call_blacklist
- Align defines with tabs
- Correct separation of function and error handling
- Propagate error codes up
v3:
- Convert smbios-thermal-ctl docs to multiline comment and wrap
- Change thermal_mode_bits enum to directly be BIT() values
- Convert related code to use this
- Use FIELD_GET/PREP and GENNMASK for getting/setting thermal modes
- Correct offset for getting current ACC mode, setting offset
unchanged
- Check if thermal_handler is allocated before freeing and
unregistering platform_profile
v2:
- Wrap smbios-thermal-ctl comment
- Return proper error code when invalid state returned
- Simplify platform_profile_get returns
- Propogate ENOMEM error

Lyndon Sanche (2):
platform/x86: dell-smbios: Add helper for checking supported commands
platform/x86: dell-laptop: Implement platform_profile

drivers/platform/x86/dell/Kconfig | 2 +
drivers/platform/x86/dell/dell-laptop.c | 242 +++++++++++++++++++
drivers/platform/x86/dell/dell-smbios-base.c | 7 +
drivers/platform/x86/dell/dell-smbios.h | 2 +
4 files changed, 253 insertions(+)

--
2.42.0


2024-05-11 02:39:40

by Lyndon Sanche

[permalink] [raw]
Subject: [PATCH v6 1/2] platform/x86: dell-smbios: Add helper for checking supported commands

Add symbol to check if a specific class of smbios command is supported.

Signed-off-by: Lyndon Sanche <[email protected]>
---
drivers/platform/x86/dell/dell-smbios-base.c | 6 ++++++
drivers/platform/x86/dell/dell-smbios.h | 1 +
2 files changed, 7 insertions(+)

diff --git a/drivers/platform/x86/dell/dell-smbios-base.c b/drivers/platform/x86/dell/dell-smbios-base.c
index e61bfaf8b5c4..6ae09d7f76fb 100644
--- a/drivers/platform/x86/dell/dell-smbios-base.c
+++ b/drivers/platform/x86/dell/dell-smbios-base.c
@@ -350,6 +350,12 @@ void dell_laptop_call_notifier(unsigned long action, void *data)
}
EXPORT_SYMBOL_GPL(dell_laptop_call_notifier);

+bool dell_laptop_check_supported_cmds(u16 class)
+{
+ return da_supported_commands & (1 << class);
+}
+EXPORT_SYMBOL_GPL(dell_laptop_check_supported_cmds);
+
static void __init parse_da_table(const struct dmi_header *dm)
{
/* Final token is a terminator, so we don't want to copy it */
diff --git a/drivers/platform/x86/dell/dell-smbios.h b/drivers/platform/x86/dell/dell-smbios.h
index eb341bf000c6..63116671eada 100644
--- a/drivers/platform/x86/dell/dell-smbios.h
+++ b/drivers/platform/x86/dell/dell-smbios.h
@@ -73,6 +73,7 @@ enum dell_laptop_notifier_actions {
int dell_laptop_register_notifier(struct notifier_block *nb);
int dell_laptop_unregister_notifier(struct notifier_block *nb);
void dell_laptop_call_notifier(unsigned long action, void *data);
+bool dell_laptop_check_supported_cmds(u16 class);

/* for the supported backends */
#ifdef CONFIG_DELL_SMBIOS_WMI
--
2.42.0


2024-05-11 02:40:02

by Lyndon Sanche

[permalink] [raw]
Subject: [PATCH v6 2/2] platform/x86: dell-laptop: Implement platform_profile

Some Dell laptops support configuration of preset fan modes through
smbios tables.

If the platform supports these fan modes, set up platform_profile to
change these modes. If not supported, skip enabling platform_profile.

Signed-off-by: Lyndon Sanche <[email protected]>
---
drivers/platform/x86/dell/Kconfig | 2 +
drivers/platform/x86/dell/dell-laptop.c | 242 +++++++++++++++++++
drivers/platform/x86/dell/dell-smbios-base.c | 1 +
drivers/platform/x86/dell/dell-smbios.h | 1 +
4 files changed, 246 insertions(+)

diff --git a/drivers/platform/x86/dell/Kconfig b/drivers/platform/x86/dell/Kconfig
index bd9f445974cc..26679f22733c 100644
--- a/drivers/platform/x86/dell/Kconfig
+++ b/drivers/platform/x86/dell/Kconfig
@@ -47,6 +47,7 @@ config DCDBAS
config DELL_LAPTOP
tristate "Dell Laptop Extras"
default m
+ depends on ACPI
depends on DMI
depends on BACKLIGHT_CLASS_DEVICE
depends on ACPI_VIDEO || ACPI_VIDEO = n
@@ -57,6 +58,7 @@ config DELL_LAPTOP
select POWER_SUPPLY
select LEDS_CLASS
select NEW_LEDS
+ select ACPI_PLATFORM_PROFILE
help
This driver adds support for rfkill and backlight control to Dell
laptops (except for some models covered by the Compal driver).
diff --git a/drivers/platform/x86/dell/dell-laptop.c b/drivers/platform/x86/dell/dell-laptop.c
index 42f7de2b4522..07f54f1cbac5 100644
--- a/drivers/platform/x86/dell/dell-laptop.c
+++ b/drivers/platform/x86/dell/dell-laptop.c
@@ -27,6 +27,9 @@
#include <linux/i8042.h>
#include <linux/debugfs.h>
#include <linux/seq_file.h>
+#include <linux/bitfield.h>
+#include <linux/bits.h>
+#include <linux/platform_profile.h>
#include <acpi/video.h>
#include "dell-rbtn.h"
#include "dell-smbios.h"
@@ -95,6 +98,7 @@ static struct backlight_device *dell_backlight_device;
static struct rfkill *wifi_rfkill;
static struct rfkill *bluetooth_rfkill;
static struct rfkill *wwan_rfkill;
+static struct platform_profile_handler *thermal_handler;
static bool force_rfkill;
static bool micmute_led_registered;
static bool mute_led_registered;
@@ -2199,6 +2203,236 @@ static int mute_led_set(struct led_classdev *led_cdev,
return 0;
}

+/* Derived from smbios-thermal-ctl
+ *
+ * cbClass 17
+ * cbSelect 19
+ * User Selectable Thermal Tables(USTT)
+ * cbArg1 determines the function to be performed
+ * cbArg1 0x0 = Get Thermal Information
+ * cbRES1 Standard return codes (0, -1, -2)
+ * cbRES2, byte 0 Bitmap of supported thermal modes. A mode is supported if
+ * its bit is set to 1
+ * Bit 0 Balanced
+ * Bit 1 Cool Bottom
+ * Bit 2 Quiet
+ * Bit 3 Performance
+ * cbRES2, byte 1 Bitmap of supported Active Acoustic Controller (AAC) modes.
+ * Each mode corresponds to the supported thermal modes in
+ * byte 0. A mode is supported if its bit is set to 1.
+ * Bit 0 AAC (Balanced)
+ * Bit 1 AAC (Cool Bottom
+ * Bit 2 AAC (Quiet)
+ * Bit 3 AAC (Performance)
+ * cbRes3, byte 0 Current Thermal Mode
+ * Bit 0 Balanced
+ * Bit 1 Cool Bottom
+ * Bit 2 Quiet
+ * Bit 3 Performanc
+ * cbRes3, byte 1 AAC Configuration type
+ * 0 Global (AAC enable/disable applies to all supported USTT modes)
+ * 1 USTT mode specific
+ * cbRes3, byte 2 Current Active Acoustic Controller (AAC) Mode
+ * If AAC Configuration Type is Global,
+ * 0 AAC mode disabled
+ * 1 AAC mode enabled
+ * If AAC Configuration Type is USTT mode specific (multiple bits may be set),
+ * Bit 0 AAC (Balanced)
+ * Bit 1 AAC (Cool Bottom
+ * Bit 2 AAC (Quiet)
+ * Bit 3 AAC (Performance)
+ * cbRes3, byte 3 Current Fan Failure Mode
+ * Bit 0 Minimal Fan Failure (at least one fan has failed, one fan working)
+ * Bit 1 Catastrophic Fan Failure (all fans have failed)
+ *
+ * cbArg1 0x1 (Set Thermal Information), both desired thermal mode and
+ * desired AAC mode shall be applied
+ * cbArg2, byte 0 Desired Thermal Mode to set
+ * (only one bit may be set for this parameter)
+ * Bit 0 Balanced
+ * Bit 1 Cool Bottom
+ * Bit 2 Quiet
+ * Bit 3 Performance
+ * cbArg2, byte 1 Desired Active Acoustic Controller (AAC) Mode to set
+ * If AAC Configuration Type is Global,
+ * 0 AAC mode disabled
+ * 1 AAC mode enabled
+ * If AAC Configuration Type is USTT mode specific
+ * (multiple bits may be set for this parameter),
+ * Bit 0 AAC (Balanced)
+ * Bit 1 AAC (Cool Bottom
+ * Bit 2 AAC (Quiet)
+ * Bit 3 AAC (Performance)
+ */
+
+#define DELL_ACC_GET_FIELD GENMASK(19, 16)
+#define DELL_ACC_SET_FIELD GENMASK(11, 8)
+#define DELL_THERMAL_SUPPORTED GENMASK(3, 0)
+
+enum thermal_mode_bits {
+ DELL_BALANCED = BIT(0),
+ DELL_COOL_BOTTOM = BIT(1),
+ DELL_QUIET = BIT(2),
+ DELL_PERFORMANCE = BIT(3),
+};
+
+static int thermal_get_mode(void)
+{
+ struct calling_interface_buffer buffer;
+ int state;
+ int ret;
+
+ dell_fill_request(&buffer, 0x0, 0, 0, 0);
+ ret = dell_send_request(&buffer, CLASS_INFO, SELECT_THERMAL_MANAGEMENT);
+ if (ret)
+ return ret;
+ state = buffer.output[2];
+ if (state & DELL_BALANCED)
+ return DELL_BALANCED;
+ else if (state & DELL_COOL_BOTTOM)
+ return DELL_COOL_BOTTOM;
+ else if (state & DELL_QUIET)
+ return DELL_QUIET;
+ else if (state & DELL_PERFORMANCE)
+ return DELL_PERFORMANCE;
+ else
+ return -ENXIO;
+}
+
+static int thermal_get_supported_modes(int *supported_bits)
+{
+ struct calling_interface_buffer buffer;
+ int ret;
+
+ dell_fill_request(&buffer, 0x0, 0, 0, 0);
+ ret = dell_send_request(&buffer, CLASS_INFO, SELECT_THERMAL_MANAGEMENT);
+ if (ret)
+ return ret;
+ *supported_bits = FIELD_GET(DELL_THERMAL_SUPPORTED, buffer.output[1]);
+ return 0;
+}
+
+static int thermal_get_acc_mode(int *acc_mode)
+{
+ struct calling_interface_buffer buffer;
+ int ret;
+
+ dell_fill_request(&buffer, 0x0, 0, 0, 0);
+ ret = dell_send_request(&buffer, CLASS_INFO, SELECT_THERMAL_MANAGEMENT);
+ if (ret)
+ return ret;
+ *acc_mode = FIELD_GET(DELL_ACC_GET_FIELD, buffer.output[3]);
+ return 0;
+}
+
+static int thermal_set_mode(enum thermal_mode_bits state)
+{
+ struct calling_interface_buffer buffer;
+ int ret;
+ int acc_mode;
+
+ ret = thermal_get_acc_mode(&acc_mode);
+ if (ret)
+ return ret;
+
+ dell_fill_request(&buffer, 0x1, FIELD_PREP(DELL_ACC_SET_FIELD, acc_mode) | state, 0, 0);
+ ret = dell_send_request(&buffer, CLASS_INFO, SELECT_THERMAL_MANAGEMENT);
+ return ret;
+}
+
+static int thermal_platform_profile_set(struct platform_profile_handler *pprof,
+ enum platform_profile_option profile)
+{
+ switch (profile) {
+ case PLATFORM_PROFILE_BALANCED:
+ return thermal_set_mode(DELL_BALANCED);
+ case PLATFORM_PROFILE_PERFORMANCE:
+ return thermal_set_mode(DELL_PERFORMANCE);
+ case PLATFORM_PROFILE_QUIET:
+ return thermal_set_mode(DELL_QUIET);
+ case PLATFORM_PROFILE_COOL:
+ return thermal_set_mode(DELL_COOL_BOTTOM);
+ default:
+ return -EOPNOTSUPP;
+ }
+}
+
+static int thermal_platform_profile_get(struct platform_profile_handler *pprof,
+ enum platform_profile_option *profile)
+{
+ int ret;
+
+ ret = thermal_get_mode();
+ if (ret < 0)
+ return ret;
+
+ switch (ret) {
+ case DELL_BALANCED:
+ *profile = PLATFORM_PROFILE_BALANCED;
+ break;
+ case DELL_PERFORMANCE:
+ *profile = PLATFORM_PROFILE_PERFORMANCE;
+ break;
+ case DELL_COOL_BOTTOM:
+ *profile = PLATFORM_PROFILE_COOL;
+ break;
+ case DELL_QUIET:
+ *profile = PLATFORM_PROFILE_QUIET;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int thermal_init(void)
+{
+ int ret;
+ int supported_modes;
+
+ /* If thermal commands not supported, exit without error */
+ if (!dell_laptop_check_supported_cmds(CLASS_INFO))
+ return 0;
+
+ /* If thermal modes not supported, exit without error */
+ ret = thermal_get_supported_modes(&supported_modes);
+ if (ret < 0)
+ return ret;
+ if (!supported_modes)
+ return 0;
+
+ thermal_handler = kzalloc(sizeof(*thermal_handler), GFP_KERNEL);
+ if (!thermal_handler)
+ return -ENOMEM;
+ thermal_handler->profile_get = thermal_platform_profile_get;
+ thermal_handler->profile_set = thermal_platform_profile_set;
+
+ if (supported_modes & DELL_QUIET)
+ set_bit(PLATFORM_PROFILE_QUIET, thermal_handler->choices);
+ if (supported_modes & DELL_COOL_BOTTOM)
+ set_bit(PLATFORM_PROFILE_COOL, thermal_handler->choices);
+ if (supported_modes & DELL_BALANCED)
+ set_bit(PLATFORM_PROFILE_BALANCED, thermal_handler->choices);
+ if (supported_modes & DELL_PERFORMANCE)
+ set_bit(PLATFORM_PROFILE_PERFORMANCE, thermal_handler->choices);
+
+ /* Clean up if failed */
+ ret = platform_profile_register(thermal_handler);
+ if (ret)
+ kfree(thermal_handler);
+
+ return ret;
+}
+
+static void thermal_cleanup(void)
+{
+ if (thermal_handler) {
+ platform_profile_remove();
+ kfree(thermal_handler);
+ }
+}
+
static struct led_classdev mute_led_cdev = {
.name = "platform::mute",
.max_brightness = 1,
@@ -2238,6 +2472,11 @@ static int __init dell_init(void)
goto fail_rfkill;
}

+ /* Do not fail module if thermal modes not supported, just skip */
+ ret = thermal_init();
+ if (ret)
+ goto fail_thermal;
+
if (quirks && quirks->touchpad_led)
touchpad_led_init(&platform_device->dev);

@@ -2317,6 +2556,8 @@ static int __init dell_init(void)
led_classdev_unregister(&mute_led_cdev);
fail_led:
dell_cleanup_rfkill();
+fail_thermal:
+ thermal_cleanup();
fail_rfkill:
platform_device_del(platform_device);
fail_platform_device2:
@@ -2344,6 +2585,7 @@ static void __exit dell_exit(void)
platform_device_unregister(platform_device);
platform_driver_unregister(&platform_driver);
}
+ thermal_cleanup();
}

/* dell-rbtn.c driver export functions which will not work correctly (and could
diff --git a/drivers/platform/x86/dell/dell-smbios-base.c b/drivers/platform/x86/dell/dell-smbios-base.c
index 6ae09d7f76fb..387fa5618f7a 100644
--- a/drivers/platform/x86/dell/dell-smbios-base.c
+++ b/drivers/platform/x86/dell/dell-smbios-base.c
@@ -71,6 +71,7 @@ static struct smbios_call call_blacklist[] = {
/* handled by kernel: dell-laptop */
{0x0000, CLASS_INFO, SELECT_RFKILL},
{0x0000, CLASS_KBD_BACKLIGHT, SELECT_KBD_BACKLIGHT},
+ {0x0000, CLASS_INFO, SELECT_THERMAL_MANAGEMENT},
};

struct token_range {
diff --git a/drivers/platform/x86/dell/dell-smbios.h b/drivers/platform/x86/dell/dell-smbios.h
index 63116671eada..5d7178df80c6 100644
--- a/drivers/platform/x86/dell/dell-smbios.h
+++ b/drivers/platform/x86/dell/dell-smbios.h
@@ -19,6 +19,7 @@
/* Classes and selects used only in kernel drivers */
#define CLASS_KBD_BACKLIGHT 4
#define SELECT_KBD_BACKLIGHT 11
+#define SELECT_THERMAL_MANAGEMENT 19

/* Tokens used in kernel drivers, any of these
* should be filtered from userspace access
--
2.42.0


2024-05-11 15:07:16

by Shen, Yijun

[permalink] [raw]
Subject: RE: RE: [PATCH v5] platform/x86: dell-laptop: Implement platform_profile


Internal Use - Confidential
+AD4- -----Original Message-----
+AD4- From: Mario Limonciello +ADw-mario.limonciello+AEA-amd.com+AD4-
+AD4- Sent: Wednesday, May 8, 2024 11:53 PM
+AD4- To: Shen, Yijun +ADw-Yijun+AF8-Shen+AEA-Dell.com+AD4AOw- Lyndon Sanche
+AD4- +ADw-lsanche+AEA-lyndeno.ca+AD4-
+AD4- Cc: pali+AEA-kernel.org+ADs- W+AF8-Armin+AEA-gmx.de+ADs-
+AD4- srinivas.pandruvada+AEA-linux.intel.com+ADs- ilpo.jarvinen+AEA-linux.intel.com+ADs-
+AD4- lkp+AEA-intel.com+ADs- Hans de Goede +ADw-hdegoede+AEA-redhat.com+AD4AOw- Matthew Garrett
+AD4- +ADw-mjg59+AEA-srcf.ucam.org+AD4AOw- Jonathan Corbet +ADw-corbet+AEA-lwn.net+AD4AOw- Heiner Kallweit
+AD4- +ADw-hkallweit1+AEA-gmail.com+AD4AOw- Vegard Nossum +ADw-vegard.nossum+AEA-oracle.com+AD4AOw-
+AD4- platform-driver-x86+AEA-vger.kernel.org+ADs- linux-kernel+AEA-vger.kernel.org+ADs- Dell Client
+AD4- Kernel +ADw-Dell.Client.Kernel+AEA-dell.com+AD4-
+AD4- Subject: Re: RE: +AFs-PATCH v5+AF0- platform/x86: dell-laptop: Implement
+AD4- platform+AF8-profile
+AD4-
+AD4-
+AD4- +AFs-EXTERNAL EMAIL+AF0-
+AD4-
+AD4- On 5/8/2024 09:24, Shen, Yijun wrote:
+AD4- +AD4- Hi Lyndon,
+AD4- +AD4-
+AD4- +AD4- Thanks for working on this patch.
+AD4- +AD4-
+AD4- +AD4APg-
+AD4- +AD4- Dell side has an initial testing with this patch on some laptops, it looks
+AD4- good. While changing the platform profile:
+AD4- +AD4- 1. The corresponding USTT option in BIOS will be changed.
+AD4- +AD4- 2. thermald will not be impacted. The related PSVT and ITMT will be loaded.
+AD4- +AD4- Some Dell DTs does not have the USTT, Dell'll have a check if nothing is
+AD4- broken.
+AD4-
+AD4- Hi Alex+ACE-
+AD4-
+AD4- Have you had a check both on both your AMD laptops and workstations too,
+AD4- or just the Intel ones? I think it would be good to make sure it's getting the
+AD4- correct experience in both cases.
+AD4-
Hi Mario,

I've a check for this, for both laptop and workstation, the dell+AF8-laptop module will not be loaded. So, AMD platform will not be impacted by this patch series.
Follow is one example output with workstation.
+ACM-lsmod +AHw- grep dell
dell+AF8-wmi 28672 0
dell+AF8-smbios 32768 1 dell+AF8-wmi
dcdbas 20480 1 dell+AF8-smbios
dell+AF8-wmi+AF8-descriptor 20480 2 dell+AF8-wmi,dell+AF8-smbios
sparse+AF8-keymap 12288 1 dell+AF8-wmi
ledtrig+AF8-audio 12288 3 snd+AF8-ctl+AF8-led,snd+AF8-hda+AF8-codec+AF8-generic,dell+AF8-wmi
video 73728 2 dell+AF8-wmi,nvidia+AF8-modeset
wmi 40960 5 video,dell+AF8-wmi,wmi+AF8-bmof,dell+AF8-smbios,dell+AF8-wmi+AF8-descriptor

+AD4- +AD4-
+AD4- +AD4- Additional, with this patch, follow behavior is found:
+AD4- +AD4- 1. For example, the platform profile is quiet.
+AD4- +AD4- 2. Reboot the system and change the USTT to performance.
+AD4- +AD4- 3. Boot to desktop, the platform profile is +ACI-quiet+ACI-, the USTT will be
+AD4- changed back to +ACI-quiet+ACI-.
+AD4- +AD4- This looks like not a proper user experience. The platform profile should
+AD4- honor the BIOS setting, aka, the platform profile should be switched to
+AD4- +ACI-performance+ACI-.
+AD4- +AD4-
+AD4-
+AD4- I agree, this sounds like the initial profile needs to be read from the BIOS
+AD4- settings too.
+AD4-
+AD4- Furthermore I wanted to ask is there also a WMI setting that corresponds to
+AD4- this that dell-wmi-sysman offers?
Yes, Mario, you're right. This thermal setting could also be toggled by dell-wmi-sysman.
But, for the Dell consumer AMD laptops, like Alienware, the BIOS is another variant which is different with the workstation one.
With this variant BIOS, there is no USTT and also no dell+AF8-wmi/dell-wmi-sysman.

+AD4- I'm wondering if both should be probed in case the SMBIOS one goes away one day.
Yep, I think this is a good suggestion.

+AD4-
+AD4- It seems like maybe ThermalManagement corresponds. There was some test
+AD4- data in fwupd for it:
+AD4-
+AD4- https://urldefense.com/v3/+AF8AXw-https://github.com/fwupd/fwupd/tree/main/lib
+AD4- fwupdplugin/tests/bios-attrs/dell-xps13-9310/dell-wmi-
+AD4- sysman/attributes/ThermalManagement+AF8AXwA7ACEAIQ-LpKI+ACE-iyfGSyfnGxLymc-
+AD4- cEg93dfcnBIOtTJbfmCckZlj46eGqvJ+AF8-pHJ7WqFZ7-
+AD4- zrklKWKkZifqNgJ13LFm6wuz2UlzYqMPXciVw+ACQ- +AFs-github+AFs-.+AF0-com+AF0-

2024-05-11 15:13:11

by Mario Limonciello

[permalink] [raw]
Subject: Re: [PATCH v5] platform/x86: dell-laptop: Implement platform_profile



On 5/11/2024 10:05 AM, Shen, Yijun wrote:
>
> Internal Use - Confidential
>> -----Original Message-----
>> From: Mario Limonciello <[email protected]>
>> Sent: Wednesday, May 8, 2024 11:53 PM
>> To: Shen, Yijun <[email protected]>; Lyndon Sanche
>> <[email protected]>
>> Cc: [email protected]; [email protected];
>> [email protected]; [email protected];
>> [email protected]; Hans de Goede <[email protected]>; Matthew Garrett
>> <[email protected]>; Jonathan Corbet <[email protected]>; Heiner Kallweit
>> <[email protected]>; Vegard Nossum <[email protected]>;
>> [email protected]; [email protected]; Dell Client
>> Kernel <[email protected]>
>> Subject: Re: RE: [PATCH v5] platform/x86: dell-laptop: Implement
>> platform_profile
>>
>>
>> [EXTERNAL EMAIL]
>>
>> On 5/8/2024 09:24, Shen, Yijun wrote:
>>> Hi Lyndon,
>>>
>>> Thanks for working on this patch.
>>>
>>>>
>>> Dell side has an initial testing with this patch on some laptops, it looks
>> good. While changing the platform profile:
>>> 1. The corresponding USTT option in BIOS will be changed.
>>> 2. thermald will not be impacted. The related PSVT and ITMT will be loaded.
>>> Some Dell DTs does not have the USTT, Dell'll have a check if nothing is
>> broken.
>>
>> Hi Alex!
>>
>> Have you had a check both on both your AMD laptops and workstations too,
>> or just the Intel ones? I think it would be good to make sure it's getting the
>> correct experience in both cases.
>>
> Hi Mario,
>
> I've a check for this, for both laptop and workstation, the dell_laptop module will not be loaded. So, AMD platform will not be impacted by this patch series.
> Follow is one example output with workstation.
> #lsmod | grep dell
> dell_wmi 28672 0
> dell_smbios 32768 1 dell_wmi
> dcdbas 20480 1 dell_smbios
> dell_wmi_descriptor 20480 2 dell_wmi,dell_smbios
> sparse_keymap 12288 1 dell_wmi
> ledtrig_audio 12288 3 snd_ctl_led,snd_hda_codec_generic,dell_wmi
> video 73728 2 dell_wmi,nvidia_modeset
> wmi 40960 5 video,dell_wmi,wmi_bmof,dell_smbios,dell_wmi_descriptor
>

Ah; right that makes sense. In that case, is dell-laptop even the right
place for this patch series? I would think the same policies for the
platform profile should be able to apply to desktop/workstation.

The v6 of this series would block smbios-thermal-ctl from working on a
workstation too.

>>>
>>> Additional, with this patch, follow behavior is found:
>>> 1. For example, the platform profile is quiet.
>>> 2. Reboot the system and change the USTT to performance.
>>> 3. Boot to desktop, the platform profile is "quiet", the USTT will be
>> changed back to "quiet".
>>> This looks like not a proper user experience. The platform profile should
>> honor the BIOS setting, aka, the platform profile should be switched to
>> "performance".
>>>
>>
>> I agree, this sounds like the initial profile needs to be read from the BIOS
>> settings too.
>>
>> Furthermore I wanted to ask is there also a WMI setting that corresponds to
>> this that dell-wmi-sysman offers?
> Yes, Mario, you're right. This thermal setting could also be toggled by dell-wmi-sysman.
> But, for the Dell consumer AMD laptops, like Alienware, the BIOS is another variant which is different with the workstation one.
> With this variant BIOS, there is no USTT and also no dell_wmi/dell-wmi-sysman.
>
>> I'm wondering if both should be probed in case the SMBIOS one goes away one day.
> Yep, I think this is a good suggestion.
>

Great! Although something I wonder is if the policy when changed with
dell-wmi-sysman is immediate or requires a reboot. A lot of the
settings in there aren't effective until after a reboot.

If this is one of them then it might not be a good idea to make it work
for both.

2024-05-11 15:13:43

by Mario Limonciello

[permalink] [raw]
Subject: Re: [PATCH v6 1/2] platform/x86: dell-smbios: Add helper for checking supported commands



On 5/10/2024 9:36 PM, Lyndon Sanche wrote:
> Add symbol to check if a specific class of smbios command is supported.
>
> Signed-off-by: Lyndon Sanche <[email protected]>
Reviewed-by: Mario Limonciello <[email protected]>
> ---
> drivers/platform/x86/dell/dell-smbios-base.c | 6 ++++++
> drivers/platform/x86/dell/dell-smbios.h | 1 +
> 2 files changed, 7 insertions(+)
>
> diff --git a/drivers/platform/x86/dell/dell-smbios-base.c b/drivers/platform/x86/dell/dell-smbios-base.c
> index e61bfaf8b5c4..6ae09d7f76fb 100644
> --- a/drivers/platform/x86/dell/dell-smbios-base.c
> +++ b/drivers/platform/x86/dell/dell-smbios-base.c
> @@ -350,6 +350,12 @@ void dell_laptop_call_notifier(unsigned long action, void *data)
> }
> EXPORT_SYMBOL_GPL(dell_laptop_call_notifier);
>
> +bool dell_laptop_check_supported_cmds(u16 class)
> +{
> + return da_supported_commands & (1 << class);
> +}
> +EXPORT_SYMBOL_GPL(dell_laptop_check_supported_cmds);
> +
> static void __init parse_da_table(const struct dmi_header *dm)
> {
> /* Final token is a terminator, so we don't want to copy it */
> diff --git a/drivers/platform/x86/dell/dell-smbios.h b/drivers/platform/x86/dell/dell-smbios.h
> index eb341bf000c6..63116671eada 100644
> --- a/drivers/platform/x86/dell/dell-smbios.h
> +++ b/drivers/platform/x86/dell/dell-smbios.h
> @@ -73,6 +73,7 @@ enum dell_laptop_notifier_actions {
> int dell_laptop_register_notifier(struct notifier_block *nb);
> int dell_laptop_unregister_notifier(struct notifier_block *nb);
> void dell_laptop_call_notifier(unsigned long action, void *data);
> +bool dell_laptop_check_supported_cmds(u16 class);
>
> /* for the supported backends */
> #ifdef CONFIG_DELL_SMBIOS_WMI

2024-05-11 15:23:17

by Shen, Yijun

[permalink] [raw]
Subject: RE: [PATCH v5] platform/x86: dell-laptop: Implement platform_profile




Internal Use - Confidential
+AD4- -----Original Message-----
+AD4- From: Lyndon Sanche +ADw-lsanche+AEA-lyndeno.ca+AD4-
+AD4- Sent: Saturday, May 11, 2024 9:49 AM
+AD4- To: Shen, Yijun +ADw-Yijun+AF8-Shen+AEA-Dell.com+AD4-
+AD4- Cc: Mario Limonciello +ADw-mario.limonciello+AEA-amd.com+AD4AOw- Pali Roh+AOE-r
+AD4- +ADw-pali+AEA-kernel.org+AD4AOw- Armin Wolf +ADw-W+AF8-Armin+AEA-gmx.de+AD4AOw-
+AD4- srinivas.pandruvada+AEA-linux.intel.com+ADs- Ilpo J+AOQ-rvinen
+AD4- +ADw-ilpo.jarvinen+AEA-linux.intel.com+AD4AOw- kernel test robot +ADw-lkp+AEA-intel.com+AD4AOw- Hans de
+AD4- Goede +ADw-hdegoede+AEA-redhat.com+AD4AOw- Matthew Garrett +ADw-mjg59+AEA-srcf.ucam.org+AD4AOw-
+AD4- Jonathan Corbet +ADw-corbet+AEA-lwn.net+AD4AOw- Heiner Kallweit
+AD4- +ADw-hkallweit1+AEA-gmail.com+AD4AOw- Vegard Nossum +ADw-vegard.nossum+AEA-oracle.com+AD4AOw-
+AD4- platform-driver-x86+AEA-vger.kernel.org+ADs- LKML +ADw-linux-kernel+AEA-vger.kernel.org+AD4AOw-
+AD4- Dell Client Kernel +ADw-Dell.Client.Kernel+AEA-dell.com+AD4-
+AD4- Subject: Re: +AFs-PATCH v5+AF0- platform/x86: dell-laptop: Implement platform+AF8-profile
+AD4-
+AD4-
+AD4- +AFs-EXTERNAL EMAIL+AF0-
+AD4-
+AD4-
+AD4-
+AD4- On Thu, May 9 2024 at 09:10:51 AM -06:00:00, Lyndon Sanche
+AD4- +ADw-lsanche+AEA-lyndeno.ca+AD4- wrote:
+AD4- +AD4- On Wed, May 8, 2024, at 8:24 AM, Shen, Yijun wrote:
+AD4- +AD4APg- Hi Lyndon,
+AD4- +AD4APg-
+AD4- +AD4APg- Thanks for working on this patch.
+AD4- +AD4APg-
+AD4- +AD4APg-
+AD4- +AD4APg- Dell side has an initial testing with this patch on some laptops,
+AD4- +AD4APg- it looks good. While changing the platform profile:
+AD4- +AD4APg- 1. The corresponding USTT option in BIOS will be changed.
+AD4- +AD4APg- 2. thermald will not be impacted. The related PSVT and ITMT will be
+AD4- +AD4APg- loaded.
+AD4- +AD4APg- Some Dell DTs does not have the USTT, Dell'll have a check if
+AD4- +AD4APg- nothing is broken.
+AD4- +AD4APg-
+AD4- +AD4APg- Additional, with this patch, follow behavior is found:
+AD4- +AD4APg- 1. For example, the platform profile is quiet.
+AD4- +AD4APg- 2. Reboot the system and change the USTT to performance.
+AD4- +AD4APg- 3. Boot to desktop, the platform profile is +ACI-quiet+ACI-, the USTT will
+AD4- +AD4APg- be changed back to +ACI-quiet+ACI-.
+AD4- +AD4APg- This looks like not a proper user experience. The platform profile
+AD4- +AD4APg- should honor the BIOS setting, aka, the platform profile should be
+AD4- +AD4APg- switched to +ACI-performance+ACI-.
+AD4- +AD4-
+AD4- +AD4- Hello:
+AD4- +AD4-
+AD4- +AD4- Thank you for your email. This is definitely undesirable behaviour, I
+AD4- +AD4- will have a look at the code to see why this is happening. Does it
+AD4- +AD4- always revert to quiet on boot, or always the mode that you had
+AD4- +AD4- switched to prior to reboot?
+AD4- +AD4-
+AD4- +AD4- Do you happen to have power-profiles-daemon or something similar
+AD4- +AD4- running? My understanding is it remembers profiles across reboots,
+AD4- +AD4- this could potentially also revert the profile back to what it was.
+AD4- +AD4- See this release for details:
+AD4- +AD4- https://urldefense.com/v3/+AF8AXw-https://gitlab.freedesktop.org/upower/powe
+AD4- +AD4- r-profiles-daemon/-/releases/0.9.0+AF8AXwA7ACEAIQ-LpKI+ACE-jUAEHb-9foumkcmPlEKD6tnQrZ
+AD4- +AD4- sqjB1sXdPDsYvH2fJ-gPV6G35MUtDW4q3xhlJ4IeLcIgmVpb3ztXqaOg8+ACQ-
+AD4- +AD4- +AFs-gitlab+AFs-.+AF0-freedesktop+AFs-.+AF0-org+AF0-
+AD4- +AD4-
+AD4- +AD4- I will assume there is a bug in my code at this point. I will test
+AD4- +AD4- with and without ppd running on my system to see if it changes across
+AD4- +AD4- reboots.
+AD4- +AD4-
+AD4- +AD4- Are USTT settings exposed in your BIOS configuration menu? On my
+AD4- +AD4- laptop they are not and I have to use smbios-thermal-ctl.
+AD4- +AD4-
+AD4- +AD4- Thank you,
+AD4- +AD4-
+AD4- +AD4- Lyndon
+AD4-
+AD4- Hi Yijun:
+AD4-
+AD4- I tested this on my computer (XPS 9560). I do not have access to the USTT
+AD4- settings in the BIOS screen so to substitute that, I booted without the patch
+AD4- and set the USTT manually using smbios-thermal-ctl.
+AD4- Here are my findings:
+AD4-
+AD4- Scenario +ACM-1: Without power-profiles-daemon (ppd) running
+AD4-
+AD4- 1. Boot with patch, set platform+AF8-profile to quiet 2. Boot without patch applied
+AD4- (no platform+AF8-profile)
+AD4- - smbios-thermal-ctl confirms USTT is set to quiet
+AD4- - use smbios-thermal-ctl to set USTT to performance
+AD4- - confirm set to performance
+AD4- 3. Boot with patch again
+AD4- - platform+AF8-profile is set to performance
+AD4-
+AD4- Scenario +ACM-2: With ppd running
+AD4- 1. Boot with patch, set platform+AF8-profile to performance with ppd
+AD4- - Confirm platform+AF8-profile is performance 2. Boot without patch applied (no
+AD4- platform+AF8-profile)
+AD4- - smbios-thermal-ctl confirms USTT is set to performance
+AD4- - ppd reverts to balanced (only controlling intel+AF8-pstate in this case)
+AD4- - use smbios-thermal-ctl to set USTT to quiet
+AD4- - confirm set to quiet
+AD4- 3. Boot with patch again
+AD4- - platform+AF8-profile and ppd is set to performance
+AD4-
+AD4- In my case, the setting in the smbios is honored if it was switched with
+AD4- another method. When using a userspace program that manipulates the
+AD4- platform+AF8-profile, the program seems to remember the previous state and
+AD4- switch to that.
+AD4-
+AD4- So I do not think there is a bug in this patch related to this issue, at least in my
+AD4- case. Please let me know if you have any questions.
+AD4-
+AD4- Thanks,
+AD4-
+AD4- Lyndon
+AD4-
+AD4-
+AD4-
Hi Lyndon,

I've made a video recorder of the issue: https://dell.box.com/s/3f3znz1z8c6htbcll9juj6tyyu0zvvut
My test environment is that I freshly installed the Fedora 40 and will not do any online updates. Then install the kernel with the v5 patch applied.

XPS 9560 is a pretty old system which is RTS with 2017. No USTT setting in the BIOS is expected.
I've a check that the Dell system, at least shipped from 2022, the USTT setting will be valid in the BIOS. The system used in above link, it is Latitude 7350 which is shipped by 2024 April.

I think the key point to duplicate of this issue that, the USTT needs to be changed under BIOS but not under the Linux OS.

Thanks



2024-05-11 15:24:32

by Mario Limonciello

[permalink] [raw]
Subject: Re: [PATCH v6 2/2] platform/x86: dell-laptop: Implement platform_profile



On 5/10/2024 9:36 PM, Lyndon Sanche wrote:
> Some Dell laptops support configuration of preset fan modes through
> smbios tables.
>
> If the platform supports these fan modes, set up platform_profile to
> change these modes. If not supported, skip enabling platform_profile.
>
> Signed-off-by: Lyndon Sanche <[email protected]>
> ---
> drivers/platform/x86/dell/Kconfig | 2 +
> drivers/platform/x86/dell/dell-laptop.c | 242 +++++++++++++++++++
> drivers/platform/x86/dell/dell-smbios-base.c | 1 +
> drivers/platform/x86/dell/dell-smbios.h | 1 +
> 4 files changed, 246 insertions(+)
>
> diff --git a/drivers/platform/x86/dell/Kconfig b/drivers/platform/x86/dell/Kconfig
> index bd9f445974cc..26679f22733c 100644
> --- a/drivers/platform/x86/dell/Kconfig
> +++ b/drivers/platform/x86/dell/Kconfig
> @@ -47,6 +47,7 @@ config DCDBAS
> config DELL_LAPTOP
> tristate "Dell Laptop Extras"
> default m
> + depends on ACPI
> depends on DMI
> depends on BACKLIGHT_CLASS_DEVICE
> depends on ACPI_VIDEO || ACPI_VIDEO = n
> @@ -57,6 +58,7 @@ config DELL_LAPTOP
> select POWER_SUPPLY
> select LEDS_CLASS
> select NEW_LEDS
> + select ACPI_PLATFORM_PROFILE
> help
> This driver adds support for rfkill and backlight control to Dell
> laptops (except for some models covered by the Compal driver).
> diff --git a/drivers/platform/x86/dell/dell-laptop.c b/drivers/platform/x86/dell/dell-laptop.c
> index 42f7de2b4522..07f54f1cbac5 100644
> --- a/drivers/platform/x86/dell/dell-laptop.c
> +++ b/drivers/platform/x86/dell/dell-laptop.c
> @@ -27,6 +27,9 @@
> #include <linux/i8042.h>
> #include <linux/debugfs.h>
> #include <linux/seq_file.h>
> +#include <linux/bitfield.h>
> +#include <linux/bits.h>
> +#include <linux/platform_profile.h>
> #include <acpi/video.h>
> #include "dell-rbtn.h"
> #include "dell-smbios.h"
> @@ -95,6 +98,7 @@ static struct backlight_device *dell_backlight_device;
> static struct rfkill *wifi_rfkill;
> static struct rfkill *bluetooth_rfkill;
> static struct rfkill *wwan_rfkill;
> +static struct platform_profile_handler *thermal_handler;
> static bool force_rfkill;
> static bool micmute_led_registered;
> static bool mute_led_registered;
> @@ -2199,6 +2203,236 @@ static int mute_led_set(struct led_classdev *led_cdev,
> return 0;
> }
>
> +/* Derived from smbios-thermal-ctl
> + *
> + * cbClass 17
> + * cbSelect 19
> + * User Selectable Thermal Tables(USTT)
> + * cbArg1 determines the function to be performed
> + * cbArg1 0x0 = Get Thermal Information
> + * cbRES1 Standard return codes (0, -1, -2)
> + * cbRES2, byte 0 Bitmap of supported thermal modes. A mode is supported if
> + * its bit is set to 1
> + * Bit 0 Balanced
> + * Bit 1 Cool Bottom
> + * Bit 2 Quiet
> + * Bit 3 Performance
> + * cbRES2, byte 1 Bitmap of supported Active Acoustic Controller (AAC) modes.
> + * Each mode corresponds to the supported thermal modes in
> + * byte 0. A mode is supported if its bit is set to 1.
> + * Bit 0 AAC (Balanced)
> + * Bit 1 AAC (Cool Bottom
> + * Bit 2 AAC (Quiet)
> + * Bit 3 AAC (Performance)
> + * cbRes3, byte 0 Current Thermal Mode
> + * Bit 0 Balanced
> + * Bit 1 Cool Bottom
> + * Bit 2 Quiet
> + * Bit 3 Performanc
> + * cbRes3, byte 1 AAC Configuration type
> + * 0 Global (AAC enable/disable applies to all supported USTT modes)
> + * 1 USTT mode specific
> + * cbRes3, byte 2 Current Active Acoustic Controller (AAC) Mode
> + * If AAC Configuration Type is Global,
> + * 0 AAC mode disabled
> + * 1 AAC mode enabled
> + * If AAC Configuration Type is USTT mode specific (multiple bits may be set),
> + * Bit 0 AAC (Balanced)
> + * Bit 1 AAC (Cool Bottom
> + * Bit 2 AAC (Quiet)
> + * Bit 3 AAC (Performance)
> + * cbRes3, byte 3 Current Fan Failure Mode
> + * Bit 0 Minimal Fan Failure (at least one fan has failed, one fan working)
> + * Bit 1 Catastrophic Fan Failure (all fans have failed)
> + *
> + * cbArg1 0x1 (Set Thermal Information), both desired thermal mode and
> + * desired AAC mode shall be applied
> + * cbArg2, byte 0 Desired Thermal Mode to set
> + * (only one bit may be set for this parameter)
> + * Bit 0 Balanced
> + * Bit 1 Cool Bottom
> + * Bit 2 Quiet
> + * Bit 3 Performance
> + * cbArg2, byte 1 Desired Active Acoustic Controller (AAC) Mode to set
> + * If AAC Configuration Type is Global,
> + * 0 AAC mode disabled
> + * 1 AAC mode enabled
> + * If AAC Configuration Type is USTT mode specific
> + * (multiple bits may be set for this parameter),
> + * Bit 0 AAC (Balanced)
> + * Bit 1 AAC (Cool Bottom
> + * Bit 2 AAC (Quiet)
> + * Bit 3 AAC (Performance)
> + */
> +
> +#define DELL_ACC_GET_FIELD GENMASK(19, 16)
> +#define DELL_ACC_SET_FIELD GENMASK(11, 8)
> +#define DELL_THERMAL_SUPPORTED GENMASK(3, 0)
> +
> +enum thermal_mode_bits {
> + DELL_BALANCED = BIT(0),
> + DELL_COOL_BOTTOM = BIT(1),
> + DELL_QUIET = BIT(2),
> + DELL_PERFORMANCE = BIT(3),
> +};
> +
> +static int thermal_get_mode(void)
> +{
> + struct calling_interface_buffer buffer;
> + int state;
> + int ret;
> +
> + dell_fill_request(&buffer, 0x0, 0, 0, 0);
> + ret = dell_send_request(&buffer, CLASS_INFO, SELECT_THERMAL_MANAGEMENT);
> + if (ret)
> + return ret;
> + state = buffer.output[2];
> + if (state & DELL_BALANCED)
> + return DELL_BALANCED;
> + else if (state & DELL_COOL_BOTTOM)
> + return DELL_COOL_BOTTOM;
> + else if (state & DELL_QUIET)
> + return DELL_QUIET;
> + else if (state & DELL_PERFORMANCE)
> + return DELL_PERFORMANCE;
> + else
> + return -ENXIO;
> +}
> +
> +static int thermal_get_supported_modes(int *supported_bits)
> +{
> + struct calling_interface_buffer buffer;
> + int ret;
> +
> + dell_fill_request(&buffer, 0x0, 0, 0, 0);
> + ret = dell_send_request(&buffer, CLASS_INFO, SELECT_THERMAL_MANAGEMENT);
> + if (ret)
> + return ret;
> + *supported_bits = FIELD_GET(DELL_THERMAL_SUPPORTED, buffer.output[1]);
> + return 0;
> +}
> +
> +static int thermal_get_acc_mode(int *acc_mode)
> +{
> + struct calling_interface_buffer buffer;
> + int ret;
> +
> + dell_fill_request(&buffer, 0x0, 0, 0, 0);
> + ret = dell_send_request(&buffer, CLASS_INFO, SELECT_THERMAL_MANAGEMENT);
> + if (ret)
> + return ret;
> + *acc_mode = FIELD_GET(DELL_ACC_GET_FIELD, buffer.output[3]);
> + return 0;
> +}
> +
> +static int thermal_set_mode(enum thermal_mode_bits state)
> +{
> + struct calling_interface_buffer buffer;
> + int ret;
> + int acc_mode;
> +
> + ret = thermal_get_acc_mode(&acc_mode);
> + if (ret)
> + return ret;
> +
> + dell_fill_request(&buffer, 0x1, FIELD_PREP(DELL_ACC_SET_FIELD, acc_mode) | state, 0, 0);
> + ret = dell_send_request(&buffer, CLASS_INFO, SELECT_THERMAL_MANAGEMENT);
> + return ret;
> +}
> +
> +static int thermal_platform_profile_set(struct platform_profile_handler *pprof,
> + enum platform_profile_option profile)
> +{
> + switch (profile) {
> + case PLATFORM_PROFILE_BALANCED:
> + return thermal_set_mode(DELL_BALANCED);
> + case PLATFORM_PROFILE_PERFORMANCE:
> + return thermal_set_mode(DELL_PERFORMANCE);
> + case PLATFORM_PROFILE_QUIET:
> + return thermal_set_mode(DELL_QUIET);
> + case PLATFORM_PROFILE_COOL:
> + return thermal_set_mode(DELL_COOL_BOTTOM);
> + default:
> + return -EOPNOTSUPP;
> + }
> +}
> +
> +static int thermal_platform_profile_get(struct platform_profile_handler *pprof,
> + enum platform_profile_option *profile)
> +{
> + int ret;
> +
> + ret = thermal_get_mode();
> + if (ret < 0)
> + return ret;
> +
> + switch (ret) {
> + case DELL_BALANCED:
> + *profile = PLATFORM_PROFILE_BALANCED;
> + break;
> + case DELL_PERFORMANCE:
> + *profile = PLATFORM_PROFILE_PERFORMANCE;
> + break;
> + case DELL_COOL_BOTTOM:
> + *profile = PLATFORM_PROFILE_COOL;
> + break;
> + case DELL_QUIET:
> + *profile = PLATFORM_PROFILE_QUIET;
> + break;
> + default:
> + return -EINVAL;
> + }
> +
> + return 0;
> +}
> +
> +static int thermal_init(void)
> +{
> + int ret;
> + int supported_modes;
> +
> + /* If thermal commands not supported, exit without error */
> + if (!dell_laptop_check_supported_cmds(CLASS_INFO))
> + return 0;
> +
> + /* If thermal modes not supported, exit without error */
> + ret = thermal_get_supported_modes(&supported_modes);
> + if (ret < 0)
> + return ret;
> + if (!supported_modes)
> + return 0;
> +
> + thermal_handler = kzalloc(sizeof(*thermal_handler), GFP_KERNEL);
> + if (!thermal_handler)
> + return -ENOMEM;
> + thermal_handler->profile_get = thermal_platform_profile_get;
> + thermal_handler->profile_set = thermal_platform_profile_set;
> +
> + if (supported_modes & DELL_QUIET)
> + set_bit(PLATFORM_PROFILE_QUIET, thermal_handler->choices);
> + if (supported_modes & DELL_COOL_BOTTOM)
> + set_bit(PLATFORM_PROFILE_COOL, thermal_handler->choices);
> + if (supported_modes & DELL_BALANCED)
> + set_bit(PLATFORM_PROFILE_BALANCED, thermal_handler->choices);
> + if (supported_modes & DELL_PERFORMANCE)
> + set_bit(PLATFORM_PROFILE_PERFORMANCE, thermal_handler->choices);
> +
> + /* Clean up if failed */
> + ret = platform_profile_register(thermal_handler);
> + if (ret)
> + kfree(thermal_handler);
> +
> + return ret;
> +}
> +
> +static void thermal_cleanup(void)
> +{
> + if (thermal_handler) {
> + platform_profile_remove();
> + kfree(thermal_handler);
> + }
> +}
> +
> static struct led_classdev mute_led_cdev = {
> .name = "platform::mute",
> .max_brightness = 1,
> @@ -2238,6 +2472,11 @@ static int __init dell_init(void)
> goto fail_rfkill;
> }
>
> + /* Do not fail module if thermal modes not supported, just skip */
> + ret = thermal_init();
> + if (ret)
> + goto fail_thermal;
> +
> if (quirks && quirks->touchpad_led)
> touchpad_led_init(&platform_device->dev);
>
> @@ -2317,6 +2556,8 @@ static int __init dell_init(void)
> led_classdev_unregister(&mute_led_cdev);
> fail_led:
> dell_cleanup_rfkill();
> +fail_thermal:
> + thermal_cleanup();
> fail_rfkill:
> platform_device_del(platform_device);
> fail_platform_device2:
> @@ -2344,6 +2585,7 @@ static void __exit dell_exit(void)
> platform_device_unregister(platform_device);
> platform_driver_unregister(&platform_driver);
> }
> + thermal_cleanup();
> }
>
> /* dell-rbtn.c driver export functions which will not work correctly (and could
> diff --git a/drivers/platform/x86/dell/dell-smbios-base.c b/drivers/platform/x86/dell/dell-smbios-base.c
> index 6ae09d7f76fb..387fa5618f7a 100644
> --- a/drivers/platform/x86/dell/dell-smbios-base.c
> +++ b/drivers/platform/x86/dell/dell-smbios-base.c
> @@ -71,6 +71,7 @@ static struct smbios_call call_blacklist[] = {
> /* handled by kernel: dell-laptop */
> {0x0000, CLASS_INFO, SELECT_RFKILL},
> {0x0000, CLASS_KBD_BACKLIGHT, SELECT_KBD_BACKLIGHT},
> + {0x0000, CLASS_INFO, SELECT_THERMAL_MANAGEMENT},
> };

So when Alex checked on v5 that this doesn't load on workstations, it
has made me realize that doing this will block the interface totally
even on workstations.

So I think there are a few ways to go to handle this:

1) Rename dell-laptop to dell-client or dell-pc and let dell-laptop load
on more form factors. This would require some internal handling in the
module for which features make sense for different form factors.

2) Add a new module just for the thermal handling and put all this code
into it instead.

I don't have a strong opinion, but I do think one of them should be done
to ensure there aren't problems on workstations losing access to thermal
control.

>
> struct token_range {
> diff --git a/drivers/platform/x86/dell/dell-smbios.h b/drivers/platform/x86/dell/dell-smbios.h
> index 63116671eada..5d7178df80c6 100644
> --- a/drivers/platform/x86/dell/dell-smbios.h
> +++ b/drivers/platform/x86/dell/dell-smbios.h
> @@ -19,6 +19,7 @@
> /* Classes and selects used only in kernel drivers */
> #define CLASS_KBD_BACKLIGHT 4
> #define SELECT_KBD_BACKLIGHT 11
> +#define SELECT_THERMAL_MANAGEMENT 19
>
> /* Tokens used in kernel drivers, any of these
> * should be filtered from userspace access

2024-05-11 15:54:32

by Lyndon Sanche

[permalink] [raw]
Subject: RE: [PATCH v5] platform/x86: dell-laptop: Implement platform_profile



On May 11, 2024 9:22:23 a.m. MDT, "Shen, Yijun" <[email protected]> wrote:
>
>
>
>Internal Use - Confidential
>> -----Original Message-----
>> From: Lyndon Sanche <[email protected]>
>> Sent: Saturday, May 11, 2024 9:49 AM
>> To: Shen, Yijun <[email protected]>
>> Cc: Mario Limonciello <[email protected]>; Pali Rohár
>> <[email protected]>; Armin Wolf <[email protected]>;
>> [email protected]; Ilpo Järvinen
>> <[email protected]>; kernel test robot <[email protected]>; Hans de
>> Goede <[email protected]>; Matthew Garrett <[email protected]>;
>> Jonathan Corbet <[email protected]>; Heiner Kallweit
>> <[email protected]>; Vegard Nossum <[email protected]>;
>> [email protected]; LKML <[email protected]>;
>> Dell Client Kernel <[email protected]>
>> Subject: Re: [PATCH v5] platform/x86: dell-laptop: Implement platform_profile
>>
>>
>> [EXTERNAL EMAIL]
>>
>>
>>
>> On Thu, May 9 2024 at 09:10:51 AM -06:00:00, Lyndon Sanche
>> <[email protected]> wrote:
>> > On Wed, May 8, 2024, at 8:24 AM, Shen, Yijun wrote:
>> >> Hi Lyndon,
>> >>
>> >> Thanks for working on this patch.
>> >>
>> >>
>> >> Dell side has an initial testing with this patch on some laptops,
>> >> it looks good. While changing the platform profile:
>> >> 1. The corresponding USTT option in BIOS will be changed.
>> >> 2. thermald will not be impacted. The related PSVT and ITMT will be
>> >> loaded.
>> >> Some Dell DTs does not have the USTT, Dell'll have a check if
>> >> nothing is broken.
>> >>
>> >> Additional, with this patch, follow behavior is found:
>> >> 1. For example, the platform profile is quiet.
>> >> 2. Reboot the system and change the USTT to performance.
>> >> 3. Boot to desktop, the platform profile is "quiet", the USTT will
>> >> be changed back to "quiet".
>> >> This looks like not a proper user experience. The platform profile
>> >> should honor the BIOS setting, aka, the platform profile should be
>> >> switched to "performance".
>> >
>> > Hello:
>> >
>> > Thank you for your email. This is definitely undesirable behaviour, I
>> > will have a look at the code to see why this is happening. Does it
>> > always revert to quiet on boot, or always the mode that you had
>> > switched to prior to reboot?
>> >
>> > Do you happen to have power-profiles-daemon or something similar
>> > running? My understanding is it remembers profiles across reboots,
>> > this could potentially also revert the profile back to what it was.
>> > See this release for details:
>> > https://urldefense.com/v3/__https://gitlab.freedesktop.org/upower/powe
>> > r-profiles-daemon/-/releases/0.9.0__;!!LpKI!jUAEHb-9foumkcmPlEKD6tnQrZ
>> > sqjB1sXdPDsYvH2fJ-gPV6G35MUtDW4q3xhlJ4IeLcIgmVpb3ztXqaOg8$
>> > [gitlab[.]freedesktop[.]org]
>> >
>> > I will assume there is a bug in my code at this point. I will test
>> > with and without ppd running on my system to see if it changes across
>> > reboots.
>> >
>> > Are USTT settings exposed in your BIOS configuration menu? On my
>> > laptop they are not and I have to use smbios-thermal-ctl.
>> >
>> > Thank you,
>> >
>> > Lyndon
>>
>> Hi Yijun:
>>
>> I tested this on my computer (XPS 9560). I do not have access to the USTT
>> settings in the BIOS screen so to substitute that, I booted without the patch
>> and set the USTT manually using smbios-thermal-ctl.
>> Here are my findings:
>>
>> Scenario #1: Without power-profiles-daemon (ppd) running
>>
>> 1. Boot with patch, set platform_profile to quiet 2. Boot without patch applied
>> (no platform_profile)
>> - smbios-thermal-ctl confirms USTT is set to quiet
>> - use smbios-thermal-ctl to set USTT to performance
>> - confirm set to performance
>> 3. Boot with patch again
>> - platform_profile is set to performance
>>
>> Scenario #2: With ppd running
>> 1. Boot with patch, set platform_profile to performance with ppd
>> - Confirm platform_profile is performance 2. Boot without patch applied (no
>> platform_profile)
>> - smbios-thermal-ctl confirms USTT is set to performance
>> - ppd reverts to balanced (only controlling intel_pstate in this case)
>> - use smbios-thermal-ctl to set USTT to quiet
>> - confirm set to quiet
>> 3. Boot with patch again
>> - platform_profile and ppd is set to performance
>>
>> In my case, the setting in the smbios is honored if it was switched with
>> another method. When using a userspace program that manipulates the
>> platform_profile, the program seems to remember the previous state and
>> switch to that.
>>
>> So I do not think there is a bug in this patch related to this issue, at least in my
>> case. Please let me know if you have any questions.
>>
>> Thanks,
>>
>> Lyndon
>>
>>
>>
>Hi Lyndon,
>
> I've made a video recorder of the issue: https://dell.box.com/s/3f3znz1z8c6htbcll9juj6tyyu0zvvut
> My test environment is that I freshly installed the Fedora 40 and will not do any online updates. Then install the kernel with the v5 patch applied.
>
> XPS 9560 is a pretty old system which is RTS with 2017. No USTT setting in the BIOS is expected.
> I've a check that the Dell system, at least shipped from 2022, the USTT setting will be valid in the BIOS. The system used in above link, it is Latitude 7350 which is shipped by 2024 April.
>
> I think the key point to duplicate of this issue that, the USTT needs to be changed under BIOS but not under the Linux OS.
>
>Thanks
>
>


Thanks for the video.

Fedora 40 has power-profiles-daemon enabled by default AFAIK. This would be changing the platform profile at load to match the last known state.

Are you able to rerun this test with PPD disabled? Just in case it is a difference between setting it in BIOS and smbios-thermal-ctl.

Thanks,

Lyndon

2024-05-11 15:57:30

by Shen, Yijun

[permalink] [raw]
Subject: RE: [PATCH v5] platform/x86: dell-laptop: Implement platform_profile


Internal Use - Confidential
+AD4- -----Original Message-----
+AD4- From: Limonciello, Mario +ADw-mario.limonciello+AEA-amd.com+AD4-
+AD4- Sent: Saturday, May 11, 2024 11:13 PM
+AD4- To: Shen, Yijun +ADw-Yijun+AF8-Shen+AEA-Dell.com+AD4AOw- Lyndon Sanche
+AD4- +ADw-lsanche+AEA-lyndeno.ca+AD4-
+AD4- Cc: pali+AEA-kernel.org+ADs- W+AF8-Armin+AEA-gmx.de+ADs-
+AD4- srinivas.pandruvada+AEA-linux.intel.com+ADs- ilpo.jarvinen+AEA-linux.intel.com+ADs-
+AD4- lkp+AEA-intel.com+ADs- Hans de Goede +ADw-hdegoede+AEA-redhat.com+AD4AOw- Matthew Garrett
+AD4- +ADw-mjg59+AEA-srcf.ucam.org+AD4AOw- Jonathan Corbet +ADw-corbet+AEA-lwn.net+AD4AOw- Heiner Kallweit
+AD4- +ADw-hkallweit1+AEA-gmail.com+AD4AOw- Vegard Nossum +ADw-vegard.nossum+AEA-oracle.com+AD4AOw-
+AD4- platform-driver-x86+AEA-vger.kernel.org+ADs- linux-kernel+AEA-vger.kernel.org+ADs- Dell Client
+AD4- Kernel +ADw-Dell.Client.Kernel+AEA-dell.com+AD4-
+AD4- Subject: Re: +AFs-PATCH v5+AF0- platform/x86: dell-laptop: Implement platform+AF8-profile
+AD4-
+AD4-
+AD4- +AFs-EXTERNAL EMAIL+AF0-
+AD4-
+AD4-
+AD4-
+AD4- On 5/11/2024 10:05 AM, Shen, Yijun wrote:
+AD4- +AD4-
+AD4- +AD4- Internal Use - Confidential
+AD4- +AD4APg- -----Original Message-----
+AD4- +AD4APg- From: Mario Limonciello +ADw-mario.limonciello+AEA-amd.com+AD4-
+AD4- +AD4APg- Sent: Wednesday, May 8, 2024 11:53 PM
+AD4- +AD4APg- To: Shen, Yijun +ADw-Yijun+AF8-Shen+AEA-Dell.com+AD4AOw- Lyndon Sanche
+AD4- +AD4APg- +ADw-lsanche+AEA-lyndeno.ca+AD4-
+AD4- +AD4APg- Cc: pali+AEA-kernel.org+ADs- W+AF8-Armin+AEA-gmx.de+ADs-
+AD4- +AD4APg- srinivas.pandruvada+AEA-linux.intel.com+ADs- ilpo.jarvinen+AEA-linux.intel.com+ADs-
+AD4- +AD4APg- lkp+AEA-intel.com+ADs- Hans de Goede +ADw-hdegoede+AEA-redhat.com+AD4AOw- Matthew
+AD4- Garrett
+AD4- +AD4APg- +ADw-mjg59+AEA-srcf.ucam.org+AD4AOw- Jonathan Corbet +ADw-corbet+AEA-lwn.net+AD4AOw- Heiner
+AD4- +AD4APg- Kallweit +ADw-hkallweit1+AEA-gmail.com+AD4AOw- Vegard Nossum
+AD4- +AD4APg- +ADw-vegard.nossum+AEA-oracle.com+AD4AOw- platform-driver-x86+AEA-vger.kernel.org+ADs-
+AD4- +AD4APg- linux-kernel+AEA-vger.kernel.org+ADs- Dell Client Kernel
+AD4- +AD4APg- +ADw-Dell.Client.Kernel+AEA-dell.com+AD4-
+AD4- +AD4APg- Subject: Re: RE: +AFs-PATCH v5+AF0- platform/x86: dell-laptop: Implement
+AD4- +AD4APg- platform+AF8-profile
+AD4- +AD4APg-
+AD4- +AD4APg-
+AD4- +AD4APg- +AFs-EXTERNAL EMAIL+AF0-
+AD4- +AD4APg-
+AD4- +AD4APg- On 5/8/2024 09:24, Shen, Yijun wrote:
+AD4- +AD4APgA+- Hi Lyndon,
+AD4- +AD4APgA+-
+AD4- +AD4APgA+- Thanks for working on this patch.
+AD4- +AD4APgA+-
+AD4- +AD4APgA+AD4-
+AD4- +AD4APgA+- Dell side has an initial testing with this patch on some laptops,
+AD4- +AD4APgA+- it looks
+AD4- +AD4APg- good. While changing the platform profile:
+AD4- +AD4APgA+- 1. The corresponding USTT option in BIOS will be changed.
+AD4- +AD4APgA+- 2. thermald will not be impacted. The related PSVT and ITMT will be
+AD4- loaded.
+AD4- +AD4APgA+- Some Dell DTs does not have the USTT, Dell'll have a check if
+AD4- +AD4APgA+- nothing is
+AD4- +AD4APg- broken.
+AD4- +AD4APg-
+AD4- +AD4APg- Hi Alex+ACE-
+AD4- +AD4APg-
+AD4- +AD4APg- Have you had a check both on both your AMD laptops and workstations
+AD4- +AD4APg- too, or just the Intel ones? I think it would be good to make sure
+AD4- +AD4APg- it's getting the correct experience in both cases.
+AD4- +AD4APg-
+AD4- +AD4- Hi Mario,
+AD4- +AD4-
+AD4- +AD4- I've a check for this, for both laptop and workstation, the dell+AF8-laptop
+AD4- module will not be loaded. So, AMD platform will not be impacted by this
+AD4- patch series.
+AD4- +AD4- Follow is one example output with workstation.
+AD4- +AD4- +ACM-lsmod +AHw- grep dell
+AD4- +AD4- dell+AF8-wmi 28672 0
+AD4- +AD4- dell+AF8-smbios 32768 1 dell+AF8-wmi
+AD4- +AD4- dcdbas 20480 1 dell+AF8-smbios
+AD4- +AD4- dell+AF8-wmi+AF8-descriptor 20480 2 dell+AF8-wmi,dell+AF8-smbios
+AD4- +AD4- sparse+AF8-keymap 12288 1 dell+AF8-wmi
+AD4- +AD4- ledtrig+AF8-audio 12288 3 snd+AF8-ctl+AF8-led,snd+AF8-hda+AF8-codec+AF8-generic,dell+AF8-wmi
+AD4- +AD4- video 73728 2 dell+AF8-wmi,nvidia+AF8-modeset
+AD4- +AD4- wmi 40960 5
+AD4- video,dell+AF8-wmi,wmi+AF8-bmof,dell+AF8-smbios,dell+AF8-wmi+AF8-descriptor
+AD4- +AD4-
+AD4-
+AD4- Ah+ADs- right that makes sense. In that case, is dell-laptop even the right place for
+AD4- this patch series? I would think the same policies for the platform profile
+AD4- should be able to apply to desktop/workstation.
+AD4-
+AD4- The v6 of this series would block smbios-thermal-ctl from working on a
+AD4- workstation too.
+AD4-
+AD4- +AD4APgA+-
+AD4- +AD4APgA+- Additional, with this patch, follow behavior is found:
+AD4- +AD4APgA+- 1. For example, the platform profile is quiet.
+AD4- +AD4APgA+- 2. Reboot the system and change the USTT to performance.
+AD4- +AD4APgA+- 3. Boot to desktop, the platform profile is +ACI-quiet+ACI-, the USTT
+AD4- +AD4APgA+- will be
+AD4- +AD4APg- changed back to +ACI-quiet+ACI-.
+AD4- +AD4APgA+- This looks like not a proper user experience. The platform
+AD4- +AD4APgA+- profile should
+AD4- +AD4APg- honor the BIOS setting, aka, the platform profile should be switched
+AD4- +AD4APg- to +ACI-performance+ACI-.
+AD4- +AD4APgA+-
+AD4- +AD4APg-
+AD4- +AD4APg- I agree, this sounds like the initial profile needs to be read from
+AD4- +AD4APg- the BIOS settings too.
+AD4- +AD4APg-
+AD4- +AD4APg- Furthermore I wanted to ask is there also a WMI setting that
+AD4- +AD4APg- corresponds to this that dell-wmi-sysman offers?
+AD4- +AD4- Yes, Mario, you're right. This thermal setting could also be toggled by dell-
+AD4- wmi-sysman.
+AD4- +AD4- But, for the Dell consumer AMD laptops, like Alienware, the BIOS is another
+AD4- variant which is different with the workstation one.
+AD4- +AD4- With this variant BIOS, there is no USTT and also no dell+AF8-wmi/dell-wmi-
+AD4- sysman.
+AD4- +AD4-
+AD4- +AD4APg- I'm wondering if both should be probed in case the SMBIOS one goes
+AD4- away one day.
+AD4- +AD4- Yep, I think this is a good suggestion.
+AD4- +AD4-
+AD4-
+AD4- Great+ACE- Although something I wonder is if the policy when changed with dell-
+AD4- wmi-sysman is immediate or requires a reboot. A lot of the settings in there
+AD4- aren't effective until after a reboot.
+AD4-
+AD4- If this is one of them then it might not be a good idea to make it work for
+AD4- both.

Hi Mario,

Just have a check, the check steps are:
1. stop the thermald
2. run the stress test
3. Toggle the thermal setting between UltraPerformance and Quiet via dell-wmi-sysman
4. Check the CPU FAN speed
The system reboot is not needed, the CPU fan speed changes immediately.
A screen recorder here: https://dell.box.com/s/p2bhd2b6cv8z5buk9eao3bosgrrp1lf9

Thanks


2024-05-11 15:59:32

by Lyndon Sanche

[permalink] [raw]
Subject: Re: [PATCH v6 2/2] platform/x86: dell-laptop: Implement platform_profile



On May 11, 2024 9:16:56 a.m. MDT, "Limonciello, Mario" <[email protected]> wrote:
>
>
>On 5/10/2024 9:36 PM, Lyndon Sanche wrote:
>> Some Dell laptops support configuration of preset fan modes through
>> smbios tables.
>>
>> If the platform supports these fan modes, set up platform_profile to
>> change these modes. If not supported, skip enabling platform_profile.
>>
>> Signed-off-by: Lyndon Sanche <[email protected]>
>> ---
>> drivers/platform/x86/dell/Kconfig | 2 +
>> drivers/platform/x86/dell/dell-laptop.c | 242 +++++++++++++++++++
>> drivers/platform/x86/dell/dell-smbios-base.c | 1 +
>> drivers/platform/x86/dell/dell-smbios.h | 1 +
>> 4 files changed, 246 insertions(+)
>>
>> diff --git a/drivers/platform/x86/dell/Kconfig b/drivers/platform/x86/dell/Kconfig
>> index bd9f445974cc..26679f22733c 100644
>> --- a/drivers/platform/x86/dell/Kconfig
>> +++ b/drivers/platform/x86/dell/Kconfig
>> @@ -47,6 +47,7 @@ config DCDBAS
>> config DELL_LAPTOP
>> tristate "Dell Laptop Extras"
>> default m
>> + depends on ACPI
>> depends on DMI
>> depends on BACKLIGHT_CLASS_DEVICE
>> depends on ACPI_VIDEO || ACPI_VIDEO = n
>> @@ -57,6 +58,7 @@ config DELL_LAPTOP
>> select POWER_SUPPLY
>> select LEDS_CLASS
>> select NEW_LEDS
>> + select ACPI_PLATFORM_PROFILE
>> help
>> This driver adds support for rfkill and backlight control to Dell
>> laptops (except for some models covered by the Compal driver).
>> diff --git a/drivers/platform/x86/dell/dell-laptop.c b/drivers/platform/x86/dell/dell-laptop.c
>> index 42f7de2b4522..07f54f1cbac5 100644
>> --- a/drivers/platform/x86/dell/dell-laptop.c
>> +++ b/drivers/platform/x86/dell/dell-laptop.c
>> @@ -27,6 +27,9 @@
>> #include <linux/i8042.h>
>> #include <linux/debugfs.h>
>> #include <linux/seq_file.h>
>> +#include <linux/bitfield.h>
>> +#include <linux/bits.h>
>> +#include <linux/platform_profile.h>
>> #include <acpi/video.h>
>> #include "dell-rbtn.h"
>> #include "dell-smbios.h"
>> @@ -95,6 +98,7 @@ static struct backlight_device *dell_backlight_device;
>> static struct rfkill *wifi_rfkill;
>> static struct rfkill *bluetooth_rfkill;
>> static struct rfkill *wwan_rfkill;
>> +static struct platform_profile_handler *thermal_handler;
>> static bool force_rfkill;
>> static bool micmute_led_registered;
>> static bool mute_led_registered;
>> @@ -2199,6 +2203,236 @@ static int mute_led_set(struct led_classdev *led_cdev,
>> return 0;
>> }
>> +/* Derived from smbios-thermal-ctl
>> + *
>> + * cbClass 17
>> + * cbSelect 19
>> + * User Selectable Thermal Tables(USTT)
>> + * cbArg1 determines the function to be performed
>> + * cbArg1 0x0 = Get Thermal Information
>> + * cbRES1 Standard return codes (0, -1, -2)
>> + * cbRES2, byte 0 Bitmap of supported thermal modes. A mode is supported if
>> + * its bit is set to 1
>> + * Bit 0 Balanced
>> + * Bit 1 Cool Bottom
>> + * Bit 2 Quiet
>> + * Bit 3 Performance
>> + * cbRES2, byte 1 Bitmap of supported Active Acoustic Controller (AAC) modes.
>> + * Each mode corresponds to the supported thermal modes in
>> + * byte 0. A mode is supported if its bit is set to 1.
>> + * Bit 0 AAC (Balanced)
>> + * Bit 1 AAC (Cool Bottom
>> + * Bit 2 AAC (Quiet)
>> + * Bit 3 AAC (Performance)
>> + * cbRes3, byte 0 Current Thermal Mode
>> + * Bit 0 Balanced
>> + * Bit 1 Cool Bottom
>> + * Bit 2 Quiet
>> + * Bit 3 Performanc
>> + * cbRes3, byte 1 AAC Configuration type
>> + * 0 Global (AAC enable/disable applies to all supported USTT modes)
>> + * 1 USTT mode specific
>> + * cbRes3, byte 2 Current Active Acoustic Controller (AAC) Mode
>> + * If AAC Configuration Type is Global,
>> + * 0 AAC mode disabled
>> + * 1 AAC mode enabled
>> + * If AAC Configuration Type is USTT mode specific (multiple bits may be set),
>> + * Bit 0 AAC (Balanced)
>> + * Bit 1 AAC (Cool Bottom
>> + * Bit 2 AAC (Quiet)
>> + * Bit 3 AAC (Performance)
>> + * cbRes3, byte 3 Current Fan Failure Mode
>> + * Bit 0 Minimal Fan Failure (at least one fan has failed, one fan working)
>> + * Bit 1 Catastrophic Fan Failure (all fans have failed)
>> + *
>> + * cbArg1 0x1 (Set Thermal Information), both desired thermal mode and
>> + * desired AAC mode shall be applied
>> + * cbArg2, byte 0 Desired Thermal Mode to set
>> + * (only one bit may be set for this parameter)
>> + * Bit 0 Balanced
>> + * Bit 1 Cool Bottom
>> + * Bit 2 Quiet
>> + * Bit 3 Performance
>> + * cbArg2, byte 1 Desired Active Acoustic Controller (AAC) Mode to set
>> + * If AAC Configuration Type is Global,
>> + * 0 AAC mode disabled
>> + * 1 AAC mode enabled
>> + * If AAC Configuration Type is USTT mode specific
>> + * (multiple bits may be set for this parameter),
>> + * Bit 0 AAC (Balanced)
>> + * Bit 1 AAC (Cool Bottom
>> + * Bit 2 AAC (Quiet)
>> + * Bit 3 AAC (Performance)
>> + */
>> +
>> +#define DELL_ACC_GET_FIELD GENMASK(19, 16)
>> +#define DELL_ACC_SET_FIELD GENMASK(11, 8)
>> +#define DELL_THERMAL_SUPPORTED GENMASK(3, 0)
>> +
>> +enum thermal_mode_bits {
>> + DELL_BALANCED = BIT(0),
>> + DELL_COOL_BOTTOM = BIT(1),
>> + DELL_QUIET = BIT(2),
>> + DELL_PERFORMANCE = BIT(3),
>> +};
>> +
>> +static int thermal_get_mode(void)
>> +{
>> + struct calling_interface_buffer buffer;
>> + int state;
>> + int ret;
>> +
>> + dell_fill_request(&buffer, 0x0, 0, 0, 0);
>> + ret = dell_send_request(&buffer, CLASS_INFO, SELECT_THERMAL_MANAGEMENT);
>> + if (ret)
>> + return ret;
>> + state = buffer.output[2];
>> + if (state & DELL_BALANCED)
>> + return DELL_BALANCED;
>> + else if (state & DELL_COOL_BOTTOM)
>> + return DELL_COOL_BOTTOM;
>> + else if (state & DELL_QUIET)
>> + return DELL_QUIET;
>> + else if (state & DELL_PERFORMANCE)
>> + return DELL_PERFORMANCE;
>> + else
>> + return -ENXIO;
>> +}
>> +
>> +static int thermal_get_supported_modes(int *supported_bits)
>> +{
>> + struct calling_interface_buffer buffer;
>> + int ret;
>> +
>> + dell_fill_request(&buffer, 0x0, 0, 0, 0);
>> + ret = dell_send_request(&buffer, CLASS_INFO, SELECT_THERMAL_MANAGEMENT);
>> + if (ret)
>> + return ret;
>> + *supported_bits = FIELD_GET(DELL_THERMAL_SUPPORTED, buffer.output[1]);
>> + return 0;
>> +}
>> +
>> +static int thermal_get_acc_mode(int *acc_mode)
>> +{
>> + struct calling_interface_buffer buffer;
>> + int ret;
>> +
>> + dell_fill_request(&buffer, 0x0, 0, 0, 0);
>> + ret = dell_send_request(&buffer, CLASS_INFO, SELECT_THERMAL_MANAGEMENT);
>> + if (ret)
>> + return ret;
>> + *acc_mode = FIELD_GET(DELL_ACC_GET_FIELD, buffer.output[3]);
>> + return 0;
>> +}
>> +
>> +static int thermal_set_mode(enum thermal_mode_bits state)
>> +{
>> + struct calling_interface_buffer buffer;
>> + int ret;
>> + int acc_mode;
>> +
>> + ret = thermal_get_acc_mode(&acc_mode);
>> + if (ret)
>> + return ret;
>> +
>> + dell_fill_request(&buffer, 0x1, FIELD_PREP(DELL_ACC_SET_FIELD, acc_mode) | state, 0, 0);
>> + ret = dell_send_request(&buffer, CLASS_INFO, SELECT_THERMAL_MANAGEMENT);
>> + return ret;
>> +}
>> +
>> +static int thermal_platform_profile_set(struct platform_profile_handler *pprof,
>> + enum platform_profile_option profile)
>> +{
>> + switch (profile) {
>> + case PLATFORM_PROFILE_BALANCED:
>> + return thermal_set_mode(DELL_BALANCED);
>> + case PLATFORM_PROFILE_PERFORMANCE:
>> + return thermal_set_mode(DELL_PERFORMANCE);
>> + case PLATFORM_PROFILE_QUIET:
>> + return thermal_set_mode(DELL_QUIET);
>> + case PLATFORM_PROFILE_COOL:
>> + return thermal_set_mode(DELL_COOL_BOTTOM);
>> + default:
>> + return -EOPNOTSUPP;
>> + }
>> +}
>> +
>> +static int thermal_platform_profile_get(struct platform_profile_handler *pprof,
>> + enum platform_profile_option *profile)
>> +{
>> + int ret;
>> +
>> + ret = thermal_get_mode();
>> + if (ret < 0)
>> + return ret;
>> +
>> + switch (ret) {
>> + case DELL_BALANCED:
>> + *profile = PLATFORM_PROFILE_BALANCED;
>> + break;
>> + case DELL_PERFORMANCE:
>> + *profile = PLATFORM_PROFILE_PERFORMANCE;
>> + break;
>> + case DELL_COOL_BOTTOM:
>> + *profile = PLATFORM_PROFILE_COOL;
>> + break;
>> + case DELL_QUIET:
>> + *profile = PLATFORM_PROFILE_QUIET;
>> + break;
>> + default:
>> + return -EINVAL;
>> + }
>> +
>> + return 0;
>> +}
>> +
>> +static int thermal_init(void)
>> +{
>> + int ret;
>> + int supported_modes;
>> +
>> + /* If thermal commands not supported, exit without error */
>> + if (!dell_laptop_check_supported_cmds(CLASS_INFO))
>> + return 0;
>> +
>> + /* If thermal modes not supported, exit without error */
>> + ret = thermal_get_supported_modes(&supported_modes);
>> + if (ret < 0)
>> + return ret;
>> + if (!supported_modes)
>> + return 0;
>> +
>> + thermal_handler = kzalloc(sizeof(*thermal_handler), GFP_KERNEL);
>> + if (!thermal_handler)
>> + return -ENOMEM;
>> + thermal_handler->profile_get = thermal_platform_profile_get;
>> + thermal_handler->profile_set = thermal_platform_profile_set;
>> +
>> + if (supported_modes & DELL_QUIET)
>> + set_bit(PLATFORM_PROFILE_QUIET, thermal_handler->choices);
>> + if (supported_modes & DELL_COOL_BOTTOM)
>> + set_bit(PLATFORM_PROFILE_COOL, thermal_handler->choices);
>> + if (supported_modes & DELL_BALANCED)
>> + set_bit(PLATFORM_PROFILE_BALANCED, thermal_handler->choices);
>> + if (supported_modes & DELL_PERFORMANCE)
>> + set_bit(PLATFORM_PROFILE_PERFORMANCE, thermal_handler->choices);
>> +
>> + /* Clean up if failed */
>> + ret = platform_profile_register(thermal_handler);
>> + if (ret)
>> + kfree(thermal_handler);
>> +
>> + return ret;
>> +}
>> +
>> +static void thermal_cleanup(void)
>> +{
>> + if (thermal_handler) {
>> + platform_profile_remove();
>> + kfree(thermal_handler);
>> + }
>> +}
>> +
>> static struct led_classdev mute_led_cdev = {
>> .name = "platform::mute",
>> .max_brightness = 1,
>> @@ -2238,6 +2472,11 @@ static int __init dell_init(void)
>> goto fail_rfkill;
>> }
>> + /* Do not fail module if thermal modes not supported, just skip */
>> + ret = thermal_init();
>> + if (ret)
>> + goto fail_thermal;
>> +
>> if (quirks && quirks->touchpad_led)
>> touchpad_led_init(&platform_device->dev);
>> @@ -2317,6 +2556,8 @@ static int __init dell_init(void)
>> led_classdev_unregister(&mute_led_cdev);
>> fail_led:
>> dell_cleanup_rfkill();
>> +fail_thermal:
>> + thermal_cleanup();
>> fail_rfkill:
>> platform_device_del(platform_device);
>> fail_platform_device2:
>> @@ -2344,6 +2585,7 @@ static void __exit dell_exit(void)
>> platform_device_unregister(platform_device);
>> platform_driver_unregister(&platform_driver);
>> }
>> + thermal_cleanup();
>> }
>> /* dell-rbtn.c driver export functions which will not work correctly (and could
>> diff --git a/drivers/platform/x86/dell/dell-smbios-base.c b/drivers/platform/x86/dell/dell-smbios-base.c
>> index 6ae09d7f76fb..387fa5618f7a 100644
>> --- a/drivers/platform/x86/dell/dell-smbios-base.c
>> +++ b/drivers/platform/x86/dell/dell-smbios-base.c
>> @@ -71,6 +71,7 @@ static struct smbios_call call_blacklist[] = {
>> /* handled by kernel: dell-laptop */
>> {0x0000, CLASS_INFO, SELECT_RFKILL},
>> {0x0000, CLASS_KBD_BACKLIGHT, SELECT_KBD_BACKLIGHT},
>> + {0x0000, CLASS_INFO, SELECT_THERMAL_MANAGEMENT},
>> };
>
>So when Alex checked on v5 that this doesn't load on workstations, it has made me realize that doing this will block the interface totally even on workstations.
>
>So I think there are a few ways to go to handle this:
>
>1) Rename dell-laptop to dell-client or dell-pc and let dell-laptop load on more form factors. This would require some internal handling in the module for which features make sense for different form factors.
>
>2) Add a new module just for the thermal handling and put all this code into it instead.
>
>I don't have a strong opinion, but I do think one of them should be done to ensure there aren't problems on workstations losing access to thermal control.
>

A dell-client/laptop separation makes more sense IMO. I don't think keyboard control would belong in a the dell-client module either. Separating just thermal control would be easier, but not as clean I think.

Thanks,

Lyndon

2024-05-11 16:02:45

by Lyndon Sanche

[permalink] [raw]
Subject: RE: RE: [PATCH v5] platform/x86: dell-laptop: Implement platform_profile



On May 11, 2024 9:05:15 a.m. MDT, "Shen, Yijun" <[email protected]> wrote:
>
>Internal Use - Confidential
>> -----Original Message-----
>> From: Mario Limonciello <[email protected]>
>> Sent: Wednesday, May 8, 2024 11:53 PM
>> To: Shen, Yijun <[email protected]>; Lyndon Sanche
>> <[email protected]>
>> Cc: [email protected]; [email protected];
>> [email protected]; [email protected];
>> [email protected]; Hans de Goede <[email protected]>; Matthew Garrett
>> <[email protected]>; Jonathan Corbet <[email protected]>; Heiner Kallweit
>> <[email protected]>; Vegard Nossum <[email protected]>;
>> [email protected]; [email protected]; Dell Client
>> Kernel <[email protected]>
>> Subject: Re: RE: [PATCH v5] platform/x86: dell-laptop: Implement
>> platform_profile
>>
>>
>> [EXTERNAL EMAIL]
>>
>> On 5/8/2024 09:24, Shen, Yijun wrote:
>> > Hi Lyndon,
>> >
>> > Thanks for working on this patch.
>> >
>> >>
>> > Dell side has an initial testing with this patch on some laptops, it looks
>> good. While changing the platform profile:
>> > 1. The corresponding USTT option in BIOS will be changed.
>> > 2. thermald will not be impacted. The related PSVT and ITMT will be loaded.
>> > Some Dell DTs does not have the USTT, Dell'll have a check if nothing is
>> broken.
>>
>> Hi Alex!
>>
>> Have you had a check both on both your AMD laptops and workstations too,
>> or just the Intel ones? I think it would be good to make sure it's getting the
>> correct experience in both cases.
>>
>Hi Mario,
>
> I've a check for this, for both laptop and workstation, the dell_laptop module will not be loaded. So, AMD platform will not be impacted by this patch series.
>Follow is one example output with workstation.
> #lsmod | grep dell
> dell_wmi 28672 0
> dell_smbios 32768 1 dell_wmi
> dcdbas 20480 1 dell_smbios
> dell_wmi_descriptor 20480 2 dell_wmi,dell_smbios
> sparse_keymap 12288 1 dell_wmi
> ledtrig_audio 12288 3 snd_ctl_led,snd_hda_codec_generic,dell_wmi
> video 73728 2 dell_wmi,nvidia_modeset
> wmi 40960 5 video,dell_wmi,wmi_bmof,dell_smbios,dell_wmi_descriptor
>

Should AMD platforms be affected? Do they support the USTT modes as well?

2024-05-11 16:13:36

by Shen, Yijun

[permalink] [raw]
Subject: RE: [PATCH v5] platform/x86: dell-laptop: Implement platform_profile


Internal Use - Confidential
+AD4- -----Original Message-----
+AD4- From: Lyndon Sanche +ADw-lsanche+AEA-lyndeno.ca+AD4-
+AD4- Sent: Saturday, May 11, 2024 11:54 PM
+AD4- To: Shen, Yijun +ADw-Yijun+AF8-Shen+AEA-Dell.com+AD4-
+AD4- Cc: Mario Limonciello +ADw-mario.limonciello+AEA-amd.com+AD4AOw- Pali Roh+AOE-r
+AD4- +ADw-pali+AEA-kernel.org+AD4AOw- Armin Wolf +ADw-W+AF8-Armin+AEA-gmx.de+AD4AOw-
+AD4- srinivas.pandruvada+AEA-linux.intel.com+ADs- Ilpo J+AOQ-rvinen
+AD4- +ADw-ilpo.jarvinen+AEA-linux.intel.com+AD4AOw- kernel test robot +ADw-lkp+AEA-intel.com+AD4AOw- Hans de
+AD4- Goede +ADw-hdegoede+AEA-redhat.com+AD4AOw- Matthew Garrett +ADw-mjg59+AEA-srcf.ucam.org+AD4AOw-
+AD4- Jonathan Corbet +ADw-corbet+AEA-lwn.net+AD4AOw- Heiner Kallweit
+AD4- +ADw-hkallweit1+AEA-gmail.com+AD4AOw- Vegard Nossum +ADw-vegard.nossum+AEA-oracle.com+AD4AOw-
+AD4- platform-driver-x86+AEA-vger.kernel.org+ADs- LKML +ADw-linux-kernel+AEA-vger.kernel.org+AD4AOw-
+AD4- Dell Client Kernel +ADw-Dell.Client.Kernel+AEA-dell.com+AD4-
+AD4- Subject: RE: +AFs-PATCH v5+AF0- platform/x86: dell-laptop: Implement platform+AF8-profile
+AD4-
+AD4-
+AD4- +AFs-EXTERNAL EMAIL+AF0-
+AD4-
+AD4-
+AD4-
+AD4- On May 11, 2024 9:22:23+IC8-a.m. MDT, +ACI-Shen, Yijun+ACI- +ADw-Yijun.Shen+AEA-dell.com+AD4-
+AD4- wrote:
+AD4- +AD4-
+AD4- +AD4-
+AD4- +AD4-
+AD4- +AD4-Internal Use - Confidential
+AD4- +AD4APg- -----Original Message-----
+AD4- +AD4APg- From: Lyndon Sanche +ADw-lsanche+AEA-lyndeno.ca+AD4-
+AD4- +AD4APg- Sent: Saturday, May 11, 2024 9:49 AM
+AD4- +AD4APg- To: Shen, Yijun +ADw-Yijun+AF8-Shen+AEA-Dell.com+AD4-
+AD4- +AD4APg- Cc: Mario Limonciello +ADw-mario.limonciello+AEA-amd.com+AD4AOw- Pali Roh+AOE-r
+AD4- +AD4APg- +ADw-pali+AEA-kernel.org+AD4AOw- Armin Wolf +ADw-W+AF8-Armin+AEA-gmx.de+AD4AOw-
+AD4- +AD4APg- srinivas.pandruvada+AEA-linux.intel.com+ADs- Ilpo J+AOQ-rvinen
+AD4- +AD4APg- +ADw-ilpo.jarvinen+AEA-linux.intel.com+AD4AOw- kernel test robot +ADw-lkp+AEA-intel.com+AD4AOw-
+AD4- +AD4APg- Hans de Goede +ADw-hdegoede+AEA-redhat.com+AD4AOw- Matthew Garrett
+AD4- +AD4APg- +ADw-mjg59+AEA-srcf.ucam.org+AD4AOw- Jonathan Corbet +ADw-corbet+AEA-lwn.net+AD4AOw- Heiner
+AD4- +AD4APg- Kallweit +ADw-hkallweit1+AEA-gmail.com+AD4AOw- Vegard Nossum
+AD4- +AD4APg- +ADw-vegard.nossum+AEA-oracle.com+AD4AOw- platform-driver-x86+AEA-vger.kernel.org+ADs-
+AD4- LKML
+AD4- +AD4APg- +ADw-linux-kernel+AEA-vger.kernel.org+AD4AOw- Dell Client Kernel
+AD4- +AD4APg- +ADw-Dell.Client.Kernel+AEA-dell.com+AD4-
+AD4- +AD4APg- Subject: Re: +AFs-PATCH v5+AF0- platform/x86: dell-laptop: Implement
+AD4- +AD4APg- platform+AF8-profile
+AD4- +AD4APg-
+AD4- +AD4APg-
+AD4- +AD4APg- +AFs-EXTERNAL EMAIL+AF0-
+AD4- +AD4APg-
+AD4- +AD4APg-
+AD4- +AD4APg-
+AD4- +AD4APg- On Thu, May 9 2024 at 09:10:51 AM -06:00:00, Lyndon Sanche
+AD4- +AD4APg- +ADw-lsanche+AEA-lyndeno.ca+AD4- wrote:
+AD4- +AD4APg- +AD4- On Wed, May 8, 2024, at 8:24 AM, Shen, Yijun wrote:
+AD4- +AD4APg- +AD4APg- Hi Lyndon,
+AD4- +AD4APg- +AD4APg-
+AD4- +AD4APg- +AD4APg- Thanks for working on this patch.
+AD4- +AD4APg- +AD4APg-
+AD4- +AD4APg- +AD4APg-
+AD4- +AD4APg- +AD4APg- Dell side has an initial testing with this patch on some
+AD4- +AD4APg- +AD4APg- laptops, it looks good. While changing the platform profile:
+AD4- +AD4APg- +AD4APg- 1. The corresponding USTT option in BIOS will be changed.
+AD4- +AD4APg- +AD4APg- 2. thermald will not be impacted. The related PSVT and ITMT will
+AD4- +AD4APg- +AD4APg- be loaded.
+AD4- +AD4APg- +AD4APg- Some Dell DTs does not have the USTT, Dell'll have a check if
+AD4- +AD4APg- +AD4APg- nothing is broken.
+AD4- +AD4APg- +AD4APg-
+AD4- +AD4APg- +AD4APg- Additional, with this patch, follow behavior is found:
+AD4- +AD4APg- +AD4APg- 1. For example, the platform profile is quiet.
+AD4- +AD4APg- +AD4APg- 2. Reboot the system and change the USTT to performance.
+AD4- +AD4APg- +AD4APg- 3. Boot to desktop, the platform profile is +ACI-quiet+ACI-, the USTT
+AD4- +AD4APg- +AD4APg- will be changed back to +ACI-quiet+ACI-.
+AD4- +AD4APg- +AD4APg- This looks like not a proper user experience. The platform
+AD4- +AD4APg- +AD4APg- profile should honor the BIOS setting, aka, the platform profile
+AD4- +AD4APg- +AD4APg- should be switched to +ACI-performance+ACI-.
+AD4- +AD4APg- +AD4-
+AD4- +AD4APg- +AD4- Hello:
+AD4- +AD4APg- +AD4-
+AD4- +AD4APg- +AD4- Thank you for your email. This is definitely undesirable behaviour,
+AD4- +AD4APg- +AD4- I will have a look at the code to see why this is happening. Does
+AD4- +AD4APg- +AD4- it always revert to quiet on boot, or always the mode that you had
+AD4- +AD4APg- +AD4- switched to prior to reboot?
+AD4- +AD4APg- +AD4-
+AD4- +AD4APg- +AD4- Do you happen to have power-profiles-daemon or something similar
+AD4- +AD4APg- +AD4- running? My understanding is it remembers profiles across reboots,
+AD4- +AD4APg- +AD4- this could potentially also revert the profile back to what it was.
+AD4- +AD4APg- +AD4- See this release for details:
+AD4- +AD4APg- +AD4- https://urldefense.com/v3/+AF8AXw-https://gitlab.freedesktop.org/upower/p
+AD4- +AD4APg- +AD4- owe
+AD4- +AD4APg- +AD4- r-profiles-daemon/-/releases/0.9.0+AF8AXwA7ACEAIQ-LpKI+ACE-jUAEHb-9foumkcmPlEKD6tn
+AD4- +AD4APg- +AD4- QrZ sqjB1sXdPDsYvH2fJ-
+AD4- gPV6G35MUtDW4q3xhlJ4IeLcIgmVpb3ztXqaOg8+ACQ-
+AD4- +AD4APg- +AD4- +AFs-gitlab+AFs-.+AF0-freedesktop+AFs-.+AF0-org+AF0-
+AD4- +AD4APg- +AD4-
+AD4- +AD4APg- +AD4- I will assume there is a bug in my code at this point. I will test
+AD4- +AD4APg- +AD4- with and without ppd running on my system to see if it changes
+AD4- +AD4APg- +AD4- across reboots.
+AD4- +AD4APg- +AD4-
+AD4- +AD4APg- +AD4- Are USTT settings exposed in your BIOS configuration menu? On my
+AD4- +AD4APg- +AD4- laptop they are not and I have to use smbios-thermal-ctl.
+AD4- +AD4APg- +AD4-
+AD4- +AD4APg- +AD4- Thank you,
+AD4- +AD4APg- +AD4-
+AD4- +AD4APg- +AD4- Lyndon
+AD4- +AD4APg-
+AD4- +AD4APg- Hi Yijun:
+AD4- +AD4APg-
+AD4- +AD4APg- I tested this on my computer (XPS 9560). I do not have access to the
+AD4- +AD4APg- USTT settings in the BIOS screen so to substitute that, I booted
+AD4- +AD4APg- without the patch and set the USTT manually using smbios-thermal-ctl.
+AD4- +AD4APg- Here are my findings:
+AD4- +AD4APg-
+AD4- +AD4APg- Scenario +ACM-1: Without power-profiles-daemon (ppd) running
+AD4- +AD4APg-
+AD4- +AD4APg- 1. Boot with patch, set platform+AF8-profile to quiet 2. Boot without
+AD4- +AD4APg- patch applied (no platform+AF8-profile)
+AD4- +AD4APg- - smbios-thermal-ctl confirms USTT is set to quiet
+AD4- +AD4APg- - use smbios-thermal-ctl to set USTT to performance
+AD4- +AD4APg- - confirm set to performance
+AD4- +AD4APg- 3. Boot with patch again
+AD4- +AD4APg- - platform+AF8-profile is set to performance
+AD4- +AD4APg-
+AD4- +AD4APg- Scenario +ACM-2: With ppd running
+AD4- +AD4APg- 1. Boot with patch, set platform+AF8-profile to performance with ppd
+AD4- +AD4APg- - Confirm platform+AF8-profile is performance 2. Boot without patch
+AD4- +AD4APg- applied (no
+AD4- +AD4APg- platform+AF8-profile)
+AD4- +AD4APg- - smbios-thermal-ctl confirms USTT is set to performance
+AD4- +AD4APg- - ppd reverts to balanced (only controlling intel+AF8-pstate in this
+AD4- +AD4APg- case)
+AD4- +AD4APg- - use smbios-thermal-ctl to set USTT to quiet
+AD4- +AD4APg- - confirm set to quiet
+AD4- +AD4APg- 3. Boot with patch again
+AD4- +AD4APg- - platform+AF8-profile and ppd is set to performance
+AD4- +AD4APg-
+AD4- +AD4APg- In my case, the setting in the smbios is honored if it was switched
+AD4- +AD4APg- with another method. When using a userspace program that manipulates
+AD4- +AD4APg- the platform+AF8-profile, the program seems to remember the previous
+AD4- +AD4APg- state and switch to that.
+AD4- +AD4APg-
+AD4- +AD4APg- So I do not think there is a bug in this patch related to this issue,
+AD4- +AD4APg- at least in my case. Please let me know if you have any questions.
+AD4- +AD4APg-
+AD4- +AD4APg- Thanks,
+AD4- +AD4APg-
+AD4- +AD4APg- Lyndon
+AD4- +AD4APg-
+AD4- +AD4APg-
+AD4- +AD4APg-
+AD4- +AD4-Hi Lyndon,
+AD4- +AD4-
+AD4- +AD4- I've made a video recorder of the issue:
+AD4- +AD4-
+AD4- https://urldefense.com/v3/+AF8AXw-https://dell.box.com/s/3f3znz1z8c6htbcll9juj6ty
+AD4- yu0zvvut+AF8AXwA7ACEAIQ-LpKI+ACE-nHHxFbxzG-rJX+AF8-KZsebMC7ZcJU0WhNhkpXn-pk6nu-sUF38-
+AD4- RXz6x3YkALgzS4jnUP9TIWIu4mX+AF8-6cSDbwQ+ACQ- +AFs-dell+AFs-.+AF0-box+AFs-.+AF0-com+AF0- My test
+AD4- environment is that I freshly installed the Fedora 40 and will not do any online
+AD4- updates. Then install the kernel with the v5 patch applied.
+AD4- +AD4-
+AD4- +AD4- XPS 9560 is a pretty old system which is RTS with 2017. No USTT setting in
+AD4- the BIOS is expected.
+AD4- +AD4- I've a check that the Dell system, at least shipped from 2022, the USTT
+AD4- setting will be valid in the BIOS. The system used in above link, it is Latitude
+AD4- 7350 which is shipped by 2024 April.
+AD4- +AD4-
+AD4- +AD4- I think the key point to duplicate of this issue that, the USTT needs to be
+AD4- changed under BIOS but not under the Linux OS.
+AD4- +AD4-
+AD4- +AD4-Thanks
+AD4- +AD4-
+AD4- +AD4-
+AD4-
+AD4-
+AD4- Thanks for the video.
+AD4-
+AD4- Fedora 40 has power-profiles-daemon enabled by default AFAIK. This would
+AD4- be changing the platform profile at load to match the last known state.
+AD4-
+AD4- Are you able to rerun this test with PPD disabled? Just in case it is a difference
+AD4- between setting it in BIOS and smbios-thermal-ctl.
+AD4-
+AD4- Thanks,
+AD4-
+AD4- Lyndon

If disable the PPD, the issue is gone.

Thanks


2024-05-12 00:14:59

by Lyndon Sanche

[permalink] [raw]
Subject: Re: [PATCH v6 2/2] platform/x86: dell-laptop: Implement platform_profile



>>
>> }
>>  /* dell-rbtn.c driver export functions which will not work
>> correctly (and could
>> diff --git a/drivers/platform/x86/dell/dell-smbios-base.c
>> b/drivers/platform/x86/dell/dell-smbios-base.c
>> index 6ae09d7f76fb..387fa5618f7a 100644
>> --- a/drivers/platform/x86/dell/dell-smbios-base.c
>> +++ b/drivers/platform/x86/dell/dell-smbios-base.c
>> @@ -71,6 +71,7 @@ static struct smbios_call call_blacklist[] = {
>> /* handled by kernel: dell-laptop */
>> {0x0000, CLASS_INFO, SELECT_RFKILL},
>> {0x0000, CLASS_KBD_BACKLIGHT, SELECT_KBD_BACKLIGHT},
>> + {0x0000, CLASS_INFO, SELECT_THERMAL_MANAGEMENT},
>> };
>
> So when Alex checked on v5 that this doesn't load on workstations, it
> has made me realize that doing this will block the interface totally
> even on workstations.
>
> So I think there are a few ways to go to handle this:
>
> 1) Rename dell-laptop to dell-client or dell-pc and let dell-laptop
> load on more form factors. This would require some internal handling
> in the module for which features make sense for different form
> factors.
>
> 2) Add a new module just for the thermal handling and put all this
> code into it instead.
>
> I don't have a strong opinion, but I do think one of them should be
> done to ensure there aren't problems on workstations losing access to
> thermal control.

My apologies, I accidentally sent my response in HTML format. Please
see plain-text below:

Thinking about it more, we can leave dell-laptop as-is and create a
common dell-pc module that does not check for specific form-factors,
assuming that is possible. Thermal management can be the first function
to go in there.

We will still block the calls from userspace regardless of which
modules are loaded. If dell-pc fails because thermal management is not
supported, we aren't losing anything by blocking that call anyway.

Thoughts?



2024-05-12 01:44:02

by Mario Limonciello

[permalink] [raw]
Subject: Re: [PATCH v6 2/2] platform/x86: dell-laptop: Implement platform_profile



On 5/11/2024 7:12 PM, Lyndon Sanche wrote:
>
>
> On Sat, May 11 2024 at 09:59:17 AM -06:00:00, Lyndon Sanche
> <[email protected]> wrote:
>> On May 11, 2024 9:16:56 a.m. MDT, "Limonciello, Mario"
>> <[email protected] <mailto:[email protected]>> wrote:
>>
>> On 5/10/2024 9:36 PM, Lyndon Sanche wrote:
>>
>> index 6ae09d7f76fb..387fa5618f7a 100644 ---
>> a/drivers/platform/x86/dell/dell-smbios-base.c +++
>> b/drivers/platform/x86/dell/dell-smbios-base.c @@ -71,6 +71,7
>> @@ static struct smbios_call call_blacklist[] = { /* handled
>> by kernel: dell-laptop */ {0x0000, CLASS_INFO, SELECT_RFKILL},
>> {0x0000, CLASS_KBD_BACKLIGHT, SELECT_KBD_BACKLIGHT}, +
>> {0x0000, CLASS_INFO, SELECT_THERMAL_MANAGEMENT}, };
>>
>> So when Alex checked on v5 that this doesn't load on workstations,
>> it has made me realize that doing this will block the interface
>> totally even on workstations. So I think there are a few ways to
>> go to handle this: 1) Rename dell-laptop to dell-client or dell-pc
>> and let dell-laptop load on more form factors. This would require
>> some internal handling in the module for which features make sense
>> for different form factors. 2) Add a new module just for the
>> thermal handling and put all this code into it instead. I don't
>> have a strong opinion, but I do think one of them should be done
>> to ensure there aren't problems on workstations losing access to
>> thermal control.
>>
>> A dell-client/laptop separation makes more sense IMO. I don't think
>> keyboard control would belong in a the dell-client module either.
>> Separating just thermal control would be easier, but not as clean I
>> think. Thanks, Lyndon
>
> Thinking about it more, we can leave dell-laptop as-is and create a
> common dell-pc module that does not check for specific form-factors,
> assuming that is possible. Thermal management can be the first function
> to go in there.
>
> We will still block the calls from userspace regardless of which modules
> are loaded. If dell-pc fails because thermal management is not
> supported, we aren't losing anything by blocking that call anyway.
>
> Thoughts?

Sounds good by me. So basically laptops will load both dell-pc and
dell-laptop and workstations would load dell-pc.

2024-05-12 15:25:40

by Hans de Goede

[permalink] [raw]
Subject: Re: [PATCH v6 2/2] platform/x86: dell-laptop: Implement platform_profile

Hi,

On 5/12/24 3:43 AM, Limonciello, Mario wrote:
>
>
> On 5/11/2024 7:12 PM, Lyndon Sanche wrote:
>>
>>
>> On Sat, May 11 2024 at 09:59:17 AM -06:00:00, Lyndon Sanche <[email protected]> wrote:
>>> On May 11, 2024 9:16:56 a.m. MDT, "Limonciello, Mario" <[email protected] <mailto:[email protected]>> wrote:
>>>
>>>     On 5/10/2024 9:36 PM, Lyndon Sanche wrote:
>>>
>>>         index 6ae09d7f76fb..387fa5618f7a 100644 ---
>>>         a/drivers/platform/x86/dell/dell-smbios-base.c +++
>>>         b/drivers/platform/x86/dell/dell-smbios-base.c @@ -71,6 +71,7
>>>         @@ static struct smbios_call call_blacklist[] = { /* handled
>>>         by kernel: dell-laptop */ {0x0000, CLASS_INFO, SELECT_RFKILL},
>>>         {0x0000, CLASS_KBD_BACKLIGHT, SELECT_KBD_BACKLIGHT}, +
>>>         {0x0000, CLASS_INFO, SELECT_THERMAL_MANAGEMENT}, };
>>>     So when Alex checked on v5 that this doesn't load on workstations,
>>>     it has made me realize that doing this will block the interface
>>>     totally even on workstations. So I think there are a few ways to
>>>     go to handle this: 1) Rename dell-laptop to dell-client or dell-pc
>>>     and let dell-laptop load on more form factors. This would require
>>>     some internal handling in the module for which features make sense
>>>     for different form factors. 2) Add a new module just for the
>>>     thermal handling and put all this code into it instead. I don't
>>>     have a strong opinion, but I do think one of them should be done
>>>     to ensure there aren't problems on workstations losing access to
>>>     thermal control.
>>> A dell-client/laptop separation makes more sense IMO. I don't think keyboard control would belong in a the dell-client module either. Separating just thermal control would be easier, but not as clean I think. Thanks, Lyndon
>>
>> Thinking about it more, we can leave dell-laptop as-is and create a common dell-pc module that does not check for specific form-factors, assuming that is possible. Thermal management can be the first function to go in there.
>>
>> We will still block the calls from userspace regardless of which modules are loaded. If dell-pc fails because thermal management is not supported, we aren't losing anything by blocking that call anyway.
>>
>> Thoughts?
>
> Sounds good by me.  So basically laptops will load both dell-pc and dell-laptop and workstations would load dell-pc.

Ack this sounds good to me too.

Regards,

Hans




2024-05-12 17:54:20

by Armin Wolf

[permalink] [raw]
Subject: Re: [PATCH v5] platform/x86: dell-laptop: Implement platform_profile

Am 11.05.24 um 17:56 schrieb Shen, Yijun:

> Internal Use - Confidential
>> -----Original Message-----
>> From: Limonciello, Mario <[email protected]>
>> Sent: Saturday, May 11, 2024 11:13 PM
>> To: Shen, Yijun <[email protected]>; Lyndon Sanche
>> <[email protected]>
>> Cc: [email protected]; [email protected];
>> [email protected]; [email protected];
>> [email protected]; Hans de Goede <[email protected]>; Matthew Garrett
>> <[email protected]>; Jonathan Corbet <[email protected]>; Heiner Kallweit
>> <[email protected]>; Vegard Nossum <[email protected]>;
>> [email protected]; [email protected]; Dell Client
>> Kernel <[email protected]>
>> Subject: Re: [PATCH v5] platform/x86: dell-laptop: Implement platform_profile
>>
>>
>> [EXTERNAL EMAIL]
>>
>>
>>
>> On 5/11/2024 10:05 AM, Shen, Yijun wrote:
>>> Internal Use - Confidential
>>>> -----Original Message-----
>>>> From: Mario Limonciello <[email protected]>
>>>> Sent: Wednesday, May 8, 2024 11:53 PM
>>>> To: Shen, Yijun <[email protected]>; Lyndon Sanche
>>>> <[email protected]>
>>>> Cc: [email protected]; [email protected];
>>>> [email protected]; [email protected];
>>>> [email protected]; Hans de Goede <[email protected]>; Matthew
>> Garrett
>>>> <[email protected]>; Jonathan Corbet <[email protected]>; Heiner
>>>> Kallweit <[email protected]>; Vegard Nossum
>>>> <[email protected]>; [email protected];
>>>> [email protected]; Dell Client Kernel
>>>> <[email protected]>
>>>> Subject: Re: RE: [PATCH v5] platform/x86: dell-laptop: Implement
>>>> platform_profile
>>>>
>>>>
>>>> [EXTERNAL EMAIL]
>>>>
>>>> On 5/8/2024 09:24, Shen, Yijun wrote:
>>>>> Hi Lyndon,
>>>>>
>>>>> Thanks for working on this patch.
>>>>>
>>>>> Dell side has an initial testing with this patch on some laptops,
>>>>> it looks
>>>> good. While changing the platform profile:
>>>>> 1. The corresponding USTT option in BIOS will be changed.
>>>>> 2. thermald will not be impacted. The related PSVT and ITMT will be
>> loaded.
>>>>> Some Dell DTs does not have the USTT, Dell'll have a check if
>>>>> nothing is
>>>> broken.
>>>>
>>>> Hi Alex!
>>>>
>>>> Have you had a check both on both your AMD laptops and workstations
>>>> too, or just the Intel ones? I think it would be good to make sure
>>>> it's getting the correct experience in both cases.
>>>>
>>> Hi Mario,
>>>
>>> I've a check for this, for both laptop and workstation, the dell_laptop
>> module will not be loaded. So, AMD platform will not be impacted by this
>> patch series.
>>> Follow is one example output with workstation.
>>> #lsmod | grep dell
>>> dell_wmi 28672 0
>>> dell_smbios 32768 1 dell_wmi
>>> dcdbas 20480 1 dell_smbios
>>> dell_wmi_descriptor 20480 2 dell_wmi,dell_smbios
>>> sparse_keymap 12288 1 dell_wmi
>>> ledtrig_audio 12288 3 snd_ctl_led,snd_hda_codec_generic,dell_wmi
>>> video 73728 2 dell_wmi,nvidia_modeset
>>> wmi 40960 5
>> video,dell_wmi,wmi_bmof,dell_smbios,dell_wmi_descriptor
>> Ah; right that makes sense. In that case, is dell-laptop even the right place for
>> this patch series? I would think the same policies for the platform profile
>> should be able to apply to desktop/workstation.
>>
>> The v6 of this series would block smbios-thermal-ctl from working on a
>> workstation too.
>>
>>>>> Additional, with this patch, follow behavior is found:
>>>>> 1. For example, the platform profile is quiet.
>>>>> 2. Reboot the system and change the USTT to performance.
>>>>> 3. Boot to desktop, the platform profile is "quiet", the USTT
>>>>> will be
>>>> changed back to "quiet".
>>>>> This looks like not a proper user experience. The platform
>>>>> profile should
>>>> honor the BIOS setting, aka, the platform profile should be switched
>>>> to "performance".
>>>> I agree, this sounds like the initial profile needs to be read from
>>>> the BIOS settings too.
>>>>
>>>> Furthermore I wanted to ask is there also a WMI setting that
>>>> corresponds to this that dell-wmi-sysman offers?
>>> Yes, Mario, you're right. This thermal setting could also be toggled by dell-
>> wmi-sysman.
>>> But, for the Dell consumer AMD laptops, like Alienware, the BIOS is another
>> variant which is different with the workstation one.
>>> With this variant BIOS, there is no USTT and also no dell_wmi/dell-wmi-
>> sysman.
>>>> I'm wondering if both should be probed in case the SMBIOS one goes
>> away one day.
>>> Yep, I think this is a good suggestion.
>>>
>> Great! Although something I wonder is if the policy when changed with dell-
>> wmi-sysman is immediate or requires a reboot. A lot of the settings in there
>> aren't effective until after a reboot.
>>
>> If this is one of them then it might not be a good idea to make it work for
>> both.
> Hi Mario,
>
> Just have a check, the check steps are:
> 1. stop the thermald
> 2. run the stress test
> 3. Toggle the thermal setting between UltraPerformance and Quiet via dell-wmi-sysman
> 4. Check the CPU FAN speed
> The system reboot is not needed, the CPU fan speed changes immediately.
> A screen recorder here: https://dell.box.com/s/p2bhd2b6cv8z5buk9eao3bosgrrp1lf9
>
> Thanks
>
Hi,

i believe it should be the responsibility of the manufacturer (in this case Dell) that
the thermal state remains consistent across both interfaces.

I think that the official Windows utility only checks the thermal state reported by
the USTT interface, so we should match this behavior.

Thanks,
Armin Wolf


2024-05-12 17:58:45

by Mario Limonciello

[permalink] [raw]
Subject: Re: [PATCH v5] platform/x86: dell-laptop: Implement platform_profile



On 5/12/2024 12:53 PM, Armin Wolf wrote:
> Am 11.05.24 um 17:56 schrieb Shen, Yijun:
>
>> Internal Use - Confidential
>>> -----Original Message-----
>>> From: Limonciello, Mario <[email protected]>
>>> Sent: Saturday, May 11, 2024 11:13 PM
>>> To: Shen, Yijun <[email protected]>; Lyndon Sanche
>>> <[email protected]>
>>> Cc: [email protected]; [email protected];
>>> [email protected]; [email protected];
>>> [email protected]; Hans de Goede <[email protected]>; Matthew Garrett
>>> <[email protected]>; Jonathan Corbet <[email protected]>; Heiner Kallweit
>>> <[email protected]>; Vegard Nossum <[email protected]>;
>>> [email protected]; [email protected];
>>> Dell Client
>>> Kernel <[email protected]>
>>> Subject: Re: [PATCH v5] platform/x86: dell-laptop: Implement
>>> platform_profile
>>>
>>>
>>> [EXTERNAL EMAIL]
>>>
>>>
>>>
>>> On 5/11/2024 10:05 AM, Shen, Yijun wrote:
>>>> Internal Use - Confidential
>>>>> -----Original Message-----
>>>>> From: Mario Limonciello <[email protected]>
>>>>> Sent: Wednesday, May 8, 2024 11:53 PM
>>>>> To: Shen, Yijun <[email protected]>; Lyndon Sanche
>>>>> <[email protected]>
>>>>> Cc: [email protected]; [email protected];
>>>>> [email protected]; [email protected];
>>>>> [email protected]; Hans de Goede <[email protected]>; Matthew
>>> Garrett
>>>>> <[email protected]>; Jonathan Corbet <[email protected]>; Heiner
>>>>> Kallweit <[email protected]>; Vegard Nossum
>>>>> <[email protected]>; [email protected];
>>>>> [email protected]; Dell Client Kernel
>>>>> <[email protected]>
>>>>> Subject: Re: RE: [PATCH v5] platform/x86: dell-laptop: Implement
>>>>> platform_profile
>>>>>
>>>>>
>>>>> [EXTERNAL EMAIL]
>>>>>
>>>>> On 5/8/2024 09:24, Shen, Yijun wrote:
>>>>>> Hi Lyndon,
>>>>>>
>>>>>>     Thanks for working on this patch.
>>>>>>
>>>>>>     Dell side has an initial testing with this patch on some laptops,
>>>>>> it looks
>>>>> good. While changing the platform profile:
>>>>>> 1. The corresponding USTT option in BIOS will be changed.
>>>>>> 2. thermald will not be impacted. The related PSVT and ITMT will be
>>> loaded.
>>>>>>     Some Dell DTs does not have the USTT, Dell'll have a check if
>>>>>> nothing is
>>>>> broken.
>>>>>
>>>>> Hi Alex!
>>>>>
>>>>> Have you had a check both on both your AMD laptops and workstations
>>>>> too, or just the Intel ones?  I think it would be good to make sure
>>>>> it's getting the correct experience in both cases.
>>>>>
>>>> Hi Mario,
>>>>
>>>>    I've a check for this, for both laptop and workstation, the
>>>> dell_laptop
>>> module will not be loaded. So, AMD platform will not be impacted by this
>>> patch series.
>>>> Follow is one example output with workstation.
>>>>    #lsmod | grep dell
>>>>      dell_wmi               28672  0
>>>>      dell_smbios            32768  1 dell_wmi
>>>>      dcdbas                 20480  1 dell_smbios
>>>>      dell_wmi_descriptor    20480  2 dell_wmi,dell_smbios
>>>>      sparse_keymap          12288  1 dell_wmi
>>>>      ledtrig_audio          12288  3
>>>> snd_ctl_led,snd_hda_codec_generic,dell_wmi
>>>>      video                  73728  2 dell_wmi,nvidia_modeset
>>>>      wmi                    40960  5
>>> video,dell_wmi,wmi_bmof,dell_smbios,dell_wmi_descriptor
>>> Ah; right that makes sense.  In that case, is dell-laptop even the
>>> right place for
>>> this patch series?  I would think the same policies for the platform
>>> profile
>>> should be able to apply to desktop/workstation.
>>>
>>> The v6 of this series would block smbios-thermal-ctl from working on a
>>> workstation too.
>>>
>>>>>>      Additional, with this patch, follow behavior is found:
>>>>>>     1. For example, the platform profile is quiet.
>>>>>>     2. Reboot the system and change the USTT to performance.
>>>>>>     3. Boot to desktop, the platform profile is "quiet", the USTT
>>>>>> will be
>>>>> changed back to "quiet".
>>>>>>     This looks like not a proper user experience. The platform
>>>>>> profile should
>>>>> honor the BIOS setting, aka, the platform profile should be switched
>>>>> to "performance".
>>>>> I agree, this sounds like the initial profile needs to be read from
>>>>> the BIOS settings too.
>>>>>
>>>>> Furthermore I wanted to ask is there also a WMI setting that
>>>>> corresponds to this that dell-wmi-sysman offers?
>>>>    Yes, Mario, you're right. This thermal setting could also be
>>>> toggled by dell-
>>> wmi-sysman.
>>>> But, for the Dell consumer AMD laptops, like Alienware, the BIOS is
>>>> another
>>> variant which is different with the workstation one.
>>>> With this variant BIOS, there is no USTT and also no dell_wmi/dell-wmi-
>>> sysman.
>>>>> I'm wondering if both should be probed in case the SMBIOS one goes
>>> away one day.
>>>>    Yep, I think this is a good suggestion.
>>>>
>>> Great! Although something I wonder is if the policy when changed with
>>> dell-
>>> wmi-sysman is immediate or requires a reboot.  A lot of the settings
>>> in there
>>> aren't effective until after a reboot.
>>>
>>> If this is one of them then it might not be a good idea to make it
>>> work for
>>> both.
>> Hi Mario,
>>
>>   Just have a check, the check steps are:
>> 1. stop the thermald
>> 2. run the stress test
>> 3. Toggle the thermal setting between UltraPerformance and Quiet via
>> dell-wmi-sysman
>> 4. Check the CPU FAN speed
>>   The system reboot is not needed, the CPU fan speed changes immediately.
>>   A screen recorder here:
>> https://dell.box.com/s/p2bhd2b6cv8z5buk9eao3bosgrrp1lf9
>>
>> Thanks
>>
> Hi,
>
> i believe it should be the responsibility of the manufacturer (in this
> case Dell) that
> the thermal state remains consistent across both interfaces.
>
> I think that the official Windows utility only checks the thermal state
> reported by
> the USTT interface, so we should match this behavior.
>
> Thanks,
> Armin Wolf
>

Why? Windows also does ACPI-WMI differently than Linux. It's not as
easy to check both from a Windows utility due to that.

2024-05-12 18:01:16

by Armin Wolf

[permalink] [raw]
Subject: Re: [PATCH v6 1/2] platform/x86: dell-smbios: Add helper for checking supported commands

Am 11.05.24 um 04:36 schrieb Lyndon Sanche:

> Add symbol to check if a specific class of smbios command is supported.
>
> Signed-off-by: Lyndon Sanche <[email protected]>
> ---
> drivers/platform/x86/dell/dell-smbios-base.c | 6 ++++++
> drivers/platform/x86/dell/dell-smbios.h | 1 +
> 2 files changed, 7 insertions(+)
>
> diff --git a/drivers/platform/x86/dell/dell-smbios-base.c b/drivers/platform/x86/dell/dell-smbios-base.c
> index e61bfaf8b5c4..6ae09d7f76fb 100644
> --- a/drivers/platform/x86/dell/dell-smbios-base.c
> +++ b/drivers/platform/x86/dell/dell-smbios-base.c
> @@ -350,6 +350,12 @@ void dell_laptop_call_notifier(unsigned long action, void *data)
> }
> EXPORT_SYMBOL_GPL(dell_laptop_call_notifier);
>
> +bool dell_laptop_check_supported_cmds(u16 class)
> +{

Hi,

the function dell_smbios_call_filter() says that classes above 30 are always unsupported,
so please check this here too.

Also please rename the function to something like dell_smbios_class_is_supported().

Other than that:
Reviewed-by: Armin Wolf <[email protected]>

> + return da_supported_commands & (1 << class);
> +}
> +EXPORT_SYMBOL_GPL(dell_laptop_check_supported_cmds);
> +
> static void __init parse_da_table(const struct dmi_header *dm)
> {
> /* Final token is a terminator, so we don't want to copy it */
> diff --git a/drivers/platform/x86/dell/dell-smbios.h b/drivers/platform/x86/dell/dell-smbios.h
> index eb341bf000c6..63116671eada 100644
> --- a/drivers/platform/x86/dell/dell-smbios.h
> +++ b/drivers/platform/x86/dell/dell-smbios.h
> @@ -73,6 +73,7 @@ enum dell_laptop_notifier_actions {
> int dell_laptop_register_notifier(struct notifier_block *nb);
> int dell_laptop_unregister_notifier(struct notifier_block *nb);
> void dell_laptop_call_notifier(unsigned long action, void *data);
> +bool dell_laptop_check_supported_cmds(u16 class);
>
> /* for the supported backends */
> #ifdef CONFIG_DELL_SMBIOS_WMI

2024-05-12 18:06:38

by Armin Wolf

[permalink] [raw]
Subject: Re: [PATCH v6 2/2] platform/x86: dell-laptop: Implement platform_profile

Am 11.05.24 um 04:36 schrieb Lyndon Sanche:

> Some Dell laptops support configuration of preset fan modes through
> smbios tables.
>
> If the platform supports these fan modes, set up platform_profile to
> change these modes. If not supported, skip enabling platform_profile.
>
> Signed-off-by: Lyndon Sanche <[email protected]>
> ---
> drivers/platform/x86/dell/Kconfig | 2 +
> drivers/platform/x86/dell/dell-laptop.c | 242 +++++++++++++++++++
> drivers/platform/x86/dell/dell-smbios-base.c | 1 +
> drivers/platform/x86/dell/dell-smbios.h | 1 +
> 4 files changed, 246 insertions(+)
>
> diff --git a/drivers/platform/x86/dell/Kconfig b/drivers/platform/x86/dell/Kconfig
> index bd9f445974cc..26679f22733c 100644
> --- a/drivers/platform/x86/dell/Kconfig
> +++ b/drivers/platform/x86/dell/Kconfig
> @@ -47,6 +47,7 @@ config DCDBAS
> config DELL_LAPTOP
> tristate "Dell Laptop Extras"
> default m
> + depends on ACPI
> depends on DMI
> depends on BACKLIGHT_CLASS_DEVICE
> depends on ACPI_VIDEO || ACPI_VIDEO = n
> @@ -57,6 +58,7 @@ config DELL_LAPTOP
> select POWER_SUPPLY
> select LEDS_CLASS
> select NEW_LEDS
> + select ACPI_PLATFORM_PROFILE
> help
> This driver adds support for rfkill and backlight control to Dell
> laptops (except for some models covered by the Compal driver).
> diff --git a/drivers/platform/x86/dell/dell-laptop.c b/drivers/platform/x86/dell/dell-laptop.c
> index 42f7de2b4522..07f54f1cbac5 100644
> --- a/drivers/platform/x86/dell/dell-laptop.c
> +++ b/drivers/platform/x86/dell/dell-laptop.c
> @@ -27,6 +27,9 @@
> #include <linux/i8042.h>
> #include <linux/debugfs.h>
> #include <linux/seq_file.h>
> +#include <linux/bitfield.h>
> +#include <linux/bits.h>
> +#include <linux/platform_profile.h>
> #include <acpi/video.h>
> #include "dell-rbtn.h"
> #include "dell-smbios.h"
> @@ -95,6 +98,7 @@ static struct backlight_device *dell_backlight_device;
> static struct rfkill *wifi_rfkill;
> static struct rfkill *bluetooth_rfkill;
> static struct rfkill *wwan_rfkill;
> +static struct platform_profile_handler *thermal_handler;
> static bool force_rfkill;
> static bool micmute_led_registered;
> static bool mute_led_registered;
> @@ -2199,6 +2203,236 @@ static int mute_led_set(struct led_classdev *led_cdev,
> return 0;
> }
>
> +/* Derived from smbios-thermal-ctl
> + *
> + * cbClass 17
> + * cbSelect 19
> + * User Selectable Thermal Tables(USTT)
> + * cbArg1 determines the function to be performed
> + * cbArg1 0x0 = Get Thermal Information
> + * cbRES1 Standard return codes (0, -1, -2)
> + * cbRES2, byte 0 Bitmap of supported thermal modes. A mode is supported if
> + * its bit is set to 1
> + * Bit 0 Balanced
> + * Bit 1 Cool Bottom
> + * Bit 2 Quiet
> + * Bit 3 Performance
> + * cbRES2, byte 1 Bitmap of supported Active Acoustic Controller (AAC) modes.
> + * Each mode corresponds to the supported thermal modes in
> + * byte 0. A mode is supported if its bit is set to 1.
> + * Bit 0 AAC (Balanced)
> + * Bit 1 AAC (Cool Bottom
> + * Bit 2 AAC (Quiet)
> + * Bit 3 AAC (Performance)
> + * cbRes3, byte 0 Current Thermal Mode
> + * Bit 0 Balanced
> + * Bit 1 Cool Bottom
> + * Bit 2 Quiet
> + * Bit 3 Performanc
> + * cbRes3, byte 1 AAC Configuration type
> + * 0 Global (AAC enable/disable applies to all supported USTT modes)
> + * 1 USTT mode specific
> + * cbRes3, byte 2 Current Active Acoustic Controller (AAC) Mode
> + * If AAC Configuration Type is Global,
> + * 0 AAC mode disabled
> + * 1 AAC mode enabled
> + * If AAC Configuration Type is USTT mode specific (multiple bits may be set),
> + * Bit 0 AAC (Balanced)
> + * Bit 1 AAC (Cool Bottom
> + * Bit 2 AAC (Quiet)
> + * Bit 3 AAC (Performance)
> + * cbRes3, byte 3 Current Fan Failure Mode
> + * Bit 0 Minimal Fan Failure (at least one fan has failed, one fan working)
> + * Bit 1 Catastrophic Fan Failure (all fans have failed)
> + *
> + * cbArg1 0x1 (Set Thermal Information), both desired thermal mode and
> + * desired AAC mode shall be applied
> + * cbArg2, byte 0 Desired Thermal Mode to set
> + * (only one bit may be set for this parameter)
> + * Bit 0 Balanced
> + * Bit 1 Cool Bottom
> + * Bit 2 Quiet
> + * Bit 3 Performance
> + * cbArg2, byte 1 Desired Active Acoustic Controller (AAC) Mode to set
> + * If AAC Configuration Type is Global,
> + * 0 AAC mode disabled
> + * 1 AAC mode enabled
> + * If AAC Configuration Type is USTT mode specific
> + * (multiple bits may be set for this parameter),
> + * Bit 0 AAC (Balanced)
> + * Bit 1 AAC (Cool Bottom
> + * Bit 2 AAC (Quiet)
> + * Bit 3 AAC (Performance)
> + */
> +
> +#define DELL_ACC_GET_FIELD GENMASK(19, 16)
> +#define DELL_ACC_SET_FIELD GENMASK(11, 8)
> +#define DELL_THERMAL_SUPPORTED GENMASK(3, 0)
> +
> +enum thermal_mode_bits {
> + DELL_BALANCED = BIT(0),
> + DELL_COOL_BOTTOM = BIT(1),
> + DELL_QUIET = BIT(2),
> + DELL_PERFORMANCE = BIT(3),
> +};
> +
> +static int thermal_get_mode(void)
> +{
> + struct calling_interface_buffer buffer;
> + int state;
> + int ret;
> +
> + dell_fill_request(&buffer, 0x0, 0, 0, 0);
> + ret = dell_send_request(&buffer, CLASS_INFO, SELECT_THERMAL_MANAGEMENT);
> + if (ret)
> + return ret;
> + state = buffer.output[2];
> + if (state & DELL_BALANCED)
> + return DELL_BALANCED;
> + else if (state & DELL_COOL_BOTTOM)
> + return DELL_COOL_BOTTOM;
> + else if (state & DELL_QUIET)
> + return DELL_QUIET;
> + else if (state & DELL_PERFORMANCE)
> + return DELL_PERFORMANCE;
> + else
> + return -ENXIO;
> +}
> +
> +static int thermal_get_supported_modes(int *supported_bits)
> +{
> + struct calling_interface_buffer buffer;
> + int ret;
> +
> + dell_fill_request(&buffer, 0x0, 0, 0, 0);
> + ret = dell_send_request(&buffer, CLASS_INFO, SELECT_THERMAL_MANAGEMENT);
> + if (ret)
> + return ret;
> + *supported_bits = FIELD_GET(DELL_THERMAL_SUPPORTED, buffer.output[1]);
> + return 0;
> +}
> +
> +static int thermal_get_acc_mode(int *acc_mode)
> +{
> + struct calling_interface_buffer buffer;
> + int ret;
> +
> + dell_fill_request(&buffer, 0x0, 0, 0, 0);
> + ret = dell_send_request(&buffer, CLASS_INFO, SELECT_THERMAL_MANAGEMENT);
> + if (ret)
> + return ret;
> + *acc_mode = FIELD_GET(DELL_ACC_GET_FIELD, buffer.output[3]);
> + return 0;
> +}
> +
> +static int thermal_set_mode(enum thermal_mode_bits state)
> +{
> + struct calling_interface_buffer buffer;
> + int ret;
> + int acc_mode;
> +
> + ret = thermal_get_acc_mode(&acc_mode);
> + if (ret)
> + return ret;
> +
> + dell_fill_request(&buffer, 0x1, FIELD_PREP(DELL_ACC_SET_FIELD, acc_mode) | state, 0, 0);
> + ret = dell_send_request(&buffer, CLASS_INFO, SELECT_THERMAL_MANAGEMENT);
> + return ret;
> +}
> +
> +static int thermal_platform_profile_set(struct platform_profile_handler *pprof,
> + enum platform_profile_option profile)
> +{
> + switch (profile) {
> + case PLATFORM_PROFILE_BALANCED:
> + return thermal_set_mode(DELL_BALANCED);
> + case PLATFORM_PROFILE_PERFORMANCE:
> + return thermal_set_mode(DELL_PERFORMANCE);
> + case PLATFORM_PROFILE_QUIET:
> + return thermal_set_mode(DELL_QUIET);
> + case PLATFORM_PROFILE_COOL:
> + return thermal_set_mode(DELL_COOL_BOTTOM);
> + default:
> + return -EOPNOTSUPP;
> + }
> +}
> +
> +static int thermal_platform_profile_get(struct platform_profile_handler *pprof,
> + enum platform_profile_option *profile)
> +{
> + int ret;
> +
> + ret = thermal_get_mode();
> + if (ret < 0)
> + return ret;
> +
> + switch (ret) {
> + case DELL_BALANCED:
> + *profile = PLATFORM_PROFILE_BALANCED;
> + break;
> + case DELL_PERFORMANCE:
> + *profile = PLATFORM_PROFILE_PERFORMANCE;
> + break;
> + case DELL_COOL_BOTTOM:
> + *profile = PLATFORM_PROFILE_COOL;
> + break;
> + case DELL_QUIET:
> + *profile = PLATFORM_PROFILE_QUIET;
> + break;
> + default:
> + return -EINVAL;
> + }
> +
> + return 0;
> +}
> +
> +static int thermal_init(void)
> +{
> + int ret;
> + int supported_modes;
> +
> + /* If thermal commands not supported, exit without error */
> + if (!dell_laptop_check_supported_cmds(CLASS_INFO))
> + return 0;
> +
> + /* If thermal modes not supported, exit without error */
> + ret = thermal_get_supported_modes(&supported_modes);
> + if (ret < 0)
> + return ret;

Hi,

the function dell_smbios_error() says that when a specific functionality is
not supported, -ENXIO is returned.

Please treat this as "no thermal modes supported", since checking if CLASS_INFO
is supported is not enough (CLASS_INFO is also used by other functionality like
rfkill, so machines might support CLASS_INFO but not USTT).

Thanks,
Armin Wolf

> + if (!supported_modes)
> + return 0;
> +
> + thermal_handler = kzalloc(sizeof(*thermal_handler), GFP_KERNEL);
> + if (!thermal_handler)
> + return -ENOMEM;
> + thermal_handler->profile_get = thermal_platform_profile_get;
> + thermal_handler->profile_set = thermal_platform_profile_set;
> +
> + if (supported_modes & DELL_QUIET)
> + set_bit(PLATFORM_PROFILE_QUIET, thermal_handler->choices);
> + if (supported_modes & DELL_COOL_BOTTOM)
> + set_bit(PLATFORM_PROFILE_COOL, thermal_handler->choices);
> + if (supported_modes & DELL_BALANCED)
> + set_bit(PLATFORM_PROFILE_BALANCED, thermal_handler->choices);
> + if (supported_modes & DELL_PERFORMANCE)
> + set_bit(PLATFORM_PROFILE_PERFORMANCE, thermal_handler->choices);
> +
> + /* Clean up if failed */
> + ret = platform_profile_register(thermal_handler);
> + if (ret)
> + kfree(thermal_handler);
> +
> + return ret;
> +}
> +
> +static void thermal_cleanup(void)
> +{
> + if (thermal_handler) {
> + platform_profile_remove();
> + kfree(thermal_handler);
> + }
> +}
> +
> static struct led_classdev mute_led_cdev = {
> .name = "platform::mute",
> .max_brightness = 1,
> @@ -2238,6 +2472,11 @@ static int __init dell_init(void)
> goto fail_rfkill;
> }
>
> + /* Do not fail module if thermal modes not supported, just skip */
> + ret = thermal_init();
> + if (ret)
> + goto fail_thermal;
> +
> if (quirks && quirks->touchpad_led)
> touchpad_led_init(&platform_device->dev);
>
> @@ -2317,6 +2556,8 @@ static int __init dell_init(void)
> led_classdev_unregister(&mute_led_cdev);
> fail_led:
> dell_cleanup_rfkill();
> +fail_thermal:
> + thermal_cleanup();
> fail_rfkill:
> platform_device_del(platform_device);
> fail_platform_device2:
> @@ -2344,6 +2585,7 @@ static void __exit dell_exit(void)
> platform_device_unregister(platform_device);
> platform_driver_unregister(&platform_driver);
> }
> + thermal_cleanup();
> }
>
> /* dell-rbtn.c driver export functions which will not work correctly (and could
> diff --git a/drivers/platform/x86/dell/dell-smbios-base.c b/drivers/platform/x86/dell/dell-smbios-base.c
> index 6ae09d7f76fb..387fa5618f7a 100644
> --- a/drivers/platform/x86/dell/dell-smbios-base.c
> +++ b/drivers/platform/x86/dell/dell-smbios-base.c
> @@ -71,6 +71,7 @@ static struct smbios_call call_blacklist[] = {
> /* handled by kernel: dell-laptop */
> {0x0000, CLASS_INFO, SELECT_RFKILL},
> {0x0000, CLASS_KBD_BACKLIGHT, SELECT_KBD_BACKLIGHT},
> + {0x0000, CLASS_INFO, SELECT_THERMAL_MANAGEMENT},
> };
>
> struct token_range {
> diff --git a/drivers/platform/x86/dell/dell-smbios.h b/drivers/platform/x86/dell/dell-smbios.h
> index 63116671eada..5d7178df80c6 100644
> --- a/drivers/platform/x86/dell/dell-smbios.h
> +++ b/drivers/platform/x86/dell/dell-smbios.h
> @@ -19,6 +19,7 @@
> /* Classes and selects used only in kernel drivers */
> #define CLASS_KBD_BACKLIGHT 4
> #define SELECT_KBD_BACKLIGHT 11
> +#define SELECT_THERMAL_MANAGEMENT 19
>
> /* Tokens used in kernel drivers, any of these
> * should be filtered from userspace access

2024-05-12 22:15:03

by Mario Limonciello

[permalink] [raw]
Subject: Re: [PATCH v5] platform/x86: dell-laptop: Implement platform_profile

On 5/12/2024 1:47 PM, Armin Wolf wrote:
>> Why?  Windows also does ACPI-WMI differently than Linux.  It's not as
>> easy to check both from a Windows utility due to that.
>
> Actually, it is quite easy to check both interfaces from a Windows
> utility. Both ACPI-WMI objects can be accessed by
> Windows applications, the utility just has to interact with an
> additional WMI object, but they decided to not do it.
>

Ah I didn't realize that they're actually instanciable from the WMI
repository in an application, but that makes perfect sense with how easy
it is to do from PowerShell.

> Also the original smbios-thermal-ctl utility was created by Dell itself
> (i think?), so they likely would have implemented this
> if it really was necessary.
>

It was created at a time that the ACPI WMI BIOS attributes interface
didn't exist. I've understood that the general direction is to use the
WMI BIOS attributes interface in the future.

That's why I was suggesting using both, if such a transition happens
then this driver would be ready for it.

> As Dell likely only tests their machines with Windows (if at all), i
> propose that we try to match the Windows behavior.

I don't have a strong horse in this game, but I see what you mean in
terms of general compatibility.

2024-05-13 20:10:08

by kernel test robot

[permalink] [raw]
Subject: Re: [PATCH v2] platform/x86: dell-laptop: Implement platform_profile

Hi Lyndon,

kernel test robot noticed the following build errors:

[auto build test ERROR on linus/master]
[also build test ERROR on v6.9 next-20240513]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]

url: https://github.com/intel-lab-lkp/linux/commits/Lyndon-Sanche/platform-x86-dell-laptop-Implement-platform_profile/20240511-144534
base: linus/master
patch link: https://lore.kernel.org/r/20240426020448.10862-1-lsanche%40lyndeno.ca
patch subject: [PATCH v2] platform/x86: dell-laptop: Implement platform_profile
config: i386-randconfig-005-20240513 (https://download.01.org/0day-ci/archive/20240514/[email protected]/config)
compiler: gcc-8 (Ubuntu 8.4.0-3ubuntu2) 8.4.0
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20240514/[email protected]/reproduce)

If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <[email protected]>
| Closes: https://lore.kernel.org/oe-kbuild-all/[email protected]/

All errors (new ones prefixed by >>):

ld: drivers/platform/x86/dell/dell-laptop.o: in function `thermal_init':
>> drivers/platform/x86/dell/dell-laptop.c:2404:(.text+0x21a3): undefined reference to `platform_profile_register'
ld: drivers/platform/x86/dell/dell-laptop.o: in function `thermal_cleanup':
>> drivers/platform/x86/dell/dell-laptop.c:2412:(.text+0x21cc): undefined reference to `platform_profile_remove'
>> ld: drivers/platform/x86/dell/dell-laptop.c:2412:(.init.text+0xb44): undefined reference to `platform_profile_remove'
>> ld: drivers/platform/x86/dell/dell-laptop.c:2412:(.exit.text+0x7c): undefined reference to `platform_profile_remove'


vim +2404 drivers/platform/x86/dell/dell-laptop.c

2377
2378 int thermal_init(void)
2379 {
2380 int ret;
2381 int supported_modes;
2382
2383 ret = thermal_get_supported_modes(&supported_modes);
2384
2385 if (ret || !supported_modes)
2386 return 0;
2387
2388 thermal_handler = kzalloc(sizeof(*thermal_handler), GFP_KERNEL);
2389 if (!thermal_handler)
2390 return -ENOMEM;
2391 thermal_handler->profile_get = thermal_platform_profile_get;
2392 thermal_handler->profile_set = thermal_platform_profile_set;
2393
2394 if ((supported_modes >> DELL_QUIET) & 1)
2395 set_bit(PLATFORM_PROFILE_QUIET, thermal_handler->choices);
2396 if ((supported_modes >> DELL_COOL_BOTTOM) & 1)
2397 set_bit(PLATFORM_PROFILE_COOL, thermal_handler->choices);
2398 if ((supported_modes >> DELL_BALANCED) & 1)
2399 set_bit(PLATFORM_PROFILE_BALANCED, thermal_handler->choices);
2400 if ((supported_modes >> DELL_PERFORMANCE) & 1)
2401 set_bit(PLATFORM_PROFILE_PERFORMANCE, thermal_handler->choices);
2402
2403 // Clean up but do not fail
> 2404 if (platform_profile_register(thermal_handler))
2405 kfree(thermal_handler);
2406
2407 return 0;
2408 }
2409
2410 void thermal_cleanup(void)
2411 {
> 2412 platform_profile_remove();
2413 kfree(thermal_handler);
2414 }
2415

--
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki

2024-05-15 17:07:27

by Lyndon Sanche

[permalink] [raw]
Subject: Re: [PATCH v6 2/2] platform/x86: dell-laptop: Implement platform_profile



On Sun, May 12, 2024, at 12:05 PM, Armin Wolf wrote:
> Am 11.05.24 um 04:36 schrieb Lyndon Sanche:
>

>> +static int thermal_init(void)
>> +{
>> + int ret;
>> + int supported_modes;
>> +
>> + /* If thermal commands not supported, exit without error */
>> + if (!dell_laptop_check_supported_cmds(CLASS_INFO))
>> + return 0;
>> +
>> + /* If thermal modes not supported, exit without error */
>> + ret = thermal_get_supported_modes(&supported_modes);
>> + if (ret < 0)
>> + return ret;
>
> Hi,
>
> the function dell_smbios_error() says that when a specific functionality is
> not supported, -ENXIO is returned.
>
> Please treat this as "no thermal modes supported", since checking if CLASS_INFO
> is supported is not enough (CLASS_INFO is also used by other functionality like
> rfkill, so machines might support CLASS_INFO but not USTT).
>
> Thanks,
> Armin Wolf
>

Armin:

Thank you for this. I will include this in the next revision.

Thanks,

Lyndon

2024-05-17 22:43:54

by Lyndon Sanche

[permalink] [raw]
Subject: [PATCH v7 0/3] platform/x86: dell: Implement platform_profile

v7:
- Move platform_profile into new dell-pc module
- Add myself as maintainer of dell-pc
- Move smbios call and fill functions to dell-smbios-base
- Check for classes above 30 and return as not supported
- Rename dell_laptop_check_supported_cmds to
dell_smbios_class_is_supported
- Check for ENXIO and treat as no thermal modes supported
v6:
- Add ACPI dependency for dell-laptop
- Add and use helper symbol for checking supported commands
v5:
- Fix indent in smbios-thermal-ctl comment
- Remove linux/wmi.h include
- Add 'select ACPI_PLATFORM_PROFILE' to Dell KConfig
v4:
- Make thermal_init and thermal_cleanup static
- Rearrange order of added includes, did not edit current includes
- Include bits.h
- Switch comment style
- Return error if platform_profile registering failed
- Add thermal calls to call_blacklist
- Align defines with tabs
- Correct separation of function and error handling
- Propagate error codes up
v3:
- Convert smbios-thermal-ctl docs to multiline comment and wrap
- Change thermal_mode_bits enum to directly be BIT() values
- Convert related code to use this
- Use FIELD_GET/PREP and GENNMASK for getting/setting thermal modes
- Correct offset for getting current ACC mode, setting offset
unchanged
- Check if thermal_handler is allocated before freeing and
unregistering platform_profile
v2:
- Wrap smbios-thermal-ctl comment
- Return proper error code when invalid state returned
- Simplify platform_profile_get returns
- Propogate ENOMEM error

Lyndon Sanche (3):
platform/x86: dell-smbios: Add helper for checking supported class
platform/x86: dell-smbios: Move request functions for reuse
platform/x86: dell-pc: Implement platform_profile

MAINTAINERS | 6 +
drivers/platform/x86/dell/Kconfig | 13 +
drivers/platform/x86/dell/Makefile | 1 +
drivers/platform/x86/dell/dell-laptop.c | 23 --
drivers/platform/x86/dell/dell-pc.c | 310 +++++++++++++++++++
drivers/platform/x86/dell/dell-smbios-base.c | 35 +++
drivers/platform/x86/dell/dell-smbios.h | 7 +
7 files changed, 372 insertions(+), 23 deletions(-)
create mode 100644 drivers/platform/x86/dell/dell-pc.c

--
2.42.0


2024-05-17 22:44:16

by Lyndon Sanche

[permalink] [raw]
Subject: [PATCH v7 1/3] platform/x86: dell-smbios: Add helper for checking supported class

Add helper that returns true if smbios command class is supported.

Signed-off-by: Lyndon Sanche <[email protected]>
---
drivers/platform/x86/dell/dell-smbios-base.c | 9 +++++++++
drivers/platform/x86/dell/dell-smbios.h | 1 +
2 files changed, 10 insertions(+)

diff --git a/drivers/platform/x86/dell/dell-smbios-base.c b/drivers/platform/x86/dell/dell-smbios-base.c
index e61bfaf8b5c4..fbdd12a7cb8d 100644
--- a/drivers/platform/x86/dell/dell-smbios-base.c
+++ b/drivers/platform/x86/dell/dell-smbios-base.c
@@ -350,6 +350,15 @@ void dell_laptop_call_notifier(unsigned long action, void *data)
}
EXPORT_SYMBOL_GPL(dell_laptop_call_notifier);

+bool dell_smbios_class_is_supported(u16 class)
+{
+ /* Classes over 30 always unsupported */
+ if (class > 30)
+ return false;
+ return da_supported_commands & (1 << class);
+}
+EXPORT_SYMBOL_GPL(dell_smbios_class_is_supported);
+
static void __init parse_da_table(const struct dmi_header *dm)
{
/* Final token is a terminator, so we don't want to copy it */
diff --git a/drivers/platform/x86/dell/dell-smbios.h b/drivers/platform/x86/dell/dell-smbios.h
index eb341bf000c6..756c354b1eef 100644
--- a/drivers/platform/x86/dell/dell-smbios.h
+++ b/drivers/platform/x86/dell/dell-smbios.h
@@ -73,6 +73,7 @@ enum dell_laptop_notifier_actions {
int dell_laptop_register_notifier(struct notifier_block *nb);
int dell_laptop_unregister_notifier(struct notifier_block *nb);
void dell_laptop_call_notifier(unsigned long action, void *data);
+bool dell_smbios_class_is_supported(u16 class);

/* for the supported backends */
#ifdef CONFIG_DELL_SMBIOS_WMI
--
2.42.0


2024-05-17 22:44:39

by Lyndon Sanche

[permalink] [raw]
Subject: [PATCH v7 2/3] platform/x86: dell-smbios: Move request functions for reuse

Move the dell_send_request and dell_fill_request symbols into smbios-base
so that they can be used in multiple modules.

Signed-off-by: Lyndon Sanche <[email protected]>
---
drivers/platform/x86/dell/dell-laptop.c | 23 ------------------
drivers/platform/x86/dell/dell-smbios-base.c | 25 ++++++++++++++++++++
drivers/platform/x86/dell/dell-smbios.h | 5 ++++
3 files changed, 30 insertions(+), 23 deletions(-)

diff --git a/drivers/platform/x86/dell/dell-laptop.c b/drivers/platform/x86/dell/dell-laptop.c
index 42f7de2b4522..6552dfe491c6 100644
--- a/drivers/platform/x86/dell/dell-laptop.c
+++ b/drivers/platform/x86/dell/dell-laptop.c
@@ -353,29 +353,6 @@ static const struct dmi_system_id dell_quirks[] __initconst = {
{ }
};

-static void dell_fill_request(struct calling_interface_buffer *buffer,
- u32 arg0, u32 arg1, u32 arg2, u32 arg3)
-{
- memset(buffer, 0, sizeof(struct calling_interface_buffer));
- buffer->input[0] = arg0;
- buffer->input[1] = arg1;
- buffer->input[2] = arg2;
- buffer->input[3] = arg3;
-}
-
-static int dell_send_request(struct calling_interface_buffer *buffer,
- u16 class, u16 select)
-{
- int ret;
-
- buffer->cmd_class = class;
- buffer->cmd_select = select;
- ret = dell_smbios_call(buffer);
- if (ret != 0)
- return ret;
- return dell_smbios_error(buffer->output[0]);
-}
-
/*
* Derived from information in smbios-wireless-ctl:
*
diff --git a/drivers/platform/x86/dell/dell-smbios-base.c b/drivers/platform/x86/dell/dell-smbios-base.c
index fbdd12a7cb8d..515c454acfe6 100644
--- a/drivers/platform/x86/dell/dell-smbios-base.c
+++ b/drivers/platform/x86/dell/dell-smbios-base.c
@@ -314,6 +314,31 @@ int dell_smbios_call(struct calling_interface_buffer *buffer)
}
EXPORT_SYMBOL_GPL(dell_smbios_call);

+void dell_fill_request(struct calling_interface_buffer *buffer,
+ u32 arg0, u32 arg1, u32 arg2, u32 arg3)
+{
+ memset(buffer, 0, sizeof(struct calling_interface_buffer));
+ buffer->input[0] = arg0;
+ buffer->input[1] = arg1;
+ buffer->input[2] = arg2;
+ buffer->input[3] = arg3;
+}
+EXPORT_SYMBOL_GPL(dell_fill_request);
+
+int dell_send_request(struct calling_interface_buffer *buffer,
+ u16 class, u16 select)
+{
+ int ret;
+
+ buffer->cmd_class = class;
+ buffer->cmd_select = select;
+ ret = dell_smbios_call(buffer);
+ if (ret != 0)
+ return ret;
+ return dell_smbios_error(buffer->output[0]);
+}
+EXPORT_SYMBOL_GPL(dell_send_request);
+
struct calling_interface_token *dell_smbios_find_token(int tokenid)
{
int i;
diff --git a/drivers/platform/x86/dell/dell-smbios.h b/drivers/platform/x86/dell/dell-smbios.h
index 756c354b1eef..1d6463cca12a 100644
--- a/drivers/platform/x86/dell/dell-smbios.h
+++ b/drivers/platform/x86/dell/dell-smbios.h
@@ -64,6 +64,11 @@ int dell_smbios_call_filter(struct device *d,
struct calling_interface_buffer *buffer);
int dell_smbios_call(struct calling_interface_buffer *buffer);

+void dell_fill_request(struct calling_interface_buffer *buffer,
+ u32 arg0, u32 arg1, u32 arg2, u32 arg3);
+int dell_send_request(struct calling_interface_buffer *buffer,
+ u16 class, u16 select);
+
struct calling_interface_token *dell_smbios_find_token(int tokenid);

enum dell_laptop_notifier_actions {
--
2.42.0


2024-05-17 22:45:05

by Lyndon Sanche

[permalink] [raw]
Subject: [PATCH v7 3/3] platform/x86: dell-pc: Implement platform_profile

Some Dell laptops support configuration of preset fan modes through
smbios tables.

If the platform supports these fan modes, set up platform_profile to
change these modes. If not supported, skip enabling platform_profile.

Signed-off-by: Lyndon Sanche <[email protected]>
---
MAINTAINERS | 6 +
drivers/platform/x86/dell/Kconfig | 13 +
drivers/platform/x86/dell/Makefile | 1 +
drivers/platform/x86/dell/dell-pc.c | 310 +++++++++++++++++++
drivers/platform/x86/dell/dell-smbios-base.c | 1 +
drivers/platform/x86/dell/dell-smbios.h | 1 +
6 files changed, 332 insertions(+)
create mode 100644 drivers/platform/x86/dell/dell-pc.c

diff --git a/MAINTAINERS b/MAINTAINERS
index ebf03f5f0619..69c582b72a08 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -5961,6 +5961,12 @@ F: Documentation/ABI/obsolete/procfs-i8k
F: drivers/hwmon/dell-smm-hwmon.c
F: include/uapi/linux/i8k.h

+DELL PC DRIVER
+M: Lyndon Sanche <[email protected]>
+L: [email protected]
+S: Maintained
+F: drivers/platform/x86/dell/dell-pc.c
+
DELL REMOTE BIOS UPDATE DRIVER
M: Stuart Hayes <[email protected]>
L: [email protected]
diff --git a/drivers/platform/x86/dell/Kconfig b/drivers/platform/x86/dell/Kconfig
index bd9f445974cc..0732850a3dd6 100644
--- a/drivers/platform/x86/dell/Kconfig
+++ b/drivers/platform/x86/dell/Kconfig
@@ -91,6 +91,19 @@ config DELL_RBTN
To compile this driver as a module, choose M here: the module will
be called dell-rbtn.

+config DELL_PC
+ tristate "Dell PC Extras"
+ default m
+ depends on ACPI
+ depends on DMI
+ depends on DELL_SMBIOS
+ select ACPI_PLATFORM_PROFILE
+ help
+ This driver adds support for controlling the fan modes via platform_profile
+ on supported Dell systems regardless of formfactor.
+ Module will simply do nothing if thermal management commands are not
+ supported.
+
#
# The DELL_SMBIOS driver depends on ACPI_WMI and/or DCDBAS if those
# backends are selected. The "depends" line prevents a configuration
diff --git a/drivers/platform/x86/dell/Makefile b/drivers/platform/x86/dell/Makefile
index 1b8942426622..9b0094fafcce 100644
--- a/drivers/platform/x86/dell/Makefile
+++ b/drivers/platform/x86/dell/Makefile
@@ -9,6 +9,7 @@ obj-$(CONFIG_DCDBAS) += dcdbas.o
obj-$(CONFIG_DELL_LAPTOP) += dell-laptop.o
obj-$(CONFIG_DELL_RBTN) += dell-rbtn.o
obj-$(CONFIG_DELL_RBU) += dell_rbu.o
+obj-$(CONFIG_DELL_PC) += dell-pc.o
obj-$(CONFIG_DELL_SMBIOS) += dell-smbios.o
dell-smbios-objs := dell-smbios-base.o
dell-smbios-$(CONFIG_DELL_SMBIOS_WMI) += dell-smbios-wmi.o
diff --git a/drivers/platform/x86/dell/dell-pc.c b/drivers/platform/x86/dell/dell-pc.c
new file mode 100644
index 000000000000..3dd762e39f45
--- /dev/null
+++ b/drivers/platform/x86/dell/dell-pc.c
@@ -0,0 +1,310 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Driver for Dell laptop extras
+ *
+ * Copyright (c) Lyndon Sanche <[email protected]>
+ *
+ * Based on documentation in the libsmbios package:
+ * Copyright (C) 2005-2014 Dell Inc.
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/err.h>
+#include <linux/dmi.h>
+#include <linux/bitfield.h>
+#include <linux/bits.h>
+#include <linux/platform_profile.h>
+#include <linux/slab.h>
+#include "dell-smbios.h"
+
+
+static const struct dmi_system_id dell_device_table[] __initconst = {
+ {
+ .ident = "Dell Inc.",
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
+ },
+ },
+ {
+ .ident = "Dell Computer Corporation",
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "Dell Computer Corporation"),
+ },
+ },
+ { }
+};
+MODULE_DEVICE_TABLE(dmi, dell_device_table);
+
+/* Derived from smbios-thermal-ctl
+ *
+ * cbClass 17
+ * cbSelect 19
+ * User Selectable Thermal Tables(USTT)
+ * cbArg1 determines the function to be performed
+ * cbArg1 0x0 = Get Thermal Information
+ * cbRES1 Standard return codes (0, -1, -2)
+ * cbRES2, byte 0 Bitmap of supported thermal modes. A mode is supported if
+ * its bit is set to 1
+ * Bit 0 Balanced
+ * Bit 1 Cool Bottom
+ * Bit 2 Quiet
+ * Bit 3 Performance
+ * cbRES2, byte 1 Bitmap of supported Active Acoustic Controller (AAC) modes.
+ * Each mode corresponds to the supported thermal modes in
+ * byte 0. A mode is supported if its bit is set to 1.
+ * Bit 0 AAC (Balanced)
+ * Bit 1 AAC (Cool Bottom
+ * Bit 2 AAC (Quiet)
+ * Bit 3 AAC (Performance)
+ * cbRes3, byte 0 Current Thermal Mode
+ * Bit 0 Balanced
+ * Bit 1 Cool Bottom
+ * Bit 2 Quiet
+ * Bit 3 Performanc
+ * cbRes3, byte 1 AAC Configuration type
+ * 0 Global (AAC enable/disable applies to all supported USTT modes)
+ * 1 USTT mode specific
+ * cbRes3, byte 2 Current Active Acoustic Controller (AAC) Mode
+ * If AAC Configuration Type is Global,
+ * 0 AAC mode disabled
+ * 1 AAC mode enabled
+ * If AAC Configuration Type is USTT mode specific (multiple bits may be set),
+ * Bit 0 AAC (Balanced)
+ * Bit 1 AAC (Cool Bottom
+ * Bit 2 AAC (Quiet)
+ * Bit 3 AAC (Performance)
+ * cbRes3, byte 3 Current Fan Failure Mode
+ * Bit 0 Minimal Fan Failure (at least one fan has failed, one fan working)
+ * Bit 1 Catastrophic Fan Failure (all fans have failed)
+ *
+ * cbArg1 0x1 (Set Thermal Information), both desired thermal mode and
+ * desired AAC mode shall be applied
+ * cbArg2, byte 0 Desired Thermal Mode to set
+ * (only one bit may be set for this parameter)
+ * Bit 0 Balanced
+ * Bit 1 Cool Bottom
+ * Bit 2 Quiet
+ * Bit 3 Performance
+ * cbArg2, byte 1 Desired Active Acoustic Controller (AAC) Mode to set
+ * If AAC Configuration Type is Global,
+ * 0 AAC mode disabled
+ * 1 AAC mode enabled
+ * If AAC Configuration Type is USTT mode specific
+ * (multiple bits may be set for this parameter),
+ * Bit 0 AAC (Balanced)
+ * Bit 1 AAC (Cool Bottom
+ * Bit 2 AAC (Quiet)
+ * Bit 3 AAC (Performance)
+ */
+
+#define DELL_ACC_GET_FIELD GENMASK(19, 16)
+#define DELL_ACC_SET_FIELD GENMASK(11, 8)
+#define DELL_THERMAL_SUPPORTED GENMASK(3, 0)
+
+static struct platform_profile_handler *thermal_handler;
+
+enum thermal_mode_bits {
+ DELL_BALANCED = BIT(0),
+ DELL_COOL_BOTTOM = BIT(1),
+ DELL_QUIET = BIT(2),
+ DELL_PERFORMANCE = BIT(3),
+};
+
+static int thermal_get_mode(void)
+{
+ struct calling_interface_buffer buffer;
+ int state;
+ int ret;
+
+ dell_fill_request(&buffer, 0x0, 0, 0, 0);
+ ret = dell_send_request(&buffer, CLASS_INFO, SELECT_THERMAL_MANAGEMENT);
+ if (ret)
+ return ret;
+ state = buffer.output[2];
+ if (state & DELL_BALANCED)
+ return DELL_BALANCED;
+ else if (state & DELL_COOL_BOTTOM)
+ return DELL_COOL_BOTTOM;
+ else if (state & DELL_QUIET)
+ return DELL_QUIET;
+ else if (state & DELL_PERFORMANCE)
+ return DELL_PERFORMANCE;
+ else
+ return -ENXIO;
+}
+
+static int thermal_get_supported_modes(int *supported_bits)
+{
+ struct calling_interface_buffer buffer;
+ int ret;
+
+ dell_fill_request(&buffer, 0x0, 0, 0, 0);
+ ret = dell_send_request(&buffer, CLASS_INFO, SELECT_THERMAL_MANAGEMENT);
+ if (ret) {
+ /* Thermal function not supported */
+ if (ret == -ENXIO) {
+ *supported_bits = 0;
+ return 0;
+ } else {
+ return ret;
+ }
+ }
+ *supported_bits = FIELD_GET(DELL_THERMAL_SUPPORTED, buffer.output[1]);
+ return 0;
+}
+
+static int thermal_get_acc_mode(int *acc_mode)
+{
+ struct calling_interface_buffer buffer;
+ int ret;
+
+ dell_fill_request(&buffer, 0x0, 0, 0, 0);
+ ret = dell_send_request(&buffer, CLASS_INFO, SELECT_THERMAL_MANAGEMENT);
+ if (ret)
+ return ret;
+ *acc_mode = FIELD_GET(DELL_ACC_GET_FIELD, buffer.output[3]);
+ return 0;
+}
+
+static int thermal_set_mode(enum thermal_mode_bits state)
+{
+ struct calling_interface_buffer buffer;
+ int ret;
+ int acc_mode;
+
+ ret = thermal_get_acc_mode(&acc_mode);
+ if (ret)
+ return ret;
+
+ dell_fill_request(&buffer, 0x1, FIELD_PREP(DELL_ACC_SET_FIELD, acc_mode) | state, 0, 0);
+ ret = dell_send_request(&buffer, CLASS_INFO, SELECT_THERMAL_MANAGEMENT);
+ return ret;
+}
+
+static int thermal_platform_profile_set(struct platform_profile_handler *pprof,
+ enum platform_profile_option profile)
+{
+ switch (profile) {
+ case PLATFORM_PROFILE_BALANCED:
+ return thermal_set_mode(DELL_BALANCED);
+ case PLATFORM_PROFILE_PERFORMANCE:
+ return thermal_set_mode(DELL_PERFORMANCE);
+ case PLATFORM_PROFILE_QUIET:
+ return thermal_set_mode(DELL_QUIET);
+ case PLATFORM_PROFILE_COOL:
+ return thermal_set_mode(DELL_COOL_BOTTOM);
+ default:
+ return -EOPNOTSUPP;
+ }
+}
+
+static int thermal_platform_profile_get(struct platform_profile_handler *pprof,
+ enum platform_profile_option *profile)
+{
+ int ret;
+
+ ret = thermal_get_mode();
+ if (ret < 0)
+ return ret;
+
+ switch (ret) {
+ case DELL_BALANCED:
+ *profile = PLATFORM_PROFILE_BALANCED;
+ break;
+ case DELL_PERFORMANCE:
+ *profile = PLATFORM_PROFILE_PERFORMANCE;
+ break;
+ case DELL_COOL_BOTTOM:
+ *profile = PLATFORM_PROFILE_COOL;
+ break;
+ case DELL_QUIET:
+ *profile = PLATFORM_PROFILE_QUIET;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int thermal_init(void)
+{
+ int ret;
+ int supported_modes;
+
+ /* If thermal commands not supported, exit without error */
+ if (!dell_smbios_class_is_supported(CLASS_INFO))
+ return 0;
+
+ /* If thermal modes not supported, exit without error */
+ ret = thermal_get_supported_modes(&supported_modes);
+ if (ret < 0)
+ return ret;
+ if (!supported_modes)
+ return 0;
+
+ thermal_handler = kzalloc(sizeof(*thermal_handler), GFP_KERNEL);
+ if (!thermal_handler)
+ return -ENOMEM;
+ thermal_handler->profile_get = thermal_platform_profile_get;
+ thermal_handler->profile_set = thermal_platform_profile_set;
+
+ if (supported_modes & DELL_QUIET)
+ set_bit(PLATFORM_PROFILE_QUIET, thermal_handler->choices);
+ if (supported_modes & DELL_COOL_BOTTOM)
+ set_bit(PLATFORM_PROFILE_COOL, thermal_handler->choices);
+ if (supported_modes & DELL_BALANCED)
+ set_bit(PLATFORM_PROFILE_BALANCED, thermal_handler->choices);
+ if (supported_modes & DELL_PERFORMANCE)
+ set_bit(PLATFORM_PROFILE_PERFORMANCE, thermal_handler->choices);
+
+ /* Clean up if failed */
+ ret = platform_profile_register(thermal_handler);
+ if (ret)
+ kfree(thermal_handler);
+
+ return ret;
+}
+
+static void thermal_cleanup(void)
+{
+ if (thermal_handler) {
+ platform_profile_remove();
+ kfree(thermal_handler);
+ }
+}
+
+static int __init dell_init(void)
+{
+ int ret;
+
+ if (!dmi_check_system(dell_device_table))
+ return -ENODEV;
+
+ /* Do not fail module if thermal modes not supported, just skip */
+ ret = thermal_init();
+ if (ret)
+ goto fail_thermal;
+
+ return 0;
+
+fail_thermal:
+ thermal_cleanup();
+ return ret;
+}
+
+static void __exit dell_exit(void)
+{
+ thermal_cleanup();
+}
+
+module_init(dell_init);
+module_exit(dell_exit);
+
+MODULE_AUTHOR("Lyndon Sanche <[email protected]>");
+MODULE_DESCRIPTION("Dell PC driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/platform/x86/dell/dell-smbios-base.c b/drivers/platform/x86/dell/dell-smbios-base.c
index 515c454acfe6..d61b33d5af95 100644
--- a/drivers/platform/x86/dell/dell-smbios-base.c
+++ b/drivers/platform/x86/dell/dell-smbios-base.c
@@ -71,6 +71,7 @@ static struct smbios_call call_blacklist[] = {
/* handled by kernel: dell-laptop */
{0x0000, CLASS_INFO, SELECT_RFKILL},
{0x0000, CLASS_KBD_BACKLIGHT, SELECT_KBD_BACKLIGHT},
+ {0x0000, CLASS_INFO, SELECT_THERMAL_MANAGEMENT},
};

struct token_range {
diff --git a/drivers/platform/x86/dell/dell-smbios.h b/drivers/platform/x86/dell/dell-smbios.h
index 1d6463cca12a..ea0cc38642a2 100644
--- a/drivers/platform/x86/dell/dell-smbios.h
+++ b/drivers/platform/x86/dell/dell-smbios.h
@@ -19,6 +19,7 @@
/* Classes and selects used only in kernel drivers */
#define CLASS_KBD_BACKLIGHT 4
#define SELECT_KBD_BACKLIGHT 11
+#define SELECT_THERMAL_MANAGEMENT 19

/* Tokens used in kernel drivers, any of these
* should be filtered from userspace access
--
2.42.0


2024-05-21 20:51:22

by Mario Limonciello

[permalink] [raw]
Subject: Re: [PATCH v7 0/3] platform/x86: dell: Implement platform_profile

On 5/17/2024 17:42, Lyndon Sanche wrote:
> v7:
> - Move platform_profile into new dell-pc module
> - Add myself as maintainer of dell-pc
> - Move smbios call and fill functions to dell-smbios-base
> - Check for classes above 30 and return as not supported
> - Rename dell_laptop_check_supported_cmds to
> dell_smbios_class_is_supported
> - Check for ENXIO and treat as no thermal modes supported
> v6:
> - Add ACPI dependency for dell-laptop
> - Add and use helper symbol for checking supported commands
> v5:
> - Fix indent in smbios-thermal-ctl comment
> - Remove linux/wmi.h include
> - Add 'select ACPI_PLATFORM_PROFILE' to Dell KConfig
> v4:
> - Make thermal_init and thermal_cleanup static
> - Rearrange order of added includes, did not edit current includes
> - Include bits.h
> - Switch comment style
> - Return error if platform_profile registering failed
> - Add thermal calls to call_blacklist
> - Align defines with tabs
> - Correct separation of function and error handling
> - Propagate error codes up
> v3:
> - Convert smbios-thermal-ctl docs to multiline comment and wrap
> - Change thermal_mode_bits enum to directly be BIT() values
> - Convert related code to use this
> - Use FIELD_GET/PREP and GENNMASK for getting/setting thermal modes
> - Correct offset for getting current ACC mode, setting offset
> unchanged
> - Check if thermal_handler is allocated before freeing and
> unregistering platform_profile
> v2:
> - Wrap smbios-thermal-ctl comment
> - Return proper error code when invalid state returned
> - Simplify platform_profile_get returns
> - Propogate ENOMEM error
>
> Lyndon Sanche (3):
> platform/x86: dell-smbios: Add helper for checking supported class
> platform/x86: dell-smbios: Move request functions for reuse
> platform/x86: dell-pc: Implement platform_profile
>
> MAINTAINERS | 6 +
> drivers/platform/x86/dell/Kconfig | 13 +
> drivers/platform/x86/dell/Makefile | 1 +
> drivers/platform/x86/dell/dell-laptop.c | 23 --
> drivers/platform/x86/dell/dell-pc.c | 310 +++++++++++++++++++
> drivers/platform/x86/dell/dell-smbios-base.c | 35 +++
> drivers/platform/x86/dell/dell-smbios.h | 7 +
> 7 files changed, 372 insertions(+), 23 deletions(-)
> create mode 100644 drivers/platform/x86/dell/dell-pc.c
>

Series looks good to me, thanks.

Reviewed-by: Mario Limonciello <[email protected]>

2024-05-27 13:24:04

by Ilpo Järvinen

[permalink] [raw]
Subject: Re: [PATCH v7 3/3] platform/x86: dell-pc: Implement platform_profile

On Fri, 17 May 2024, Lyndon Sanche wrote:

> Some Dell laptops support configuration of preset fan modes through
> smbios tables.
>
> If the platform supports these fan modes, set up platform_profile to
> change these modes. If not supported, skip enabling platform_profile.
>
> Signed-off-by: Lyndon Sanche <[email protected]>
> ---
> MAINTAINERS | 6 +
> drivers/platform/x86/dell/Kconfig | 13 +
> drivers/platform/x86/dell/Makefile | 1 +
> drivers/platform/x86/dell/dell-pc.c | 310 +++++++++++++++++++
> drivers/platform/x86/dell/dell-smbios-base.c | 1 +
> drivers/platform/x86/dell/dell-smbios.h | 1 +
> 6 files changed, 332 insertions(+)
> create mode 100644 drivers/platform/x86/dell/dell-pc.c
>
> diff --git a/MAINTAINERS b/MAINTAINERS
> index ebf03f5f0619..69c582b72a08 100644
> --- a/MAINTAINERS
> +++ b/MAINTAINERS
> @@ -5961,6 +5961,12 @@ F: Documentation/ABI/obsolete/procfs-i8k
> F: drivers/hwmon/dell-smm-hwmon.c
> F: include/uapi/linux/i8k.h
>
> +DELL PC DRIVER
> +M: Lyndon Sanche <[email protected]>
> +L: [email protected]
> +S: Maintained
> +F: drivers/platform/x86/dell/dell-pc.c
> +
> DELL REMOTE BIOS UPDATE DRIVER
> M: Stuart Hayes <[email protected]>
> L: [email protected]
> diff --git a/drivers/platform/x86/dell/Kconfig b/drivers/platform/x86/dell/Kconfig
> index bd9f445974cc..0732850a3dd6 100644
> --- a/drivers/platform/x86/dell/Kconfig
> +++ b/drivers/platform/x86/dell/Kconfig
> @@ -91,6 +91,19 @@ config DELL_RBTN
> To compile this driver as a module, choose M here: the module will
> be called dell-rbtn.
>
> +config DELL_PC
> + tristate "Dell PC Extras"
> + default m
> + depends on ACPI
> + depends on DMI
> + depends on DELL_SMBIOS
> + select ACPI_PLATFORM_PROFILE
> + help
> + This driver adds support for controlling the fan modes via platform_profile
> + on supported Dell systems regardless of formfactor.
> + Module will simply do nothing if thermal management commands are not
> + supported.


> +#include <linux/module.h>
> +#include <linux/kernel.h>
> +#include <linux/init.h>
> +#include <linux/err.h>
> +#include <linux/dmi.h>
> +#include <linux/bitfield.h>
> +#include <linux/bits.h>
> +#include <linux/platform_profile.h>
> +#include <linux/slab.h>
> +#include "dell-smbios.h"

Add empty line between <> and "" includes.

> +static const struct dmi_system_id dell_device_table[] __initconst = {
> + {
> + .ident = "Dell Inc.",
> + .matches = {
> + DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
> + },
> + },
> + {
> + .ident = "Dell Computer Corporation",
> + .matches = {
> + DMI_MATCH(DMI_SYS_VENDOR, "Dell Computer Corporation"),
> + },
> + },
> + { }
> +};
> +MODULE_DEVICE_TABLE(dmi, dell_device_table);

> +enum thermal_mode_bits {
> + DELL_BALANCED = BIT(0),
> + DELL_COOL_BOTTOM = BIT(1),
> + DELL_QUIET = BIT(2),
> + DELL_PERFORMANCE = BIT(3),

A few nits still to address.

Can you please align these so that the values align (IIRC, I asked this
earlier but perhaps my request was too unclear):

DELL_XX = BIT(X),
DELL_YYYYYYYYY = BIT(Y),

> +static int thermal_get_supported_modes(int *supported_bits)
> +{
> + struct calling_interface_buffer buffer;
> + int ret;
> +
> + dell_fill_request(&buffer, 0x0, 0, 0, 0);
> + ret = dell_send_request(&buffer, CLASS_INFO, SELECT_THERMAL_MANAGEMENT);
> + if (ret) {
> + /* Thermal function not supported */
> + if (ret == -ENXIO) {
> + *supported_bits = 0;
> + return 0;
> + } else {

Drop else because the previous block ends into return.

> + return ret;
> + }
> + }

Remove the outer if (ret) block and put the inner ones directly on the
main level as two if () conditions.

> + *supported_bits = FIELD_GET(DELL_THERMAL_SUPPORTED, buffer.output[1]);
> + return 0;
> +}
> +
> +static int thermal_get_acc_mode(int *acc_mode)
> +{
> + struct calling_interface_buffer buffer;
> + int ret;
> +
> + dell_fill_request(&buffer, 0x0, 0, 0, 0);
> + ret = dell_send_request(&buffer, CLASS_INFO, SELECT_THERMAL_MANAGEMENT);
> + if (ret)
> + return ret;
> + *acc_mode = FIELD_GET(DELL_ACC_GET_FIELD, buffer.output[3]);
> + return 0;
> +}
> +
> +static int thermal_set_mode(enum thermal_mode_bits state)
> +{
> + struct calling_interface_buffer buffer;
> + int ret;
> + int acc_mode;
> +
> + ret = thermal_get_acc_mode(&acc_mode);
> + if (ret)
> + return ret;
> +
> + dell_fill_request(&buffer, 0x1, FIELD_PREP(DELL_ACC_SET_FIELD, acc_mode) | state, 0, 0);
> + ret = dell_send_request(&buffer, CLASS_INFO, SELECT_THERMAL_MANAGEMENT);
> + return ret;

Return directly on the previous line.

> +static int thermal_platform_profile_get(struct platform_profile_handler *pprof,
> + enum platform_profile_option *profile)
> +{
> + int ret;
> +
> + ret = thermal_get_mode();
> + if (ret < 0)
> + return ret;
> +
> + switch (ret) {
> + case DELL_BALANCED:
> + *profile = PLATFORM_PROFILE_BALANCED;
> + break;
> + case DELL_PERFORMANCE:
> + *profile = PLATFORM_PROFILE_PERFORMANCE;
> + break;
> + case DELL_COOL_BOTTOM:
> + *profile = PLATFORM_PROFILE_COOL;
> + break;
> + case DELL_QUIET:
> + *profile = PLATFORM_PROFILE_QUIET;
> + break;
> + default:
> + return -EINVAL;
> + }
> +
> + return 0;
> +}
> +
> +static int thermal_init(void)
> +{
> + int ret;
> + int supported_modes;
> +
> + /* If thermal commands not supported, exit without error */

Fix grammar, you're perhaps missing "are".

> + if (!dell_smbios_class_is_supported(CLASS_INFO))
> + return 0;
> +
> + /* If thermal modes not supported, exit without error */

Ditto.

--
i.

2024-05-28 16:16:48

by Lyndon Sanche

[permalink] [raw]
Subject: Re: [PATCH v7 3/3] platform/x86: dell-pc: Implement platform_profile

On Mon, May 27, 2024, at 3:39 AM, Ilpo Järvinen wrote:
> On Fri, 17 May 2024, Lyndon Sanche wrote:
>
>> +#include <linux/platform_profile.h>
>> +#include <linux/slab.h>
>> +#include "dell-smbios.h"
>
> Add empty line between <> and "" includes.

Agreed.

>> +enum thermal_mode_bits {
>> + DELL_BALANCED = BIT(0),
>> + DELL_COOL_BOTTOM = BIT(1),
>> + DELL_QUIET = BIT(2),
>> + DELL_PERFORMANCE = BIT(3),
>
> A few nits still to address.
>
> Can you please align these so that the values align (IIRC, I asked this
> earlier but perhaps my request was too unclear):
>
> DELL_XX = BIT(X),
> DELL_YYYYYYYYY = BIT(Y),
>

I must have missed this, I will get this corrected.

>> +static int thermal_get_supported_modes(int *supported_bits)
>> +{
>> + struct calling_interface_buffer buffer;
>> + int ret;
>> +
>> + dell_fill_request(&buffer, 0x0, 0, 0, 0);
>> + ret = dell_send_request(&buffer, CLASS_INFO, SELECT_THERMAL_MANAGEMENT);
>> + if (ret) {
>> + /* Thermal function not supported */
>> + if (ret == -ENXIO) {
>> + *supported_bits = 0;
>> + return 0;
>> + } else {
>
> Drop else because the previous block ends into return.
>

Agreed.

>> + return ret;
>> + }
>> + }
>
> Remove the outer if (ret) block and put the inner ones directly on the
> main level as two if () conditions.
>

Agreed.

>> + dell_fill_request(&buffer, 0x1, FIELD_PREP(DELL_ACC_SET_FIELD, acc_mode) | state, 0, 0);
>> + ret = dell_send_request(&buffer, CLASS_INFO, SELECT_THERMAL_MANAGEMENT);
>> + return ret;
>
> Return directly on the previous line.
>

Agreed.

>> + int ret;
>> + int supported_modes;
>> +
>> + /* If thermal commands not supported, exit without error */
>
> Fix grammar, you're perhaps missing "are".
>

Agreed.

>> + if (!dell_smbios_class_is_supported(CLASS_INFO))
>> + return 0;
>> +
>> + /* If thermal modes not supported, exit without error */
>
> Ditto.
>
> --
> i.

Thank you for your feedback. I will include this in the next patch series.

Thanks,

Lyndon

2024-05-29 17:49:18

by Lyndon Sanche

[permalink] [raw]
Subject: [PATCH v8 0/3] platform/x86: dell: Implement platform_profile

v8:
- Rebase all patches against master
- dell-pc.c:
- Separate <> and "" includes
- Align thermal_mode_bits with tabs
- Flatten nested ifs
- Directly return dell_send_request
- Correct some grammar
v7:
- Move platform_profile into new dell-pc module
- Add myself as maintainer of dell-pc
- Move smbios call and fill functions to dell-smbios-base
- Check for classes above 30 and return as not supported
- Rename dell_laptop_check_supported_cmds to
dell_smbios_class_is_supported
- Check for ENXIO and treat as no thermal modes supported
v6:
- Add ACPI dependency for dell-laptop
- Add and use helper symbol for checking supported commands
v5:
- Fix indent in smbios-thermal-ctl comment
- Remove linux/wmi.h include
- Add 'select ACPI_PLATFORM_PROFILE' to Dell KConfig
v4:
- Make thermal_init and thermal_cleanup static
- Rearrange order of added includes, did not edit current includes
- Include bits.h
- Switch comment style
- Return error if platform_profile registering failed
- Add thermal calls to call_blacklist
- Align defines with tabs
- Correct separation of function and error handling
- Propagate error codes up
v3:
- Convert smbios-thermal-ctl docs to multiline comment and wrap
- Change thermal_mode_bits enum to directly be BIT() values
- Convert related code to use this
- Use FIELD_GET/PREP and GENNMASK for getting/setting thermal modes
- Correct offset for getting current ACC mode, setting offset
unchanged
- Check if thermal_handler is allocated before freeing and
unregistering platform_profile
v2:
- Wrap smbios-thermal-ctl comment
- Return proper error code when invalid state returned
- Simplify platform_profile_get returns
- Propagate ENOMEM error

Lyndon Sanche (3):
platform/x86: dell-smbios: Add helper for checking supported class
platform/x86: dell-smbios: Move request functions for reuse
platform/x86: dell-pc: Implement platform_profile

MAINTAINERS | 6 +
drivers/platform/x86/dell/Kconfig | 13 +
drivers/platform/x86/dell/Makefile | 1 +
drivers/platform/x86/dell/dell-laptop.c | 23 --
drivers/platform/x86/dell/dell-pc.c | 307 +++++++++++++++++++
drivers/platform/x86/dell/dell-smbios-base.c | 35 +++
drivers/platform/x86/dell/dell-smbios.h | 7 +
7 files changed, 369 insertions(+), 23 deletions(-)
create mode 100644 drivers/platform/x86/dell/dell-pc.c

--
2.42.0


2024-05-29 17:49:45

by Lyndon Sanche

[permalink] [raw]
Subject: [PATCH v8 1/3] platform/x86: dell-smbios: Add helper for checking supported class

Add helper that returns true if smbios command class is supported.

Signed-off-by: Lyndon Sanche <[email protected]>
---
drivers/platform/x86/dell/dell-smbios-base.c | 9 +++++++++
drivers/platform/x86/dell/dell-smbios.h | 1 +
2 files changed, 10 insertions(+)

diff --git a/drivers/platform/x86/dell/dell-smbios-base.c b/drivers/platform/x86/dell/dell-smbios-base.c
index e61bfaf8b5c4..fbdd12a7cb8d 100644
--- a/drivers/platform/x86/dell/dell-smbios-base.c
+++ b/drivers/platform/x86/dell/dell-smbios-base.c
@@ -350,6 +350,15 @@ void dell_laptop_call_notifier(unsigned long action, void *data)
}
EXPORT_SYMBOL_GPL(dell_laptop_call_notifier);

+bool dell_smbios_class_is_supported(u16 class)
+{
+ /* Classes over 30 always unsupported */
+ if (class > 30)
+ return false;
+ return da_supported_commands & (1 << class);
+}
+EXPORT_SYMBOL_GPL(dell_smbios_class_is_supported);
+
static void __init parse_da_table(const struct dmi_header *dm)
{
/* Final token is a terminator, so we don't want to copy it */
diff --git a/drivers/platform/x86/dell/dell-smbios.h b/drivers/platform/x86/dell/dell-smbios.h
index eb341bf000c6..756c354b1eef 100644
--- a/drivers/platform/x86/dell/dell-smbios.h
+++ b/drivers/platform/x86/dell/dell-smbios.h
@@ -73,6 +73,7 @@ enum dell_laptop_notifier_actions {
int dell_laptop_register_notifier(struct notifier_block *nb);
int dell_laptop_unregister_notifier(struct notifier_block *nb);
void dell_laptop_call_notifier(unsigned long action, void *data);
+bool dell_smbios_class_is_supported(u16 class);

/* for the supported backends */
#ifdef CONFIG_DELL_SMBIOS_WMI
--
2.42.0


2024-05-29 17:50:11

by Lyndon Sanche

[permalink] [raw]
Subject: [PATCH v8 2/3] platform/x86: dell-smbios: Move request functions for reuse

Move the dell_send_request and dell_fill_request symbols into smbios-base
so that they can be used in multiple modules.

Signed-off-by: Lyndon Sanche <[email protected]>
---
drivers/platform/x86/dell/dell-laptop.c | 23 ------------------
drivers/platform/x86/dell/dell-smbios-base.c | 25 ++++++++++++++++++++
drivers/platform/x86/dell/dell-smbios.h | 5 ++++
3 files changed, 30 insertions(+), 23 deletions(-)

diff --git a/drivers/platform/x86/dell/dell-laptop.c b/drivers/platform/x86/dell/dell-laptop.c
index 42f7de2b4522..6552dfe491c6 100644
--- a/drivers/platform/x86/dell/dell-laptop.c
+++ b/drivers/platform/x86/dell/dell-laptop.c
@@ -353,29 +353,6 @@ static const struct dmi_system_id dell_quirks[] __initconst = {
{ }
};

-static void dell_fill_request(struct calling_interface_buffer *buffer,
- u32 arg0, u32 arg1, u32 arg2, u32 arg3)
-{
- memset(buffer, 0, sizeof(struct calling_interface_buffer));
- buffer->input[0] = arg0;
- buffer->input[1] = arg1;
- buffer->input[2] = arg2;
- buffer->input[3] = arg3;
-}
-
-static int dell_send_request(struct calling_interface_buffer *buffer,
- u16 class, u16 select)
-{
- int ret;
-
- buffer->cmd_class = class;
- buffer->cmd_select = select;
- ret = dell_smbios_call(buffer);
- if (ret != 0)
- return ret;
- return dell_smbios_error(buffer->output[0]);
-}
-
/*
* Derived from information in smbios-wireless-ctl:
*
diff --git a/drivers/platform/x86/dell/dell-smbios-base.c b/drivers/platform/x86/dell/dell-smbios-base.c
index fbdd12a7cb8d..515c454acfe6 100644
--- a/drivers/platform/x86/dell/dell-smbios-base.c
+++ b/drivers/platform/x86/dell/dell-smbios-base.c
@@ -314,6 +314,31 @@ int dell_smbios_call(struct calling_interface_buffer *buffer)
}
EXPORT_SYMBOL_GPL(dell_smbios_call);

+void dell_fill_request(struct calling_interface_buffer *buffer,
+ u32 arg0, u32 arg1, u32 arg2, u32 arg3)
+{
+ memset(buffer, 0, sizeof(struct calling_interface_buffer));
+ buffer->input[0] = arg0;
+ buffer->input[1] = arg1;
+ buffer->input[2] = arg2;
+ buffer->input[3] = arg3;
+}
+EXPORT_SYMBOL_GPL(dell_fill_request);
+
+int dell_send_request(struct calling_interface_buffer *buffer,
+ u16 class, u16 select)
+{
+ int ret;
+
+ buffer->cmd_class = class;
+ buffer->cmd_select = select;
+ ret = dell_smbios_call(buffer);
+ if (ret != 0)
+ return ret;
+ return dell_smbios_error(buffer->output[0]);
+}
+EXPORT_SYMBOL_GPL(dell_send_request);
+
struct calling_interface_token *dell_smbios_find_token(int tokenid)
{
int i;
diff --git a/drivers/platform/x86/dell/dell-smbios.h b/drivers/platform/x86/dell/dell-smbios.h
index 756c354b1eef..1d6463cca12a 100644
--- a/drivers/platform/x86/dell/dell-smbios.h
+++ b/drivers/platform/x86/dell/dell-smbios.h
@@ -64,6 +64,11 @@ int dell_smbios_call_filter(struct device *d,
struct calling_interface_buffer *buffer);
int dell_smbios_call(struct calling_interface_buffer *buffer);

+void dell_fill_request(struct calling_interface_buffer *buffer,
+ u32 arg0, u32 arg1, u32 arg2, u32 arg3);
+int dell_send_request(struct calling_interface_buffer *buffer,
+ u16 class, u16 select);
+
struct calling_interface_token *dell_smbios_find_token(int tokenid);

enum dell_laptop_notifier_actions {
--
2.42.0


2024-05-29 17:50:25

by Lyndon Sanche

[permalink] [raw]
Subject: [PATCH v8 3/3] platform/x86: dell-pc: Implement platform_profile

Some Dell laptops support configuration of preset fan modes through
smbios tables.

If the platform supports these fan modes, set up platform_profile to
change these modes. If not supported, skip enabling platform_profile.

Signed-off-by: Lyndon Sanche <[email protected]>
---
MAINTAINERS | 6 +
drivers/platform/x86/dell/Kconfig | 13 +
drivers/platform/x86/dell/Makefile | 1 +
drivers/platform/x86/dell/dell-pc.c | 307 +++++++++++++++++++
drivers/platform/x86/dell/dell-smbios-base.c | 1 +
drivers/platform/x86/dell/dell-smbios.h | 1 +
6 files changed, 329 insertions(+)
create mode 100644 drivers/platform/x86/dell/dell-pc.c

diff --git a/MAINTAINERS b/MAINTAINERS
index d6c90161c7bf..09ff0dfd65cb 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -6116,6 +6116,12 @@ F: Documentation/ABI/obsolete/procfs-i8k
F: drivers/hwmon/dell-smm-hwmon.c
F: include/uapi/linux/i8k.h

+DELL PC DRIVER
+M: Lyndon Sanche <[email protected]>
+L: [email protected]
+S: Maintained
+F: drivers/platform/x86/dell/dell-pc.c
+
DELL REMOTE BIOS UPDATE DRIVER
M: Stuart Hayes <[email protected]>
L: [email protected]
diff --git a/drivers/platform/x86/dell/Kconfig b/drivers/platform/x86/dell/Kconfig
index 195a8bf532cc..85a78ef91182 100644
--- a/drivers/platform/x86/dell/Kconfig
+++ b/drivers/platform/x86/dell/Kconfig
@@ -91,6 +91,19 @@ config DELL_RBTN
To compile this driver as a module, choose M here: the module will
be called dell-rbtn.

+config DELL_PC
+ tristate "Dell PC Extras"
+ default m
+ depends on ACPI
+ depends on DMI
+ depends on DELL_SMBIOS
+ select ACPI_PLATFORM_PROFILE
+ help
+ This driver adds support for controlling the fan modes via platform_profile
+ on supported Dell systems regardless of formfactor.
+ Module will simply do nothing if thermal management commands are not
+ supported.
+
#
# The DELL_SMBIOS driver depends on ACPI_WMI and/or DCDBAS if those
# backends are selected. The "depends" line prevents a configuration
diff --git a/drivers/platform/x86/dell/Makefile b/drivers/platform/x86/dell/Makefile
index 8176a257d9c3..79d60f1bf4c1 100644
--- a/drivers/platform/x86/dell/Makefile
+++ b/drivers/platform/x86/dell/Makefile
@@ -9,6 +9,7 @@ obj-$(CONFIG_DCDBAS) += dcdbas.o
obj-$(CONFIG_DELL_LAPTOP) += dell-laptop.o
obj-$(CONFIG_DELL_RBTN) += dell-rbtn.o
obj-$(CONFIG_DELL_RBU) += dell_rbu.o
+obj-$(CONFIG_DELL_PC) += dell-pc.o
obj-$(CONFIG_DELL_SMBIOS) += dell-smbios.o
dell-smbios-objs := dell-smbios-base.o
dell-smbios-$(CONFIG_DELL_SMBIOS_WMI) += dell-smbios-wmi.o
diff --git a/drivers/platform/x86/dell/dell-pc.c b/drivers/platform/x86/dell/dell-pc.c
new file mode 100644
index 000000000000..a86ad921d4ee
--- /dev/null
+++ b/drivers/platform/x86/dell/dell-pc.c
@@ -0,0 +1,307 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Driver for Dell laptop extras
+ *
+ * Copyright (c) Lyndon Sanche <[email protected]>
+ *
+ * Based on documentation in the libsmbios package:
+ * Copyright (C) 2005-2014 Dell Inc.
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/err.h>
+#include <linux/dmi.h>
+#include <linux/bitfield.h>
+#include <linux/bits.h>
+#include <linux/platform_profile.h>
+#include <linux/slab.h>
+
+#include "dell-smbios.h"
+
+static const struct dmi_system_id dell_device_table[] __initconst = {
+ {
+ .ident = "Dell Inc.",
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
+ },
+ },
+ {
+ .ident = "Dell Computer Corporation",
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "Dell Computer Corporation"),
+ },
+ },
+ { }
+};
+MODULE_DEVICE_TABLE(dmi, dell_device_table);
+
+/* Derived from smbios-thermal-ctl
+ *
+ * cbClass 17
+ * cbSelect 19
+ * User Selectable Thermal Tables(USTT)
+ * cbArg1 determines the function to be performed
+ * cbArg1 0x0 = Get Thermal Information
+ * cbRES1 Standard return codes (0, -1, -2)
+ * cbRES2, byte 0 Bitmap of supported thermal modes. A mode is supported if
+ * its bit is set to 1
+ * Bit 0 Balanced
+ * Bit 1 Cool Bottom
+ * Bit 2 Quiet
+ * Bit 3 Performance
+ * cbRES2, byte 1 Bitmap of supported Active Acoustic Controller (AAC) modes.
+ * Each mode corresponds to the supported thermal modes in
+ * byte 0. A mode is supported if its bit is set to 1.
+ * Bit 0 AAC (Balanced)
+ * Bit 1 AAC (Cool Bottom
+ * Bit 2 AAC (Quiet)
+ * Bit 3 AAC (Performance)
+ * cbRes3, byte 0 Current Thermal Mode
+ * Bit 0 Balanced
+ * Bit 1 Cool Bottom
+ * Bit 2 Quiet
+ * Bit 3 Performanc
+ * cbRes3, byte 1 AAC Configuration type
+ * 0 Global (AAC enable/disable applies to all supported USTT modes)
+ * 1 USTT mode specific
+ * cbRes3, byte 2 Current Active Acoustic Controller (AAC) Mode
+ * If AAC Configuration Type is Global,
+ * 0 AAC mode disabled
+ * 1 AAC mode enabled
+ * If AAC Configuration Type is USTT mode specific (multiple bits may be set),
+ * Bit 0 AAC (Balanced)
+ * Bit 1 AAC (Cool Bottom
+ * Bit 2 AAC (Quiet)
+ * Bit 3 AAC (Performance)
+ * cbRes3, byte 3 Current Fan Failure Mode
+ * Bit 0 Minimal Fan Failure (at least one fan has failed, one fan working)
+ * Bit 1 Catastrophic Fan Failure (all fans have failed)
+ *
+ * cbArg1 0x1 (Set Thermal Information), both desired thermal mode and
+ * desired AAC mode shall be applied
+ * cbArg2, byte 0 Desired Thermal Mode to set
+ * (only one bit may be set for this parameter)
+ * Bit 0 Balanced
+ * Bit 1 Cool Bottom
+ * Bit 2 Quiet
+ * Bit 3 Performance
+ * cbArg2, byte 1 Desired Active Acoustic Controller (AAC) Mode to set
+ * If AAC Configuration Type is Global,
+ * 0 AAC mode disabled
+ * 1 AAC mode enabled
+ * If AAC Configuration Type is USTT mode specific
+ * (multiple bits may be set for this parameter),
+ * Bit 0 AAC (Balanced)
+ * Bit 1 AAC (Cool Bottom
+ * Bit 2 AAC (Quiet)
+ * Bit 3 AAC (Performance)
+ */
+
+#define DELL_ACC_GET_FIELD GENMASK(19, 16)
+#define DELL_ACC_SET_FIELD GENMASK(11, 8)
+#define DELL_THERMAL_SUPPORTED GENMASK(3, 0)
+
+static struct platform_profile_handler *thermal_handler;
+
+enum thermal_mode_bits {
+ DELL_BALANCED = BIT(0),
+ DELL_COOL_BOTTOM = BIT(1),
+ DELL_QUIET = BIT(2),
+ DELL_PERFORMANCE = BIT(3),
+};
+
+static int thermal_get_mode(void)
+{
+ struct calling_interface_buffer buffer;
+ int state;
+ int ret;
+
+ dell_fill_request(&buffer, 0x0, 0, 0, 0);
+ ret = dell_send_request(&buffer, CLASS_INFO, SELECT_THERMAL_MANAGEMENT);
+ if (ret)
+ return ret;
+ state = buffer.output[2];
+ if (state & DELL_BALANCED)
+ return DELL_BALANCED;
+ else if (state & DELL_COOL_BOTTOM)
+ return DELL_COOL_BOTTOM;
+ else if (state & DELL_QUIET)
+ return DELL_QUIET;
+ else if (state & DELL_PERFORMANCE)
+ return DELL_PERFORMANCE;
+ else
+ return -ENXIO;
+}
+
+static int thermal_get_supported_modes(int *supported_bits)
+{
+ struct calling_interface_buffer buffer;
+ int ret;
+
+ dell_fill_request(&buffer, 0x0, 0, 0, 0);
+ ret = dell_send_request(&buffer, CLASS_INFO, SELECT_THERMAL_MANAGEMENT);
+ /* Thermal function not supported */
+ if (ret == -ENXIO) {
+ *supported_bits = 0;
+ return 0;
+ }
+ if (ret)
+ return ret;
+ *supported_bits = FIELD_GET(DELL_THERMAL_SUPPORTED, buffer.output[1]);
+ return 0;
+}
+
+static int thermal_get_acc_mode(int *acc_mode)
+{
+ struct calling_interface_buffer buffer;
+ int ret;
+
+ dell_fill_request(&buffer, 0x0, 0, 0, 0);
+ ret = dell_send_request(&buffer, CLASS_INFO, SELECT_THERMAL_MANAGEMENT);
+ if (ret)
+ return ret;
+ *acc_mode = FIELD_GET(DELL_ACC_GET_FIELD, buffer.output[3]);
+ return 0;
+}
+
+static int thermal_set_mode(enum thermal_mode_bits state)
+{
+ struct calling_interface_buffer buffer;
+ int ret;
+ int acc_mode;
+
+ ret = thermal_get_acc_mode(&acc_mode);
+ if (ret)
+ return ret;
+
+ dell_fill_request(&buffer, 0x1, FIELD_PREP(DELL_ACC_SET_FIELD, acc_mode) | state, 0, 0);
+ return dell_send_request(&buffer, CLASS_INFO, SELECT_THERMAL_MANAGEMENT);
+}
+
+static int thermal_platform_profile_set(struct platform_profile_handler *pprof,
+ enum platform_profile_option profile)
+{
+ switch (profile) {
+ case PLATFORM_PROFILE_BALANCED:
+ return thermal_set_mode(DELL_BALANCED);
+ case PLATFORM_PROFILE_PERFORMANCE:
+ return thermal_set_mode(DELL_PERFORMANCE);
+ case PLATFORM_PROFILE_QUIET:
+ return thermal_set_mode(DELL_QUIET);
+ case PLATFORM_PROFILE_COOL:
+ return thermal_set_mode(DELL_COOL_BOTTOM);
+ default:
+ return -EOPNOTSUPP;
+ }
+}
+
+static int thermal_platform_profile_get(struct platform_profile_handler *pprof,
+ enum platform_profile_option *profile)
+{
+ int ret;
+
+ ret = thermal_get_mode();
+ if (ret < 0)
+ return ret;
+
+ switch (ret) {
+ case DELL_BALANCED:
+ *profile = PLATFORM_PROFILE_BALANCED;
+ break;
+ case DELL_PERFORMANCE:
+ *profile = PLATFORM_PROFILE_PERFORMANCE;
+ break;
+ case DELL_COOL_BOTTOM:
+ *profile = PLATFORM_PROFILE_COOL;
+ break;
+ case DELL_QUIET:
+ *profile = PLATFORM_PROFILE_QUIET;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int thermal_init(void)
+{
+ int ret;
+ int supported_modes;
+
+ /* If thermal commands are not supported, exit without error */
+ if (!dell_smbios_class_is_supported(CLASS_INFO))
+ return 0;
+
+ /* If thermal modes are not supported, exit without error */
+ ret = thermal_get_supported_modes(&supported_modes);
+ if (ret < 0)
+ return ret;
+ if (!supported_modes)
+ return 0;
+
+ thermal_handler = kzalloc(sizeof(*thermal_handler), GFP_KERNEL);
+ if (!thermal_handler)
+ return -ENOMEM;
+ thermal_handler->profile_get = thermal_platform_profile_get;
+ thermal_handler->profile_set = thermal_platform_profile_set;
+
+ if (supported_modes & DELL_QUIET)
+ set_bit(PLATFORM_PROFILE_QUIET, thermal_handler->choices);
+ if (supported_modes & DELL_COOL_BOTTOM)
+ set_bit(PLATFORM_PROFILE_COOL, thermal_handler->choices);
+ if (supported_modes & DELL_BALANCED)
+ set_bit(PLATFORM_PROFILE_BALANCED, thermal_handler->choices);
+ if (supported_modes & DELL_PERFORMANCE)
+ set_bit(PLATFORM_PROFILE_PERFORMANCE, thermal_handler->choices);
+
+ /* Clean up if failed */
+ ret = platform_profile_register(thermal_handler);
+ if (ret)
+ kfree(thermal_handler);
+
+ return ret;
+}
+
+static void thermal_cleanup(void)
+{
+ if (thermal_handler) {
+ platform_profile_remove();
+ kfree(thermal_handler);
+ }
+}
+
+static int __init dell_init(void)
+{
+ int ret;
+
+ if (!dmi_check_system(dell_device_table))
+ return -ENODEV;
+
+ /* Do not fail module if thermal modes not supported, just skip */
+ ret = thermal_init();
+ if (ret)
+ goto fail_thermal;
+
+ return 0;
+
+fail_thermal:
+ thermal_cleanup();
+ return ret;
+}
+
+static void __exit dell_exit(void)
+{
+ thermal_cleanup();
+}
+
+module_init(dell_init);
+module_exit(dell_exit);
+
+MODULE_AUTHOR("Lyndon Sanche <[email protected]>");
+MODULE_DESCRIPTION("Dell PC driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/platform/x86/dell/dell-smbios-base.c b/drivers/platform/x86/dell/dell-smbios-base.c
index 515c454acfe6..d61b33d5af95 100644
--- a/drivers/platform/x86/dell/dell-smbios-base.c
+++ b/drivers/platform/x86/dell/dell-smbios-base.c
@@ -71,6 +71,7 @@ static struct smbios_call call_blacklist[] = {
/* handled by kernel: dell-laptop */
{0x0000, CLASS_INFO, SELECT_RFKILL},
{0x0000, CLASS_KBD_BACKLIGHT, SELECT_KBD_BACKLIGHT},
+ {0x0000, CLASS_INFO, SELECT_THERMAL_MANAGEMENT},
};

struct token_range {
diff --git a/drivers/platform/x86/dell/dell-smbios.h b/drivers/platform/x86/dell/dell-smbios.h
index 1d6463cca12a..ea0cc38642a2 100644
--- a/drivers/platform/x86/dell/dell-smbios.h
+++ b/drivers/platform/x86/dell/dell-smbios.h
@@ -19,6 +19,7 @@
/* Classes and selects used only in kernel drivers */
#define CLASS_KBD_BACKLIGHT 4
#define SELECT_KBD_BACKLIGHT 11
+#define SELECT_THERMAL_MANAGEMENT 19

/* Tokens used in kernel drivers, any of these
* should be filtered from userspace access
--
2.42.0


2024-05-30 08:39:59

by Ilpo Järvinen

[permalink] [raw]
Subject: Re: [PATCH v8 3/3] platform/x86: dell-pc: Implement platform_profile

On Wed, 29 May 2024, Lyndon Sanche wrote:

> Some Dell laptops support configuration of preset fan modes through
> smbios tables.
>
> If the platform supports these fan modes, set up platform_profile to
> change these modes. If not supported, skip enabling platform_profile.
>
> Signed-off-by: Lyndon Sanche <[email protected]>
> ---
> MAINTAINERS | 6 +
> drivers/platform/x86/dell/Kconfig | 13 +
> drivers/platform/x86/dell/Makefile | 1 +
> drivers/platform/x86/dell/dell-pc.c | 307 +++++++++++++++++++
> drivers/platform/x86/dell/dell-smbios-base.c | 1 +
> drivers/platform/x86/dell/dell-smbios.h | 1 +
> 6 files changed, 329 insertions(+)
> create mode 100644 drivers/platform/x86/dell/dell-pc.c
>
> diff --git a/MAINTAINERS b/MAINTAINERS
> index d6c90161c7bf..09ff0dfd65cb 100644
> --- a/MAINTAINERS
> +++ b/MAINTAINERS
> @@ -6116,6 +6116,12 @@ F: Documentation/ABI/obsolete/procfs-i8k
> F: drivers/hwmon/dell-smm-hwmon.c
> F: include/uapi/linux/i8k.h
>
> +DELL PC DRIVER
> +M: Lyndon Sanche <[email protected]>
> +L: [email protected]
> +S: Maintained
> +F: drivers/platform/x86/dell/dell-pc.c
> +
> DELL REMOTE BIOS UPDATE DRIVER
> M: Stuart Hayes <[email protected]>
> L: [email protected]
> diff --git a/drivers/platform/x86/dell/Kconfig b/drivers/platform/x86/dell/Kconfig
> index 195a8bf532cc..85a78ef91182 100644
> --- a/drivers/platform/x86/dell/Kconfig
> +++ b/drivers/platform/x86/dell/Kconfig
> @@ -91,6 +91,19 @@ config DELL_RBTN
> To compile this driver as a module, choose M here: the module will
> be called dell-rbtn.
>
> +config DELL_PC
> + tristate "Dell PC Extras"
> + default m
> + depends on ACPI
> + depends on DMI
> + depends on DELL_SMBIOS
> + select ACPI_PLATFORM_PROFILE
> + help
> + This driver adds support for controlling the fan modes via platform_profile
> + on supported Dell systems regardless of formfactor.
> + Module will simply do nothing if thermal management commands are not
> + supported.
> +
> #
> # The DELL_SMBIOS driver depends on ACPI_WMI and/or DCDBAS if those
> # backends are selected. The "depends" line prevents a configuration
> diff --git a/drivers/platform/x86/dell/Makefile b/drivers/platform/x86/dell/Makefile
> index 8176a257d9c3..79d60f1bf4c1 100644
> --- a/drivers/platform/x86/dell/Makefile
> +++ b/drivers/platform/x86/dell/Makefile
> @@ -9,6 +9,7 @@ obj-$(CONFIG_DCDBAS) += dcdbas.o
> obj-$(CONFIG_DELL_LAPTOP) += dell-laptop.o
> obj-$(CONFIG_DELL_RBTN) += dell-rbtn.o
> obj-$(CONFIG_DELL_RBU) += dell_rbu.o
> +obj-$(CONFIG_DELL_PC) += dell-pc.o
> obj-$(CONFIG_DELL_SMBIOS) += dell-smbios.o
> dell-smbios-objs := dell-smbios-base.o
> dell-smbios-$(CONFIG_DELL_SMBIOS_WMI) += dell-smbios-wmi.o
> diff --git a/drivers/platform/x86/dell/dell-pc.c b/drivers/platform/x86/dell/dell-pc.c
> new file mode 100644
> index 000000000000..a86ad921d4ee
> --- /dev/null
> +++ b/drivers/platform/x86/dell/dell-pc.c
> @@ -0,0 +1,307 @@
> +// SPDX-License-Identifier: GPL-2.0-only
> +/*
> + * Driver for Dell laptop extras
> + *
> + * Copyright (c) Lyndon Sanche <[email protected]>
> + *
> + * Based on documentation in the libsmbios package:
> + * Copyright (C) 2005-2014 Dell Inc.
> + */
> +
> +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
> +
> +#include <linux/module.h>
> +#include <linux/kernel.h>
> +#include <linux/init.h>
> +#include <linux/err.h>
> +#include <linux/dmi.h>
> +#include <linux/bitfield.h>
> +#include <linux/bits.h>
> +#include <linux/platform_profile.h>
> +#include <linux/slab.h>

Thanks for the update. I've now applied this into review-ilpo branch.

I reordered those headers into alphabetical order while applying. In
future, when adding new headers, try adhere to the alphabetical order.

--
i.


2024-05-31 01:20:00

by Lyndon Sanche

[permalink] [raw]
Subject: Re: [PATCH v8 3/3] platform/x86: dell-pc: Implement platform_profile



On Thu, May 30 2024 at 11:39:27 AM +03:00:00, Ilpo J?rvinen
<[email protected]> wrote:
> Thanks for the update. I've now applied this into review-ilpo branch.
>
> I reordered those headers into alphabetical order while applying. In
> future, when adding new headers, try adhere to the alphabetical order.
>
> --
> i.

Thank you for taking the time to review. Also thank you for letting me
know about the header order, I will note that for next time.

Please let me know if you need anything else on my end.

Thank you,

Lyndon Sanche