From patchwork Tue Oct 27 16:42:19 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Mark Pearson X-Patchwork-Id: 292062 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-12.8 required=3.0 tests=BAYES_00, HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_PATCH, MAILING_LIST_MULTI, SIGNED_OFF_BY, SPF_HELO_NONE,SPF_PASS,URIBL_BLOCKED,USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 1709BC388F9 for ; Tue, 27 Oct 2020 16:42:54 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id C6FCA218AC for ; Tue, 27 Oct 2020 16:42:53 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1811850AbgJ0Qmw (ORCPT ); Tue, 27 Oct 2020 12:42:52 -0400 Received: from mail1.bemta24.messagelabs.com ([67.219.250.116]:24365 "EHLO mail1.bemta24.messagelabs.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1811836AbgJ0Qmu (ORCPT ); Tue, 27 Oct 2020 12:42:50 -0400 Received: from [100.112.135.1] (using TLSv1.2 with cipher DHE-RSA-AES256-GCM-SHA384 (256 bits)) by server-5.bemta.az-b.us-west-2.aws.symcld.net id 06/B9-42875-70E489F5; Tue, 27 Oct 2020 16:42:47 +0000 X-Brightmail-Tracker: H4sIAAAAAAAAA+NgFuplleJIrShJLcpLzFFi42JJl3vFpsvuNyP eYMFWUYv91yUsuhYaWCy8f4rV4uu32+wWb45PZ7JYvq+f0eLyrjlsFp97jzBaNHU2AVkdk1ks Vu95wezA7TFp5gxmj52z7rJ7/Nq2hsVj8wotj3knAz3e77vK5vF5k1wAexRrZl5SfkUCa8aZs 5IFX5UqFt7KamB8ItvFyMUhJPCfUeLZ8cWMXYycQM4bRomXG4tAbDYBbYktW36xdTFycIgIyE h8WOsJEmYW2MskseNvCogtLBAl8f1JDwuIzSKgKvFt2142EJtXwEbi0KxnYCMlBOQlnvYuZwa xOYFqznQ9ZoFYpSJx/8ESqHpBiZMzn7BAzJeXaN46mxnClpA4+OIFM8QcBYlvd78xQdgJEste 3mGewCgwC0n7LCTts5C0L2BkXsVollSUmZ5RkpuYmaNraGCga2hopGtobKRroZdYpZukV1qsW 55aXKJrpJdYXqxXXJmbnJOil5dasokRGEspBS0cOxgPv/6gd4hRkoNJSZR3iceMeCG+pPyUyo zE4oz4otKc1OJDjDIcHEoSvNo+QDnBotT01Iq0zBxgXMOkJTh4lER4J4KkeYsLEnOLM9MhUqc YFaXEedeDJARAEhmleXBtsFRyiVFWSpiXkYGBQYinILUoN7MEVf4VozgHo5Iw73uQKTyZeSVw 018BLWYCWtxWMQVkcUkiQkqqgcn59Gm9FSua+vveO7mYvo+/91DQvyVvwZTpfzdl/X74vu/vr Orgx6mu6+pPy37e3RMQuXj73KVfHi3dXrA2ZbHR5mlJz84//3krcR/7jC1PD15u3K5boKJ5Me Dt0nPXplsozH9WMslVuZt9ckdOgO2NS+ImqQcebKqcnsE2w1xJbM5m17Cj8615Drkff6GUFVh 4efKqlVz9+huuMczfV/coQyPy+ppXU2bPU883U8na5tHQ9G3Ts2W/qx7l+keazb+b5lSZ7xv+ Iz1Xx1sgMGOn16Uz+otM3gt+XVlf8P7bPkapCdk5V3e/f8grV+sQHige5vFvsUSE5dqwhF0tK 1j177qv3PM04lVuKZPn5CUiSizFGYmGWsxFxYkA1pxFwqADAAA= X-Env-Sender: markpearson@lenovo.com X-Msg-Ref: server-3.tower-355.messagelabs.com!1603816965!7460!1 X-Originating-IP: [103.30.234.6] X-SYMC-ESS-Client-Auth: outbound-route-from=pass X-StarScan-Received: X-StarScan-Version: 9.60.3; banners=-,-,- X-VirusChecked: Checked Received: (qmail 16068 invoked from network); 27 Oct 2020 16:42:47 -0000 Received: from unknown (HELO lenovo.com) (103.30.234.6) by server-3.tower-355.messagelabs.com with ECDHE-RSA-AES256-GCM-SHA384 encrypted SMTP; 27 Oct 2020 16:42:47 -0000 Received: from reswpmail04.lenovo.com (unknown [10.62.32.23]) (using TLSv1.2 with cipher AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by Forcepoint Email with ESMTPS id 7B7A14184040F8AEE639; Wed, 28 Oct 2020 00:42:42 +0800 (CST) Received: from localhost.localdomain.com (10.64.85.148) by reswpmail04.lenovo.com (10.62.32.23) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.1.2044.4; Tue, 27 Oct 2020 09:42:37 -0700 From: Mark Pearson To: CC: , , , , , , , , , , Hans de Goede Subject: [PATCH] Documentation: Add documentation for new platform_profile sysfs attribute Date: Tue, 27 Oct 2020 12:42:19 -0400 Message-ID: <20201027164219.868839-1-markpearson@lenovo.com> X-Mailer: git-send-email 2.28.0 In-Reply-To: References: MIME-Version: 1.0 X-Originating-IP: [10.64.85.148] X-ClientProxiedBy: reswpmail04.lenovo.com (10.62.32.23) To reswpmail04.lenovo.com (10.62.32.23) Precedence: bulk List-ID: X-Mailing-List: linux-acpi@vger.kernel.org From: Hans de Goede On modern systems the platform performance, temperature, fan and other hardware related characteristics are often dynamically configurable. The profile is often automatically adjusted to the load by somei automatic-mechanism (which may very well live outside the kernel). These auto platform-adjustment mechanisms often can be configured with one of several 'platform-profiles', with either a bias towards low-power consumption or towards performance (and higher power consumption and thermals). Introduce a new platform_profile sysfs API which offers a generic API for selecting the performance-profile of these automatic-mechanisms. Co-developed-by: Mark Pearson Signed-off-by: Mark Pearson Signed-off-by: Hans de Goede --- Changes in V1: - Moved from RFC to proposed patch - Added cool profile as requested - removed extra-profiles as no longer relevant .../ABI/testing/sysfs-platform_profile | 66 +++++++++++++++++++ 1 file changed, 66 insertions(+) create mode 100644 Documentation/ABI/testing/sysfs-platform_profile diff --git a/Documentation/ABI/testing/sysfs-platform_profile b/Documentation/ABI/testing/sysfs-platform_profile new file mode 100644 index 000000000000..240bd3d7532b --- /dev/null +++ b/Documentation/ABI/testing/sysfs-platform_profile @@ -0,0 +1,66 @@ +Platform-profile selection (e.g. /sys/firmware/acpi/platform_profile) + +On modern systems the platform performance, temperature, fan and other +hardware related characteristics are often dynamically configurable. The +profile is often automatically adjusted to the load by some +automatic-mechanism (which may very well live outside the kernel). + +These auto platform-adjustment mechanisms often can be configured with +one of several 'platform-profiles', with either a bias towards low-power +consumption or towards performance (and higher power consumption and +thermals). + +The purpose of the platform_profile attribute is to offer a generic sysfs +API for selecting the platform-profile of these automatic-mechanisms. + +Note that this API is only for selecting the platform-profile, it is +NOT a goal of this API to allow monitoring the resulting performance +characteristics. Monitoring performance is best done with device/vendor +specific tools such as e.g. turbostat. + +Specifically when selecting a high-performance profile the actual achieved +performance may be limited by various factors such as: the heat generated +by other components, room temperature, free air flow at the bottom of a +laptop, etc. It is explicitly NOT a goal of this API to let userspace know +about any sub-optimal conditions which are impeding reaching the requested +performance level. + +Since numbers are a rather meaningless way to describe platform-profiles +this API uses strings to describe the various profiles. To make sure that +userspace gets a consistent experience when using this API this API +document defines a fixed set of profile-names. Drivers *must* map their +internal profile representation/names onto this fixed set. + +If for some reason there is no good match when mapping then a new profile-name +may be added. Drivers which wish to introduce new profile-names must: +1. Have very good reasons to do so. +2. Add the new profile-name to this document, so that future drivers which also + have a similar problem can use the same name. + +What: /sys/firmware/acpi/platform_profile_choices +Date: October 2020 +Contact: Hans de Goede +Description: + Reading this file gives a space separated list of profiles + supported for this device. + + Drivers must use the following standard profile-names: + + low-power: Emphasises low power consumption + cool: Emphasises cooler operation + quiet: Emphasises quieter operation + balanced: Balance between low power consumption + and performance + performance: Emphasises performance (and may lead to + higher temperatures and fan speeds) + + Userspace may expect drivers to offer at least several of these + standard profile-names. + +What: /sys/firmware/acpi/platform_profile +Date: October 2020 +Contact: Hans de Goede +Description: + Reading this file gives the current selected profile for this + device. Writing this file with one of the strings from + available_profiles changes the profile to the new value. From patchwork Thu Nov 26 16:51:42 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Mark Pearson X-Patchwork-Id: 333100 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-16.8 required=3.0 tests=BAYES_00, HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,USER_AGENT_GIT autolearn=unavailable autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 45BF8C63697 for ; Thu, 26 Nov 2020 16:52:24 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id F14C5221F7 for ; Thu, 26 Nov 2020 16:52:23 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S2391520AbgKZQwX (ORCPT ); Thu, 26 Nov 2020 11:52:23 -0500 Received: from mail1.bemta23.messagelabs.com ([67.219.246.3]:61118 "EHLO mail1.bemta23.messagelabs.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S2391590AbgKZQwX (ORCPT ); Thu, 26 Nov 2020 11:52:23 -0500 Received: from [100.112.1.203] (using TLSv1.2 with cipher DHE-RSA-AES256-GCM-SHA384 (256 bits)) by server-3.bemta.az-b.us-east-1.aws.symcld.net id 3D/4C-29643-34DDFBF5; Thu, 26 Nov 2020 16:52:19 +0000 X-Brightmail-Tracker: H4sIAAAAAAAAA+NgFprGKsWRWlGSWpSXmKPExsWSLveKTdf57v5 4g+5dchb7r0tYdC00sFh4/xSrxddvt9kt3hyfzmSxfF8/o8XHZRwWnzsms1is3vOC2WLtl3ls FmdOX2J14PaYNHMGs8fOWXfZPX5tW8PisXmFlse8k4EePW2bmDze77vK5rHlajuLx+dNcgGcU ayZeUn5FQmsGb3bdjIWHPCvOHhMs4Hxl3MXIxeHkMB/Roln15pYuhg5gZyHjBKfr4iA2GwC2h Jbtvxi62Lk4BARkJH4sNYTpJ5ZYAGTxJfra1hB4sICPhJb2pNBylkEVCU2//jEBGLzClhLTOr 7yQhiSwjISzztXc4MYnMK2Eg8nvOOHWJVqET/0ifMEPWCEidnPgE7gRmovnnrbGYIW0Li4IsX zBBzFCQmL7jKBGEnSCx7eYd5AqPALCTts5C0z0LSvoCReRWjaVJRZnpGSW5iZo6uoYGBrqGhk a6hroWlXmKVbpJeabFuamJxia6hXmJ5sV5xZW5yTopeXmrJJkZgdKUUMEbuYNz3+oPeIUZJDi YlUd4le/bHC/El5adUZiQWZ8QXleakFh9ilOHgUJLg9bwNlBMsSk1PrUjLzAFGOkxagoNHSYT 3N0iat7ggMbc4Mx0idYpRUUqcdxtIQgAkkVGaB9cGSy6XGGWlhHkZGRgYhHgKUotyM0tQ5V8x inMwKgnzhoFM4cnMK4Gb/gpoMRPQ4umce0AWlyQipKQamAodlm57aKp//fimtKp3rrX6AcWTU /WEDoTv7L9+2cIut0U5mp3VO5vl+6tb25VtUpsY1pQtS5NVYTz4UEDPJm69RN0DpXeGgpfEeH 61hH24einLSJvRU+E2j/VHvhTpeaeueX+TtnWZFemy+oZs/c04i1kKKxZ67srLW/fTZ2Fd9Zv pFX+cFqncnb/VX1rz6rzHzYqJaQ8/p6UeiOuV8j2tMe3+V+2JpySkeib/3Xbtpc+jFQEfBSuX 8a0r7ZwWv1C4r+JA4A3OjgKDktKJF20Xt8Yvmavr9D6lNctdwtJoW3nvpL3Mlxa8Y1VZm1MUl h1zg7O2QrB20b3KkLmCItfkm1SndypEZfwN7buhxFKckWioxVxUnAgAXl1656kDAAA= X-Env-Sender: markpearson@lenovo.com X-Msg-Ref: server-4.tower-396.messagelabs.com!1606409537!1406277!1 X-Originating-IP: [103.30.234.6] X-SYMC-ESS-Client-Auth: outbound-route-from=pass X-StarScan-Received: X-StarScan-Version: 9.60.3; banners=-,-,- X-VirusChecked: Checked Received: (qmail 7489 invoked from network); 26 Nov 2020 16:52:19 -0000 Received: from unknown (HELO lenovo.com) (103.30.234.6) by server-4.tower-396.messagelabs.com with ECDHE-RSA-AES256-GCM-SHA384 encrypted SMTP; 26 Nov 2020 16:52:19 -0000 Received: from reswpmail04.lenovo.com (unknown [10.62.32.23]) (using TLSv1.2 with cipher AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by Forcepoint Email with ESMTPS id 4D81B908DC87CDDAB036; Fri, 27 Nov 2020 00:52:14 +0800 (CST) Received: from localhost.home (10.64.80.205) by reswpmail04.lenovo.com (10.62.32.23) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.1.2044.4; Thu, 26 Nov 2020 08:52:09 -0800 From: Mark Pearson To: CC: , , , , , , , , , , Subject: [PATCH v4 2/3] ACPI: platform-profile: Add platform profile support Date: Thu, 26 Nov 2020 11:51:42 -0500 Message-ID: <20201126165143.32776-2-markpearson@lenovo.com> X-Mailer: git-send-email 2.28.0 In-Reply-To: <20201126165143.32776-1-markpearson@lenovo.com> References: <20201126165143.32776-1-markpearson@lenovo.com> MIME-Version: 1.0 X-Originating-IP: [10.64.80.205] X-ClientProxiedBy: reswpmail04.lenovo.com (10.62.32.23) To reswpmail04.lenovo.com (10.62.32.23) Precedence: bulk List-ID: X-Mailing-List: linux-acpi@vger.kernel.org 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 --- Changes in v2: Address (hopefully) all recommendations from review including: - reorder includes list alphabetically - make globals statics and use const as required - change profile name scanning to use full string - clean up profile name lists to remove unwanted additions - use sysfs_emit and sysfs_emit_at appropriately (much nicer!) - improve error handling. Return errors to user in all cases and use better error codes where appropriate (ENOOPSUPP) - clean up sysfs output for better readability - formatting fixes where needed - improve structure and enum names to be clearer - remove cur_profile field from structure. It is now local to the actual platform driver file (patch 3 in series) - improve checking so if future profile options are added profile_names will be updated as well. - move CONFIG option next to ACPI_THERMAL as it seemed slightly related - removed MAINTAINERS update as not appropriate (note warning message is seen when running checkpatch) Changes in v3: - Add missed platform_profile.h file Changes in v4: - Clean up duplicate entry in Kconfig file - Add linux/bits.h to include list - Remove unnecessary items from include list - Make cur_profile const - Clean up comments - formatting clean-ups - add checking of profile return value to show function - add checking to store to see if it's a supported profile - revert ENOTSUPP change in store function - improved error checking in profile registration - improved profile naming (now platform_profile_*) drivers/acpi/Kconfig | 14 ++ drivers/acpi/Makefile | 1 + drivers/acpi/platform_profile.c | 215 +++++++++++++++++++++++++++++++ include/linux/platform_profile.h | 36 ++++++ 4 files changed, 266 insertions(+) create mode 100644 drivers/acpi/platform_profile.c create mode 100644 include/linux/platform_profile.h diff --git a/drivers/acpi/Kconfig b/drivers/acpi/Kconfig index edf1558c1105..c1ca6255ff85 100644 --- a/drivers/acpi/Kconfig +++ b/drivers/acpi/Kconfig @@ -326,6 +326,20 @@ config ACPI_THERMAL To compile this driver as a module, choose M here: the module will be called thermal. +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. + config ACPI_CUSTOM_DSDT_FILE string "Custom DSDT Table file to include" default "" diff --git a/drivers/acpi/Makefile b/drivers/acpi/Makefile index 44e412506317..c64a8af106c0 100644 --- a/drivers/acpi/Makefile +++ b/drivers/acpi/Makefile @@ -78,6 +78,7 @@ obj-$(CONFIG_ACPI_PCI_SLOT) += pci_slot.o obj-$(CONFIG_ACPI_PROCESSOR) += processor.o obj-$(CONFIG_ACPI) += container.o obj-$(CONFIG_ACPI_THERMAL) += thermal.o +obj-$(CONFIG_ACPI_PLATFORM_PROFILE) += platform_profile.o obj-$(CONFIG_ACPI_NFIT) += nfit/ obj-$(CONFIG_ACPI_NUMA) += numa/ obj-$(CONFIG_ACPI) += acpi_memhotplug.o diff --git a/drivers/acpi/platform_profile.c b/drivers/acpi/platform_profile.c new file mode 100644 index 000000000000..678cb4596ada --- /dev/null +++ b/drivers/acpi/platform_profile.c @@ -0,0 +1,215 @@ +// SPDX-License-Identifier: GPL-2.0-or-later + +/* Platform profile sysfs interface */ + +#include +#include +#include +#include +#include +#include + +static const struct platform_profile_handler *cur_profile; +static DEFINE_MUTEX(profile_lock); + +static const char * const profile_names[] = { + [platform_profile_low] = "low-power", + [platform_profile_cool] = "cool", + [platform_profile_quiet] = "quiet", + [platform_profile_balance] = "balance", + [platform_profile_perform] = "performance", +}; +static_assert(ARRAY_SIZE(profile_names) == platform_profile_perform+1); + +static ssize_t platform_profile_choices_show(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + int len = 0; + int err, i; + + err = mutex_lock_interruptible(&profile_lock); + if (err) + return err; + + if (!cur_profile) { + mutex_unlock(&profile_lock); + return -ENODEV; + } + + if (!cur_profile->choices) { + mutex_unlock(&profile_lock); + return sysfs_emit(buf, "\n"); + } + + for (i = 0; i < ARRAY_SIZE(profile_names); i++) { + if (cur_profile->choices & BIT(i)) { + if (len == 0) + len += sysfs_emit_at(buf, len, "%s", profile_names[i]); + else + len += sysfs_emit_at(buf, len, " %s", profile_names[i]); + } + } + len += sysfs_emit_at(buf, len, "\n"); + mutex_unlock(&profile_lock); + return len; +} + +static ssize_t platform_profile_show(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + enum platform_profile_option profile = platform_profile_balance; + int err; + + err = mutex_lock_interruptible(&profile_lock); + if (err) + return err; + + if (!cur_profile) { + mutex_unlock(&profile_lock); + return -ENODEV; + } + + if (!cur_profile->profile_get) { + mutex_unlock(&profile_lock); + return -EOPNOTSUPP; + } + + err = cur_profile->profile_get(&profile); + mutex_unlock(&profile_lock); + if (err < 0) + return err; + + /* Check that profile is valid index */ + if ((profile < 0) || (profile >= ARRAY_SIZE(profile_names))) + return sysfs_emit(buf, "\n"); + + return sysfs_emit(buf, "%s\n", profile_names[profile]); +} + +static ssize_t platform_profile_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + int err, i; + + err = mutex_lock_interruptible(&profile_lock); + if (err) + return err; + + if (!cur_profile) { + mutex_unlock(&profile_lock); + return -ENODEV; + } + + if (!cur_profile->profile_set) { + mutex_unlock(&profile_lock); + return -EOPNOTSUPP; + } + + /* Scan for a matching profile */ + i = sysfs_match_string(profile_names, buf); + if (i < 0) { + mutex_unlock(&profile_lock); + return -EINVAL; + } + + /* Check that platform supports this profile choice */ + if (!(cur_profile->choices & BIT(i))) { + mutex_unlock(&profile_lock); + return -EOPNOTSUPP; + } + + err = cur_profile->profile_set(i); + mutex_unlock(&profile_lock); + if (err) + return err; + return count; +} + +static DEVICE_ATTR_RO(platform_profile_choices); +static DEVICE_ATTR_RW(platform_profile); + +static struct attribute *platform_profile_attrs[] = { + &dev_attr_platform_profile_choices.attr, + &dev_attr_platform_profile.attr, + NULL +}; + +static const struct attribute_group platform_profile_group = { + .attrs = platform_profile_attrs +}; + +void platform_profile_notify(void) +{ + if (!cur_profile) + return; + sysfs_notify(acpi_kobj, NULL, "platform_profile"); +} +EXPORT_SYMBOL_GPL(platform_profile_notify); + +int platform_profile_register(const struct platform_profile_handler *pprof) +{ + int err; + + err = mutex_lock_interruptible(&profile_lock); + if (err) + return err; + + /* We can only have one active profile */ + if (cur_profile) { + mutex_unlock(&profile_lock); + return -EEXIST; + } + + err = sysfs_create_group(acpi_kobj, &platform_profile_group); + if (err) { + mutex_unlock(&profile_lock); + return err; + } + + cur_profile = pprof; + mutex_unlock(&profile_lock); + return 0; +} +EXPORT_SYMBOL_GPL(platform_profile_register); + +int platform_profile_unregister(void) +{ + int err; + + err = mutex_lock_interruptible(&profile_lock); + if (err) + return err; + + if (!cur_profile) { + mutex_unlock(&profile_lock); + return -ENODEV; + } + + sysfs_remove_group(acpi_kobj, &platform_profile_group); + cur_profile = NULL; + mutex_unlock(&profile_lock); + return 0; +} +EXPORT_SYMBOL_GPL(platform_profile_unregister); + +static int __init platform_profile_init(void) +{ + return 0; +} +module_init(platform_profile_init); + +static void __exit platform_profile_exit(void) +{ + /* Check if we have a registered profile, and clean up */ + if (cur_profile) { + sysfs_remove_group(acpi_kobj, &platform_profile_group); + cur_profile = NULL; + } +} +module_exit(platform_profile_exit); + +MODULE_AUTHOR("Mark Pearson "); +MODULE_LICENSE("GPL"); diff --git a/include/linux/platform_profile.h b/include/linux/platform_profile.h new file mode 100644 index 000000000000..33ccd40bb9cf --- /dev/null +++ b/include/linux/platform_profile.h @@ -0,0 +1,36 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ +/* + * Platform profile sysfs interface + * + * See Documentation/ABI/testing/sysfs-platform_profile.rst for more + * information. + */ + +#ifndef _PLATFORM_PROFILE_H_ +#define _PLATFORM_PROFILE_H_ + +/* + * If more options are added please update profile_names + * array in platform-profile.c and sysfs-platform-profile.rst + * documentation. + */ + +enum platform_profile_option { + platform_profile_low, + platform_profile_cool, + platform_profile_quiet, + platform_profile_balance, + platform_profile_perform, +}; + +struct platform_profile_handler { + unsigned int choices; /* Bitmap of available choices */ + int (*profile_get)(enum platform_profile_option *profile); + int (*profile_set)(enum platform_profile_option profile); +}; + +int platform_profile_register(const struct platform_profile_handler *pprof); +int platform_profile_unregister(void); +void platform_profile_notify(void); + +#endif /*_PLATFORM_PROFILE_H_*/ From patchwork Tue Nov 10 03:31:24 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Mark Pearson X-Patchwork-Id: 321087 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-12.8 required=3.0 tests=BAYES_00, HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_PATCH, MAILING_LIST_MULTI, SIGNED_OFF_BY, SPF_HELO_NONE,SPF_PASS,URIBL_BLOCKED,USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 6B2D6C5517A for ; Tue, 10 Nov 2020 03:32:24 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 27B66207BC for ; Tue, 10 Nov 2020 03:32:24 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1731664AbgKJDcX (ORCPT ); Mon, 9 Nov 2020 22:32:23 -0500 Received: from mail1.bemta23.messagelabs.com ([67.219.246.4]:8526 "EHLO mail1.bemta23.messagelabs.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1731341AbgKJDcW (ORCPT ); Mon, 9 Nov 2020 22:32:22 -0500 Received: from [100.112.1.102] (using TLSv1.2 with cipher DHE-RSA-AES256-GCM-SHA384 (256 bits)) by server-4.bemta.az-b.us-east-1.aws.symcld.net id 44/46-54728-4C90AAF5; Tue, 10 Nov 2020 03:32:20 +0000 X-Brightmail-Tracker: H4sIAAAAAAAAA+NgFprDKsWRWlGSWpSXmKPExsWSLveKXfcw56p 4gyuPtSz2X5ew6FpoYLHw/ilWi6/fbrNbvDk+ncli+b5+RoumziY2i88dk1ksVu95wWxx5vQl Vgcuj0kzZzB77Jx1l93j17Y1LB6bV2h5zDsZ6PF+31U2jy1X21k8Pm+SC+CIYs3MS8qvSGDNW P39M2tBr0/Fq388DYwN9l2MXBxCAv8ZJfb0/2ODcO4DOes/sXYxcnKwCWhLbNnyCyjBwSEiIC PxYa0nSA2zQDuTxOpjj9lAaoQF/CR+/W9iBrFZBFQkvmw9ARbnFbCSOHzgF5gtISAv8bR3OVg Np4C1xNXjX9lBbCGBEIknO96yQNQLSpyc+QTMZgaqb946mxnClpA4+OIFM8yckxs+MUHYCRLL Xt5hnsAoMAtJ+ywk7bOQtC9gZF7FaJZUlJmeUZKbmJmja2hgoGtoaKRroGtkZKSXWKWbpFdar JuaWFyia6iXWF6sV1yZm5yTopeXWrKJERhRKQUM93Yw/nn9Qe8QoyQHk5IobxbTqnghvqT8lM qMxOKM+KLSnNTiQ4wyHBxKEryObEA5waLU9NSKtMwcYHTDpCU4eJREeF+wAKV5iwsSc4sz0yF Spxh1OU6uWrKIWYglLz8vVUqcdwo7UJEASFFGaR7cCFiiucQoKyXMy8jAwCDEU5BalJtZgir/ ilGcg1FJmPcYyBSezLwSuE2vgI5gAjoiwHEFyBEliQgpqQamefPeTFM5EsG3T9rP5HOx8JvJx 35FpBWLOwu3TP3OZsObJVqw4WP8Gb3XIZd+ZaivfzLnxDEVwUAW8wW/Cr9Ou+Y4hS3Edsr/dt 8tTSelbqs5eDjJVzDWKRrHvVCaJJ0muE6L8eslhV2blsY2xt4T/p3Pvnzr8/pJv54ndDGyzij UPPN0z/KktZEJ90X36LvXcb95z5l3bP105Q6GXyXvLu3d7t3U6dpqcSaZdW52ZbFLWsC7L7rx aqJ7Kxp91fKcvldEmM+4F/XF58uzu9M6uGsuTNozNeXrU524GK/kDZJbOd7cPet907X2gsoei /5zD9pmXDA9Nu3Mod2C3Jnm/3sbZea3rg76OmkJq6SYEktxRqKhFnNRcSIAZQaKy68DAAA= X-Env-Sender: markpearson@lenovo.com X-Msg-Ref: server-15.tower-386.messagelabs.com!1604979137!255772!1 X-Originating-IP: [103.30.234.7] X-SYMC-ESS-Client-Auth: outbound-route-from=pass X-StarScan-Received: X-StarScan-Version: 9.60.3; banners=-,-,- X-VirusChecked: Checked Received: (qmail 13138 invoked from network); 10 Nov 2020 03:32:19 -0000 Received: from unknown (HELO lenovo.com) (103.30.234.7) by server-15.tower-386.messagelabs.com with ECDHE-RSA-AES256-GCM-SHA384 encrypted SMTP; 10 Nov 2020 03:32:19 -0000 Received: from reswpmail04.lenovo.com (unknown [10.62.32.23]) (using TLSv1.2 with cipher AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by Forcepoint Email with ESMTPS id 9A9A59E1579E767D0D4B; Tue, 10 Nov 2020 11:32:14 +0800 (CST) Received: from localhost.home (10.64.89.28) by reswpmail04.lenovo.com (10.62.32.23) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.1.2044.4; Mon, 9 Nov 2020 19:32:09 -0800 From: Mark Pearson To: CC: , , , , , , , , , Subject: [PATCH 3/3] platform/x86: thinkpad_acpi: Add platform profile support Date: Mon, 9 Nov 2020 22:31:24 -0500 Message-ID: <20201110033124.3211-4-markpearson@lenovo.com> X-Mailer: git-send-email 2.28.0 In-Reply-To: <20201110033124.3211-1-markpearson@lenovo.com> References: <20201110033124.3211-1-markpearson@lenovo.com> MIME-Version: 1.0 X-Originating-IP: [10.64.89.28] X-ClientProxiedBy: reswpmail04.lenovo.com (10.62.32.23) To reswpmail04.lenovo.com (10.62.32.23) Precedence: bulk List-ID: X-Mailing-List: linux-acpi@vger.kernel.org Add support to thinkpad_acpi for Lenovo platforms that have DYTC version 5 support or newer to use the platform profile feature. This will allow users to determine and control the platform modes between low-power, balanced operation and performance modes. Signed-off-by: Mark Pearson --- drivers/platform/x86/thinkpad_acpi.c | 263 +++++++++++++++++++++++++-- 1 file changed, 246 insertions(+), 17 deletions(-) diff --git a/drivers/platform/x86/thinkpad_acpi.c b/drivers/platform/x86/thinkpad_acpi.c index fe438a5e1dbe..d70181b5772b 100644 --- a/drivers/platform/x86/thinkpad_acpi.c +++ b/drivers/platform/x86/thinkpad_acpi.c @@ -72,6 +72,7 @@ #include #include #include +#include /* ThinkPad CMOS commands */ #define TP_CMOS_VOLUME_DOWN 0 @@ -9824,10 +9825,40 @@ static struct ibm_struct lcdshadow_driver_data = { * DYTC subdriver, for the Lenovo lapmode feature */ +#define DYTC_CMD_QUERY 0 /* To get DYTC status - enable/revision */ +#define DYTC_CMD_SET 1 /* To enable/disable IC function mode */ #define DYTC_CMD_GET 2 /* To get current IC function and mode */ #define DYTC_GET_LAPMODE_BIT 17 /* Set when in lapmode */ +#define DYTC_CMD_RESET 0x1ff /* To reset back to default */ + +#define DYTC_QUERY_ENABLE_BIT 8 /* Bit 8 - 0 = disabled, 1 = enabled */ +#define DYTC_QUERY_SUBREV_BIT 16 /* Bits 16 - 27 - sub revisision */ +#define DYTC_QUERY_REV_BIT 28 /* Bits 28 - 31 - revision */ + +#define DYTC_GET_FUNCTION_BIT 8 /* Bits 8-11 - function setting */ +#define DYTC_GET_MODE_BIT 12 /* Bits 12-15 - mode setting */ +#define DYTC_GET_LAPMODE_BIT 17 /* Bit 17 - lapmode. Set when on lap */ + +#define DYTC_SET_FUNCTION_BIT 12 /* Bits 12-15 - funct setting */ +#define DYTC_SET_MODE_BIT 16 /* Bits 16-19 - mode setting */ +#define DYTC_SET_VALID_BIT 20 /* Bit 20 - 1 = on, 0 = off */ + +#define DYTC_FUNCTION_STD 0 /* Function = 0, standard mode */ +#define DYTC_FUNCTION_CQL 1 /* Function = 1, lap mode */ +#define DYTC_FUNCTION_MMC 11 /* Function = 11, desk mode */ + +#define DYTC_MODE_PERFORM 2 /* High power mode aka performance */ +#define DYTC_MODE_QUIET 3 /* low power mode aka quiet */ +#define DYTC_MODE_BALANCE 0xF /* default mode aka balance */ + +#define DYTC_DISABLE_CQL ((DYTC_MODE_BALANCE << DYTC_SET_MODE_BIT) | \ + (DYTC_FUNCTION_CQL << DYTC_SET_FUNCTION_BIT) | \ + DYTC_CMD_SET) +#define DYTC_ENABLE_CQL (DYTC_DISABLE_CQL | (1 << DYTC_SET_VALID_BIT)) static bool dytc_lapmode; +static bool dytc_available; +static bool dytc_ignore_next_event; static void dytc_lapmode_notify_change(void) { @@ -9881,22 +9912,172 @@ static ssize_t dytc_lapmode_show(struct device *dev, static DEVICE_ATTR_RO(dytc_lapmode); -static struct attribute *dytc_attributes[] = { - &dev_attr_dytc_lapmode.attr, - NULL, -}; +#if defined(CONFIG_ACPI_PLATFORM_PROFILE) +static struct platform_profile dytc_profile; -static const struct attribute_group dytc_attr_group = { - .attrs = dytc_attributes, -}; +static int convert_dytc_to_profile(int dytcmode) +{ + switch (dytcmode) { + case DYTC_MODE_QUIET: + return profile_low; + case DYTC_MODE_BALANCE: + return profile_balance; + case DYTC_MODE_PERFORM: + return profile_perform; + default: /* Unknown mode */ + return profile_unknown; + } +} -static int tpacpi_dytc_init(struct ibm_init_struct *iibm) +static int convert_profile_to_dytc(int profile) +{ + switch (profile) { + case profile_low: + return DYTC_MODE_QUIET; + case profile_balance: + return DYTC_MODE_BALANCE; + case profile_perform: + return DYTC_MODE_PERFORM; + default: /* Unknown profile */ + return -EINVAL; + } +} + +static int dytc_perfmode_get(int *perfmode, int *funcmode) +{ + int output, err; + + if (!dytc_available) + return -ENODEV; + + err = dytc_command(DYTC_CMD_GET, &output); + if (err) + return err; + + *funcmode = (output >> DYTC_GET_FUNCTION_BIT) & 0xF; + if (*funcmode == DYTC_FUNCTION_CQL) { + int dummy; + /* + * We can't get the mode when in CQL mode - so we disable CQL + * mode retrieve the mode and then enable it again. + * As disabling/enabling CQL triggers an event we set a flag to + * ignore these events. This will be cleared by the event handler + */ + dytc_ignore_next_event = true; + err = dytc_command(DYTC_DISABLE_CQL, &dummy); + if (err) + return err; + err = dytc_command(DYTC_CMD_GET, &output); + if (err) + return err; + /* Again ignore this event */ + dytc_ignore_next_event = true; + err = dytc_command(DYTC_ENABLE_CQL, &dummy); + if (err) + return err; + } + *perfmode = (output >> DYTC_GET_MODE_BIT) & 0xF; + return 0; +} + +/* + * dytc_profile_get: Function to register with platform_profile + * handler. Returns current platform profile. + */ +int dytc_profile_get(void) { int err; + int funcmode, perfmode; + + err = dytc_perfmode_get(&perfmode, &funcmode); + if (err) + return err; - err = dytc_lapmode_get(&dytc_lapmode); - /* If support isn't available (ENODEV) then don't return an error - * but just don't create the sysfs group + /* Convert Lenovo DYTC profile to platform_profile */ + dytc_profile.cur_profile = convert_dytc_to_profile(perfmode); + return dytc_profile.cur_profile; +} + +/* + * dytc_profile_set: Function to register with platform_profile + * handler. Sets current platform profile. + */ +int dytc_profile_set(int profile) +{ + int err, dytc_set; + int output; + int cur_perfmode, cur_funcmode; + + if (!dytc_available) + return -ENODEV; + + if (profile == profile_balance) { + /* To get back to balance mode we just issue a reset command */ + err = dytc_command(DYTC_CMD_RESET, &output); + if (err) + return err; + } else { + int perfmode = convert_profile_to_dytc(profile); + + if (perfmode < 0) + return perfmode; + + /* Determine if we are in CQL mode. This alters the commands we do */ + err = dytc_perfmode_get(&cur_perfmode, &cur_funcmode); + if (err) + return err; + + if (cur_funcmode == DYTC_FUNCTION_CQL) { + /* To set the mode we need to disable CQL first*/ + dytc_ignore_next_event = true; /*ignore event*/ + err = dytc_command(DYTC_DISABLE_CQL, &output); + if (err) + return err; + } + dytc_set = (1 << DYTC_SET_VALID_BIT) | + (DYTC_FUNCTION_MMC << DYTC_SET_FUNCTION_BIT) | + (perfmode << DYTC_SET_MODE_BIT) | + DYTC_CMD_SET; + err = dytc_command(dytc_set, &output); + if (err) + return err; + if (cur_funcmode == DYTC_FUNCTION_CQL) { + dytc_ignore_next_event = true; /*ignore event*/ + err = dytc_command(DYTC_ENABLE_CQL, &output); + if (err) + return err; + } + } + /* Success - update current profile */ + dytc_profile.cur_profile = profile; + return 0; +} + +static void dytc_profile_refresh(void) +{ + int perfmode, funcmode, profile; + int err; + + err = dytc_perfmode_get(&perfmode, &funcmode); + if (err) + return; + + profile = convert_dytc_to_profile(perfmode); + if (profile != dytc_profile.cur_profile) { + dytc_profile.cur_profile = profile; + platform_profile_notify(); + } +} +#endif + +static int tpacpi_dytc_init(struct ibm_init_struct *iibm) +{ + int err, output; + + err = dytc_command(DYTC_CMD_QUERY, &output); + /* + * If support isn't available (ENODEV) then don't return an error + * and don't create the sysfs group */ if (err == -ENODEV) return 0; @@ -9904,14 +10085,55 @@ static int tpacpi_dytc_init(struct ibm_init_struct *iibm) if (err) return err; - /* Platform supports this feature - create the group */ - err = sysfs_create_group(&tpacpi_pdev->dev.kobj, &dytc_attr_group); - return err; + /* Check DYTC is enabled and supports mode setting */ + dytc_available = false; + dytc_ignore_next_event = false; + + if (output & BIT(DYTC_QUERY_ENABLE_BIT)) { + /* Only DYTC v5.0 and later has this feature. */ + int dytc_version; + + dytc_version = (output >> DYTC_QUERY_REV_BIT) & 0xF; + if (dytc_version >= 5) { + dbg_printk(TPACPI_DBG_INIT, + "DYTC version %d: thermal mode available\n", dytc_version); + dytc_available = true; +#if defined(CONFIG_ACPI_PLATFORM_PROFILE) + /* Create platform_profile structure and register */ + dytc_profile.choices = (1 << profile_low) | + (1 << profile_balance) | + (1 << profile_perform); + dytc_profile.profile_get = dytc_profile_get; + dytc_profile.profile_set = dytc_profile_set; + dytc_profile.cur_profile = profile_unknown; + err = platform_profile_register(&dytc_profile); + /* + * If for some reason platform_profiles aren't enabled + * don't quit terminally. + */ + if (err) + return 0; +#endif + /* + * Note - this has been deprecated by the input sensor implementation, + * but can't be removed until we confirm user space is no longer using + */ + dytc_lapmode_get(&dytc_lapmode); + return device_create_file(&tpacpi_pdev->dev, &dev_attr_dytc_lapmode); + } + } + return 0; } static void dytc_exit(void) { - sysfs_remove_group(&tpacpi_pdev->dev.kobj, &dytc_attr_group); + if (dytc_available) { + device_remove_file(&tpacpi_pdev->dev, &dev_attr_dytc_lapmode); +#if defined(CONFIG_ACPI_PLATFORM_PROFILE) + platform_profile_unregister(); +#endif + dytc_available = false; + } } static struct ibm_struct dytc_driver_data = { @@ -10095,8 +10317,15 @@ static void tpacpi_driver_event(const unsigned int hkey_event) } if (hkey_event == TP_HKEY_EV_THM_CSM_COMPLETED) { - dytc_lapmode_refresh(); - lapsensor_refresh(); + if (dytc_ignore_next_event) + dytc_ignore_next_event = false; /*clear setting*/ + else { + dytc_lapmode_refresh(); +#if defined(CONFIG_ACPI_PLATFORM_PROFILE) + dytc_profile_refresh(); +#endif + lapsensor_refresh(); + } } }