All of lore.kernel.org
 help / color / mirror / Atom feed
From: Lyndon Sanche <lsanche@lyndeno.ca>
To: lsanche@lyndeno.ca
Cc: mario.limonciello@amd.com, pali@kernel.org, W_Armin@gmx.de,
	srinivas.pandruvada@linux.intel.com,
	ilpo.jarvinen@linux.intel.com, lkp@intel.com,
	hdegoede@redhat.com, Yijun.Shen@dell.com,
	Matthew Garrett <mjg59@srcf.ucam.org>,
	Vegard Nossum <vegard.nossum@oracle.com>,
	Jonathan Corbet <corbet@lwn.net>,
	Heiner Kallweit <hkallweit1@gmail.com>,
	linux-kernel@vger.kernel.org,
	platform-driver-x86@vger.kernel.org, Dell.Client.Kernel@dell.com
Subject: [PATCH v7 3/3] platform/x86: dell-pc: Implement platform_profile
Date: Fri, 17 May 2024 16:42:36 -0600	[thread overview]
Message-ID: <20240517224323.10045-4-lsanche@lyndeno.ca> (raw)
In-Reply-To: <20240517224323.10045-1-lsanche@lyndeno.ca>

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 <lsanche@lyndeno.ca>
---
 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 <lsanche@lyndeno.ca>
+L:	platform-driver-x86@vger.kernel.org
+S:	Maintained
+F:	drivers/platform/x86/dell/dell-pc.c
+
 DELL REMOTE BIOS UPDATE DRIVER
 M:	Stuart Hayes <stuart.w.hayes@gmail.com>
 L:	platform-driver-x86@vger.kernel.org
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 <lsanche@lyndeno.ca>
+ *
+ *  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 <lsanche@lyndeno.ca>");
+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


  parent reply	other threads:[~2024-05-17 22:44 UTC|newest]

Thread overview: 80+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2024-04-25 17:27 [PATCH] platform/x86: dell-laptop: Implement platform_profile Lyndon Sanche
2024-04-25 20:07 ` Mario Limonciello
2024-04-25 20:24   ` Lyndon Sanche
2024-04-25 20:28     ` Mario Limonciello
2024-04-25 21:51       ` Srinivas Pandruvada
2024-04-26  0:38         ` Lyndon Sanche
2024-04-26 16:14     ` srinivas pandruvada
2024-04-26 18:23       ` Lyndon Sanche
2024-04-26 18:24         ` srinivas pandruvada
2024-04-25 20:12 ` Pali Rohár
2024-04-25 20:27   ` Lyndon Sanche
2024-04-25 20:31     ` Pali Rohár
2024-04-25 21:07 ` Armin Wolf
2024-04-26  0:54   ` Lyndon Sanche
2024-04-26  2:04 ` [PATCH v2] " Lyndon Sanche
2024-04-26  9:23   ` Ilpo Järvinen
2024-04-26 18:05     ` Lyndon Sanche
2024-05-13 20:09   ` kernel test robot
2024-04-26  6:57 ` [PATCH] " Ilpo Järvinen
2024-04-29 16:48 ` [PATCH v3] " Lyndon Sanche
2024-04-29 17:45   ` Mario Limonciello
2024-04-29 17:51     ` Mario Limonciello
2024-04-29 21:25       ` Lyndon Sanche
2024-04-29 21:21     ` Lyndon Sanche
2024-04-30 10:31   ` Ilpo Järvinen
2024-04-30 18:38     ` Lyndon Sanche
2024-04-30 15:36   ` kernel test robot
2024-05-01  8:16   ` kernel test robot
2024-05-01 16:35   ` kernel test robot
2024-05-01 17:07   ` kernel test robot
2024-05-01  1:14 ` [PATCH v4] " Lyndon Sanche
2024-05-01  1:36   ` Pali Rohár
2024-05-01  1:42     ` Lyndon Sanche
2024-05-01 21:58 ` [PATCH v5] " Lyndon Sanche
2024-05-03 10:19   ` kernel test robot
2024-05-04  1:03     ` Lyndon Sanche
2024-05-06 10:18       ` Hans de Goede
2024-05-07 16:00         ` Lyndon Sanche
2024-05-03 21:19   ` Armin Wolf
2024-05-04  0:59     ` Lyndon Sanche
2024-05-08 14:24   ` Shen, Yijun
2024-05-08 15:53     ` Mario Limonciello
2024-05-11 15:05       ` Shen, Yijun
2024-05-11 15:12         ` Limonciello, Mario
2024-05-11 15:56           ` Shen, Yijun
2024-05-12 17:53             ` Armin Wolf
2024-05-12 17:58               ` Limonciello, Mario
2024-05-12 18:47                 ` Armin Wolf
2024-05-12 22:14                   ` Limonciello, Mario
2024-05-11 16:02         ` Lyndon Sanche
2024-05-09 15:10     ` Lyndon Sanche
2024-05-11  1:49       ` Lyndon Sanche
2024-05-11 15:22         ` Shen, Yijun
2024-05-11 15:54           ` Lyndon Sanche
2024-05-11 16:12             ` Shen, Yijun
2024-05-11  2:36 ` [PATCH v6 0/2] " Lyndon Sanche
2024-05-11  2:36 ` [PATCH v6 1/2] platform/x86: dell-smbios: Add helper for checking supported commands Lyndon Sanche
2024-05-11 15:13   ` Limonciello, Mario
2024-05-12 18:00   ` Armin Wolf
2024-05-11  2:36 ` [PATCH v6 2/2] platform/x86: dell-laptop: Implement platform_profile Lyndon Sanche
2024-05-11 15:16   ` Limonciello, Mario
2024-05-11 15:59     ` Lyndon Sanche
     [not found]       ` <48JCDS.E4RT1F9DTKFU1@lyndeno.ca>
2024-05-12  1:43         ` Limonciello, Mario
2024-05-12 15:25           ` Hans de Goede
2024-05-12  0:14     ` Lyndon Sanche
2024-05-12 18:05   ` Armin Wolf
2024-05-15 17:06     ` Lyndon Sanche
2024-05-17 22:42 ` [PATCH v7 0/3] platform/x86: dell: " Lyndon Sanche
2024-05-17 22:42   ` [PATCH v7 1/3] platform/x86: dell-smbios: Add helper for checking supported class Lyndon Sanche
2024-05-17 22:42   ` [PATCH v7 2/3] platform/x86: dell-smbios: Move request functions for reuse Lyndon Sanche
2024-05-17 22:42   ` Lyndon Sanche [this message]
2024-05-27  9:39     ` [PATCH v7 3/3] platform/x86: dell-pc: Implement platform_profile Ilpo Järvinen
2024-05-28 16:16       ` Lyndon Sanche
2024-05-21 20:50   ` [PATCH v7 0/3] platform/x86: dell: " Mario Limonciello
2024-05-29 17:47 ` [PATCH v8 " Lyndon Sanche
2024-05-29 17:47   ` [PATCH v8 1/3] platform/x86: dell-smbios: Add helper for checking supported class Lyndon Sanche
2024-05-29 17:47   ` [PATCH v8 2/3] platform/x86: dell-smbios: Move request functions for reuse Lyndon Sanche
2024-05-29 17:47   ` [PATCH v8 3/3] platform/x86: dell-pc: Implement platform_profile Lyndon Sanche
2024-05-30  8:39     ` Ilpo Järvinen
2024-05-31  1:19       ` Lyndon Sanche

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20240517224323.10045-4-lsanche@lyndeno.ca \
    --to=lsanche@lyndeno.ca \
    --cc=Dell.Client.Kernel@dell.com \
    --cc=W_Armin@gmx.de \
    --cc=Yijun.Shen@dell.com \
    --cc=corbet@lwn.net \
    --cc=hdegoede@redhat.com \
    --cc=hkallweit1@gmail.com \
    --cc=ilpo.jarvinen@linux.intel.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=lkp@intel.com \
    --cc=mario.limonciello@amd.com \
    --cc=mjg59@srcf.ucam.org \
    --cc=pali@kernel.org \
    --cc=platform-driver-x86@vger.kernel.org \
    --cc=srinivas.pandruvada@linux.intel.com \
    --cc=vegard.nossum@oracle.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.