From: Mark Pearson <markpearson@lenovo.com>
To: <markpearson@lenovo.com>
Cc: <rjw@rjwysocki.net>, <hdegoede@redhat.com>,
<mgross@linux.intel.com>, <linux-acpi@vger.kernel.org>,
<mario.limonciello@dell.com>, <eliadevito@gmail.com>,
<hadess@hadess.net>, <bberg@redhat.com>,
<platform-driver-x86@vger.kernel.org>, <dvhart@infradead.org>
Subject: [PATCH 2/3] ACPI: platform-profile: Add platform profile support
Date: Mon, 9 Nov 2020 22:31:23 -0500 [thread overview]
Message-ID: <20201110033124.3211-3-markpearson@lenovo.com> (raw)
In-Reply-To: <20201110033124.3211-1-markpearson@lenovo.com>
This is the initial implementation of the platform-profile feature.
It provides the details discussed and outlined in the
sysfs-platform_profile document.
Many modern systems have the ability to modify the operating profile to
control aspects like fan speed, temperature and power levels. This
module provides a common sysfs interface that platform modules can register
against to control their individual profile options.
Signed-off-by: Mark Pearson <markpearson@lenovo.com>
---
MAINTAINERS | 8 ++
drivers/acpi/Kconfig | 19 ++++
drivers/acpi/Makefile | 1 +
drivers/acpi/platform_profile.c | 172 +++++++++++++++++++++++++++++++
include/linux/platform_profile.h | 36 +++++++
5 files changed, 236 insertions(+)
create mode 100644 drivers/acpi/platform_profile.c
create mode 100644 include/linux/platform_profile.h
diff --git a/MAINTAINERS b/MAINTAINERS
index 9a54806ebf02..e731ac1c4447 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -436,6 +436,14 @@ S: Orphan
F: drivers/platform/x86/wmi.c
F: include/uapi/linux/wmi.h
+ACPI PLATFORM PROFILE DRIVER
+M: Mark Pearson <markpearons@lenovo.com>
+L: linux-acpi@vger.kernel.org
+S: Supported
+W: https://01.org/linux-acpi
+B: https://bugzilla.kernel.org
+F: drivers/acpi/platform_profile.c
+
AD1889 ALSA SOUND DRIVER
L: linux-parisc@vger.kernel.org
S: Maintained
diff --git a/drivers/acpi/Kconfig b/drivers/acpi/Kconfig
index 7540a5179a47..b10a8e0863cf 100644
--- a/drivers/acpi/Kconfig
+++ b/drivers/acpi/Kconfig
@@ -601,3 +601,22 @@ config X86_PM_TIMER
You should nearly always say Y here because many modern
systems require this timer.
+
+config ACPI_PLATFORM_PROFILE
+ tristate "ACPI Platform Profile Driver"
+ default y
+ help
+ This driver adds support for platform-profiles on platforms that
+ support it.
+
+ Platform-profiles can be used to control the platform behaviour. For
+ example whether to operate in a lower power mode, in a higher
+ power performance mode or between the two.
+
+ This driver provides the sysfs interface and is used as the registration
+ point for platform specific drivers.
+
+ Which profiles are supported is determined on a per-platform basis and
+ should be obtained from the platform specific driver.
+
+
diff --git a/drivers/acpi/Makefile b/drivers/acpi/Makefile
index 9a957544e357..82dbdc0300ed 100644
--- a/drivers/acpi/Makefile
+++ b/drivers/acpi/Makefile
@@ -93,6 +93,7 @@ obj-$(CONFIG_ACPI_CPPC_LIB) += cppc_acpi.o
obj-$(CONFIG_ACPI_SPCR_TABLE) += spcr.o
obj-$(CONFIG_ACPI_DEBUGGER_USER) += acpi_dbg.o
obj-$(CONFIG_ACPI_PPTT) += pptt.o
+obj-$(CONFIG_ACPI_PLATFORM_PROFILE) += platform_profile.o
# processor has its own "processor." module_param namespace
processor-y := processor_driver.o
diff --git a/drivers/acpi/platform_profile.c b/drivers/acpi/platform_profile.c
new file mode 100644
index 000000000000..3c460c0a3857
--- /dev/null
+++ b/drivers/acpi/platform_profile.c
@@ -0,0 +1,172 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+/*
+ * platform_profile.c - Platform profile sysfs interface
+ */
+
+#include <linux/module.h>
+#include <linux/printk.h>
+#include <linux/kobject.h>
+#include <linux/sysfs.h>
+#include <linux/init.h>
+#include <linux/fs.h>
+#include <linux/string.h>
+#include <linux/device.h>
+#include <linux/acpi.h>
+#include <linux/mutex.h>
+#include <acpi/acpi_bus.h>
+#include <linux/platform_profile.h>
+
+struct platform_profile *cur_profile;
+DEFINE_MUTEX(profile_lock);
+
+/* Ensure the first char of each profile is unique */
+static char *profile_str[] = {
+ "Low-power",
+ "Cool",
+ "Quiet",
+ "Balance",
+ "Performance",
+ "Unknown"
+};
+
+static ssize_t platform_profile_choices_show(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ int i;
+ int ret, count = 0;
+
+ mutex_lock(&profile_lock);
+ if (!cur_profile) {
+ mutex_unlock(&profile_lock);
+ return -ENODEV;
+ }
+
+ if (!cur_profile->choices) {
+ mutex_unlock(&profile_lock);
+ return snprintf(buf, PAGE_SIZE, "None");
+ }
+
+ for (i = profile_low; i < profile_unknown; i++) {
+ if (cur_profile->choices & (1 << i)) {
+ ret = snprintf(buf+count, PAGE_SIZE, "%s ", profile_str[i]);
+ if (ret < 0)
+ break;
+ count += ret;
+ }
+ }
+ mutex_unlock(&profile_lock);
+ return count;
+}
+
+static ssize_t platform_profile_show(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ enum profile_option profile = profile_unknown;
+
+ mutex_lock(&profile_lock);
+ if (!cur_profile) {
+ mutex_unlock(&profile_lock);
+ return -ENODEV;
+ }
+ if (cur_profile->profile_get)
+ profile = cur_profile->profile_get();
+ mutex_unlock(&profile_lock);
+
+ return snprintf(buf, PAGE_SIZE, "%s", profile_str[profile]);
+}
+
+static ssize_t platform_profile_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ enum profile_option profile;
+
+ mutex_lock(&profile_lock);
+ if (!cur_profile) {
+ mutex_unlock(&profile_lock);
+ return -ENODEV;
+ }
+
+ /* Scan for a matching profile */
+ for (profile = profile_low; profile < profile_unknown; profile++) {
+ if (toupper(buf[0]) == profile_str[profile][0])
+ break;
+ }
+ if (profile == profile_unknown) {
+ mutex_unlock(&profile_lock);
+ return -EINVAL;
+ }
+
+ if (cur_profile->profile_set)
+ cur_profile->profile_set(profile);
+
+ mutex_unlock(&profile_lock);
+ return count;
+}
+
+static DEVICE_ATTR_RO(platform_profile_choices);
+static DEVICE_ATTR_RW(platform_profile);
+
+static struct attribute *platform_profile_attributes[] = {
+ &dev_attr_platform_profile_choices.attr,
+ &dev_attr_platform_profile.attr,
+ NULL,
+};
+
+static const struct attribute_group platform_profile_attr_group = {
+ .attrs = platform_profile_attributes,
+};
+
+int platform_profile_notify(void)
+{
+ if (!cur_profile)
+ return -ENODEV;
+ sysfs_notify(acpi_kobj, NULL, "platform_profile");
+ return 0;
+}
+EXPORT_SYMBOL_GPL(platform_profile_notify);
+
+int platform_profile_register(struct platform_profile *pprof)
+{
+ mutex_lock(&profile_lock);
+ /* We can only have one active profile */
+ if (cur_profile) {
+ mutex_unlock(&profile_lock);
+ return -EEXIST;
+ }
+ cur_profile = pprof;
+ mutex_unlock(&profile_lock);
+ return sysfs_create_group(acpi_kobj, &platform_profile_attr_group);
+}
+EXPORT_SYMBOL_GPL(platform_profile_register);
+
+int platform_profile_unregister(void)
+{
+ mutex_lock(&profile_lock);
+ sysfs_remove_group(acpi_kobj, &platform_profile_attr_group);
+ cur_profile = NULL;
+ mutex_unlock(&profile_lock);
+ return 0;
+}
+EXPORT_SYMBOL_GPL(platform_profile_unregister);
+
+static int __init platform_profile_init(void)
+{
+ cur_profile = NULL;
+ return 0;
+}
+
+static void platform_profile_exit(void)
+{
+ sysfs_remove_group(acpi_kobj, &platform_profile_attr_group);
+ cur_profile = NULL;
+}
+
+MODULE_AUTHOR("Mark Pearson <markpearson@lenovo.com>");
+MODULE_LICENSE("GPL");
+
+module_init(platform_profile_init);
+module_exit(platform_profile_exit);
diff --git a/include/linux/platform_profile.h b/include/linux/platform_profile.h
new file mode 100644
index 000000000000..347a12172c09
--- /dev/null
+++ b/include/linux/platform_profile.h
@@ -0,0 +1,36 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * platform_profile.h - platform profile sysfs interface
+ *
+ * See Documentation/ABI/testing/sysfs-platform_profile for more information.
+ */
+
+#ifndef _PLATFORM_PROFILE_H_
+#define _PLATFORM_PROFILE_H_
+
+/*
+ * If more options are added please update profile_str
+ * array in platform-profile.c
+ */
+
+enum profile_option {
+ profile_low,
+ profile_cool,
+ profile_quiet,
+ profile_balance,
+ profile_perform,
+ profile_unknown /* Must always be last */
+};
+
+struct platform_profile {
+ unsigned int choices; /* bitmap of available choices */
+ int cur_profile; /* Current active profile */
+ int (*profile_get)(void);
+ int (*profile_set)(int profile);
+};
+
+extern int platform_profile_register(struct platform_profile *pprof);
+extern int platform_profile_unregister(void);
+extern int platform_profile_notify(void);
+
+#endif /*_PLATFORM_PROFILE_H_*/
--
2.28.0
next prev parent reply other threads:[~2020-11-10 3:32 UTC|newest]
Thread overview: 17+ messages / expand[flat|nested] mbox.gz Atom feed top
2020-11-10 3:31 [PATCH 0/3] Platform Profile support Mark Pearson
2020-11-10 3:31 ` [PATCH 1/3] Documentation: Add documentation for new platform_profile sysfs attribute Mark Pearson
2020-11-10 10:03 ` Andy Shevchenko
2020-11-10 14:09 ` [External] " Mark Pearson
2020-11-10 3:31 ` Mark Pearson [this message]
2020-11-10 10:15 ` [PATCH 2/3] ACPI: platform-profile: Add platform profile support Barnabás Pőcze
2020-11-10 14:32 ` [External] " Mark Pearson
2020-11-10 23:48 ` Barnabás Pőcze
2020-11-11 10:29 ` Hans de Goede
2020-11-10 10:26 ` Andy Shevchenko
2020-11-10 14:39 ` [External] " Mark Pearson
2020-11-10 12:53 ` Rafael J. Wysocki
2020-11-10 14:40 ` [External] " Mark Pearson
2020-11-10 3:31 ` [PATCH 3/3] platform/x86: thinkpad_acpi: " Mark Pearson
2020-11-10 10:06 ` Andy Shevchenko
2020-11-10 14:41 ` [External] " Mark Pearson
2020-11-19 16:37 ` [PATCH 0/3] Platform Profile support Bastien Nocera
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=20201110033124.3211-3-markpearson@lenovo.com \
--to=markpearson@lenovo.com \
--cc=bberg@redhat.com \
--cc=dvhart@infradead.org \
--cc=eliadevito@gmail.com \
--cc=hadess@hadess.net \
--cc=hdegoede@redhat.com \
--cc=linux-acpi@vger.kernel.org \
--cc=mario.limonciello@dell.com \
--cc=mgross@linux.intel.com \
--cc=platform-driver-x86@vger.kernel.org \
--cc=rjw@rjwysocki.net \
/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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox