dri-devel.lists.freedesktop.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 00/15] Introduce PMF Smart PC Solution Builder Feature
@ 2023-09-22 17:50 Shyam Sundar S K
  2023-09-22 17:50 ` [PATCH 01/15] platform/x86/amd/pmf: Add PMF TEE interface Shyam Sundar S K
                   ` (14 more replies)
  0 siblings, 15 replies; 54+ messages in thread
From: Shyam Sundar S K @ 2023-09-22 17:50 UTC (permalink / raw)
  To: hdegoede, markgross, basavaraj.natikar, jikos,
	benjamin.tissoires, alexander.deucher, christian.koenig,
	Xinhui.Pan, airlied, daniel
  Cc: Shyam Sundar S K, amd-gfx, platform-driver-x86, dri-devel,
	Patil.Reddy, linux-input, mario.limonciello

Smart PC Solutions Builder allows for OEM to define a large number of
custom system states to dynamically switch to. The system states are
referred to as policies, and multiple policies can be loaded onto the
system at any given time, however only one policy can be active at a
given time.

Policy is a combination of PMF input and output capabilities. The inputs
are the incoming information from the other kernel subsystems like LID
state, Sensor info, GPU info etc and the actions are the updating the 
power limits of SMU etc.

The policy binary is signed and encrypted by a special key from AMD. This
policy binary shall have the inputs and outputs which the OEMs can build
for the platform customization that can enhance the user experience and
system behavior.

This series adds the initial support for Smart PC solution to PMF driver.

Note that, on platforms where CnQF and Smart PC is advertised, Smart PC
shall have higher precedence and same applies for Auto Mode.

Basavaraj Natikar (2):
  platform/x86/amd/pmf: Add PMF-AMDSFH interface for HPD
  platform/x86/amd/pmf: Add PMF-AMDSFH interface for ALS

Shyam Sundar S K (13):
  platform/x86/amd/pmf: Add PMF TEE interface
  platform/x86/amd/pmf: Add support PMF-TA interaction
  platform/x86/amd/pmf: Change signature of amd_pmf_set_dram_addr
  platform/x86/amd/pmf: Add support for PMF Policy Binary
  platform/x86/amd/pmf: change debugfs init sequence
  platform/x86/amd/pmf: Add support to get inputs from other subsystems
  platform/x86/amd/pmf: Add support update p3t limit
  platform/x86/amd/pmf: Add support to update system state
  platform/x86/amd/pmf: Add facility to dump TA inputs
  platform/x86/amd/pmf: Add capability to sideload of policy binary
  platform/x86/amd/pmf: dump policy binary data
  platform/x86/amd/pmf: Add PMF-AMDGPU get interface
  platform/x86/amd/pmf: Add PMF-AMDGPU set interface

 Documentation/admin-guide/pmf.rst             |  24 +
 drivers/gpu/drm/amd/amdgpu/Makefile           |   2 +
 drivers/gpu/drm/amd/amdgpu/amdgpu.h           |   1 +
 drivers/gpu/drm/amd/amdgpu/amdgpu_pmf.c       |  91 ++++
 drivers/hid/amd-sfh-hid/amd_sfh_common.h      |   6 +
 drivers/hid/amd-sfh-hid/sfh1_1/amd_sfh_desc.c |   2 +-
 drivers/hid/amd-sfh-hid/sfh1_1/amd_sfh_init.c |  17 +
 .../amd-sfh-hid/sfh1_1/amd_sfh_interface.c    |  48 ++
 .../amd-sfh-hid/sfh1_1/amd_sfh_interface.h    |   1 +
 drivers/platform/x86/amd/pmf/Kconfig          |   2 +
 drivers/platform/x86/amd/pmf/Makefile         |   3 +-
 drivers/platform/x86/amd/pmf/acpi.c           |  37 ++
 drivers/platform/x86/amd/pmf/core.c           |  40 +-
 drivers/platform/x86/amd/pmf/pmf.h            | 199 +++++++
 drivers/platform/x86/amd/pmf/spc.c            | 194 +++++++
 drivers/platform/x86/amd/pmf/sps.c            |   2 +-
 drivers/platform/x86/amd/pmf/tee-if.c         | 492 ++++++++++++++++++
 include/linux/amd-pmf-io.h                    |  51 ++
 18 files changed, 1199 insertions(+), 13 deletions(-)
 create mode 100644 Documentation/admin-guide/pmf.rst
 create mode 100644 drivers/gpu/drm/amd/amdgpu/amdgpu_pmf.c
 create mode 100644 drivers/platform/x86/amd/pmf/spc.c
 create mode 100644 drivers/platform/x86/amd/pmf/tee-if.c
 create mode 100644 include/linux/amd-pmf-io.h

-- 
2.25.1


^ permalink raw reply	[flat|nested] 54+ messages in thread

* [PATCH 01/15] platform/x86/amd/pmf: Add PMF TEE interface
  2023-09-22 17:50 [PATCH 00/15] Introduce PMF Smart PC Solution Builder Feature Shyam Sundar S K
@ 2023-09-22 17:50 ` Shyam Sundar S K
  2023-09-26 16:42   ` Ilpo Järvinen
  2023-09-22 17:50 ` [PATCH 02/15] platform/x86/amd/pmf: Add support PMF-TA interaction Shyam Sundar S K
                   ` (13 subsequent siblings)
  14 siblings, 1 reply; 54+ messages in thread
From: Shyam Sundar S K @ 2023-09-22 17:50 UTC (permalink / raw)
  To: hdegoede, markgross, basavaraj.natikar, jikos,
	benjamin.tissoires, alexander.deucher, christian.koenig,
	Xinhui.Pan, airlied, daniel
  Cc: Shyam Sundar S K, amd-gfx, platform-driver-x86, dri-devel,
	Patil.Reddy, linux-input, mario.limonciello

AMD PMF driver loads the PMF TA (Trusted Application) into the AMD
ASP's (AMD Security Processor) TEE (Trusted Execution Environment).

PMF Trusted Application is a secured firmware placed under
/lib/firmware/amdtee gets loaded only when the TEE environment is
initialized. Add the initial code path to build these pipes.

Reviewed-by: Mario Limonciello <mario.limonciello@amd.com>
Signed-off-by: Shyam Sundar S K <Shyam-sundar.S-k@amd.com>
---
 drivers/platform/x86/amd/pmf/Makefile |   3 +-
 drivers/platform/x86/amd/pmf/core.c   |  11 ++-
 drivers/platform/x86/amd/pmf/pmf.h    |  16 ++++
 drivers/platform/x86/amd/pmf/tee-if.c | 106 ++++++++++++++++++++++++++
 4 files changed, 132 insertions(+), 4 deletions(-)
 create mode 100644 drivers/platform/x86/amd/pmf/tee-if.c

diff --git a/drivers/platform/x86/amd/pmf/Makefile b/drivers/platform/x86/amd/pmf/Makefile
index fdededf54392..d2746ee7369f 100644
--- a/drivers/platform/x86/amd/pmf/Makefile
+++ b/drivers/platform/x86/amd/pmf/Makefile
@@ -6,4 +6,5 @@
 
 obj-$(CONFIG_AMD_PMF) += amd-pmf.o
 amd-pmf-objs := core.o acpi.o sps.o \
-		auto-mode.o cnqf.o
+		auto-mode.o cnqf.o \
+		tee-if.o
diff --git a/drivers/platform/x86/amd/pmf/core.c b/drivers/platform/x86/amd/pmf/core.c
index 78ed3ee22555..68f1389dda3e 100644
--- a/drivers/platform/x86/amd/pmf/core.c
+++ b/drivers/platform/x86/amd/pmf/core.c
@@ -309,8 +309,11 @@ static void amd_pmf_init_features(struct amd_pmf_dev *dev)
 		dev_dbg(dev->dev, "SPS enabled and Platform Profiles registered\n");
 	}
 
-	/* Enable Auto Mode */
-	if (is_apmf_func_supported(dev, APMF_FUNC_AUTO_MODE)) {
+	if (amd_pmf_init_smart_pc(dev)) {
+		/* Enable Smart PC Solution builder */
+		dev_dbg(dev->dev, "Smart PC Solution Enabled\n");
+	} else if (is_apmf_func_supported(dev, APMF_FUNC_AUTO_MODE)) {
+		/* Enable Auto Mode */
 		amd_pmf_init_auto_mode(dev);
 		dev_dbg(dev->dev, "Auto Mode Init done\n");
 	} else if (is_apmf_func_supported(dev, APMF_FUNC_DYN_SLIDER_AC) ||
@@ -330,7 +333,9 @@ static void amd_pmf_deinit_features(struct amd_pmf_dev *dev)
 		amd_pmf_deinit_sps(dev);
 	}
 
-	if (is_apmf_func_supported(dev, APMF_FUNC_AUTO_MODE)) {
+	if (dev->smart_pc_enabled) {
+		amd_pmf_deinit_smart_pc(dev);
+	} else if (is_apmf_func_supported(dev, APMF_FUNC_AUTO_MODE)) {
 		amd_pmf_deinit_auto_mode(dev);
 	} else if (is_apmf_func_supported(dev, APMF_FUNC_DYN_SLIDER_AC) ||
 			  is_apmf_func_supported(dev, APMF_FUNC_DYN_SLIDER_DC)) {
diff --git a/drivers/platform/x86/amd/pmf/pmf.h b/drivers/platform/x86/amd/pmf/pmf.h
index deba88e6e4c8..02460c2a31ea 100644
--- a/drivers/platform/x86/amd/pmf/pmf.h
+++ b/drivers/platform/x86/amd/pmf/pmf.h
@@ -179,6 +179,12 @@ struct amd_pmf_dev {
 	bool cnqf_enabled;
 	bool cnqf_supported;
 	struct notifier_block pwr_src_notifier;
+	/* Smart PC solution builder */
+	struct tee_context *tee_ctx;
+	struct tee_shm *fw_shm_pool;
+	u32 session_id;
+	void *shbuf;
+	bool smart_pc_enabled;
 };
 
 struct apmf_sps_prop_granular {
@@ -389,6 +395,13 @@ struct apmf_dyn_slider_output {
 	struct apmf_cnqf_power_set ps[APMF_CNQF_MAX];
 } __packed;
 
+struct ta_pmf_shared_memory {
+	int command_id;
+	int resp_id;
+	u32 pmf_result;
+	u32 if_version;
+};
+
 /* Core Layer */
 int apmf_acpi_init(struct amd_pmf_dev *pmf_dev);
 void apmf_acpi_deinit(struct amd_pmf_dev *pmf_dev);
@@ -433,4 +446,7 @@ void amd_pmf_deinit_cnqf(struct amd_pmf_dev *dev);
 int amd_pmf_trans_cnqf(struct amd_pmf_dev *dev, int socket_power, ktime_t time_lapsed_ms);
 extern const struct attribute_group cnqf_feature_attribute_group;
 
+/* Smart PC builder Layer*/
+int amd_pmf_init_smart_pc(struct amd_pmf_dev *dev);
+void amd_pmf_deinit_smart_pc(struct amd_pmf_dev *dev);
 #endif /* PMF_H */
diff --git a/drivers/platform/x86/amd/pmf/tee-if.c b/drivers/platform/x86/amd/pmf/tee-if.c
new file mode 100644
index 000000000000..b48340edbf44
--- /dev/null
+++ b/drivers/platform/x86/amd/pmf/tee-if.c
@@ -0,0 +1,106 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * AMD Platform Management Framework Driver - TEE Interface
+ *
+ * Copyright (c) 2023, Advanced Micro Devices, Inc.
+ * All Rights Reserved.
+ *
+ * Author: Shyam Sundar S K <Shyam-sundar.S-k@amd.com>
+ */
+
+#include <linux/tee_drv.h>
+#include <linux/uuid.h>
+#include "pmf.h"
+
+#define MAX_TEE_PARAM	4
+static const uuid_t amd_pmf_ta_uuid = UUID_INIT(0x6fd93b77, 0x3fb8, 0x524d,
+						0xb1, 0x2d, 0xc5, 0x29, 0xb1, 0x3d, 0x85, 0x43);
+
+static int amd_pmf_amdtee_ta_match(struct tee_ioctl_version_data *ver, const void *data)
+{
+	return ver->impl_id == TEE_IMPL_ID_AMDTEE;
+}
+
+static int amd_pmf_ta_open_session(struct tee_context *ctx, u32 *id)
+{
+	struct tee_ioctl_open_session_arg sess_arg = {};
+	int rc;
+
+	export_uuid(sess_arg.uuid, &amd_pmf_ta_uuid);
+	sess_arg.clnt_login = TEE_IOCTL_LOGIN_PUBLIC;
+	sess_arg.num_params = 0;
+
+	rc = tee_client_open_session(ctx, &sess_arg, NULL);
+	if (rc < 0 || sess_arg.ret != 0) {
+		pr_err("%s: tee_client_open_session failed err:%#x, ret:%#x\n",
+		       __func__, sess_arg.ret, rc);
+		rc = -EINVAL;
+	} else {
+		*id = sess_arg.session;
+	}
+
+	return rc;
+}
+
+static int amd_pmf_tee_init(struct amd_pmf_dev *dev)
+{
+	int ret;
+	u32 size;
+
+	/* Open context with TEE driver */
+	dev->tee_ctx = tee_client_open_context(NULL, amd_pmf_amdtee_ta_match, NULL, NULL);
+	if (IS_ERR(dev->tee_ctx)) {
+		dev_err(dev->dev, "%s: tee_client_open_context failed\n", __func__);
+		return PTR_ERR(dev->tee_ctx);
+	}
+
+	/* Open session with PMF Trusted App */
+	ret = amd_pmf_ta_open_session(dev->tee_ctx, &dev->session_id);
+	if (ret) {
+		dev_err(dev->dev, "%s: amd_pmf_ta_open_session failed(%d)\n", __func__, ret);
+		ret = -EINVAL;
+		goto out_ctx;
+	}
+
+	size = sizeof(struct ta_pmf_shared_memory);
+	dev->fw_shm_pool = tee_shm_alloc_kernel_buf(dev->tee_ctx, size);
+	if (IS_ERR(dev->fw_shm_pool)) {
+		dev_err(dev->dev, "%s: tee_shm_alloc_kernel_buf failed\n", __func__);
+		ret = PTR_ERR(dev->fw_shm_pool);
+		goto out_sess;
+	}
+
+	dev->shbuf = tee_shm_get_va(dev->fw_shm_pool, 0);
+	dev_dbg(dev->dev, "TEE init done\n");
+
+	return 0;
+
+out_sess:
+	tee_client_close_session(dev->tee_ctx, dev->session_id);
+out_ctx:
+	tee_client_close_context(dev->tee_ctx);
+
+	return ret;
+}
+
+static void amd_pmf_tee_deinit(struct amd_pmf_dev *dev)
+{
+	/* Free the shared memory pool */
+	tee_shm_free(dev->fw_shm_pool);
+
+	/* close the existing session with PMF TA*/
+	tee_client_close_session(dev->tee_ctx, dev->session_id);
+
+	/* close the context with TEE driver */
+	tee_client_close_context(dev->tee_ctx);
+}
+
+int amd_pmf_init_smart_pc(struct amd_pmf_dev *dev)
+{
+	return amd_pmf_tee_init(dev);
+}
+
+void amd_pmf_deinit_smart_pc(struct amd_pmf_dev *dev)
+{
+	amd_pmf_tee_deinit(dev);
+}
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 54+ messages in thread

* [PATCH 02/15] platform/x86/amd/pmf: Add support PMF-TA interaction
  2023-09-22 17:50 [PATCH 00/15] Introduce PMF Smart PC Solution Builder Feature Shyam Sundar S K
  2023-09-22 17:50 ` [PATCH 01/15] platform/x86/amd/pmf: Add PMF TEE interface Shyam Sundar S K
@ 2023-09-22 17:50 ` Shyam Sundar S K
  2023-09-26 16:48   ` Ilpo Järvinen
  2023-09-22 17:50 ` [PATCH 03/15] platform/x86/amd/pmf: Change signature of amd_pmf_set_dram_addr Shyam Sundar S K
                   ` (12 subsequent siblings)
  14 siblings, 1 reply; 54+ messages in thread
From: Shyam Sundar S K @ 2023-09-22 17:50 UTC (permalink / raw)
  To: hdegoede, markgross, basavaraj.natikar, jikos,
	benjamin.tissoires, alexander.deucher, christian.koenig,
	Xinhui.Pan, airlied, daniel
  Cc: Shyam Sundar S K, amd-gfx, platform-driver-x86, dri-devel,
	Patil.Reddy, linux-input, mario.limonciello

PMF TA (Trusted Application) loads via the TEE environment into the
AMD ASP.

PMF-TA supports two commands:
1) Init: Initialize the TA with the PMF Smart PC policy binary and
start the policy engine. A policy is a combination of inputs and
outputs, where;
 - the inputs are the changing dynamics of the system like the user
   behaviour, system heuristics etc.
 - the outputs, which are the actions to be set on the system which
   lead to better power management and enhanced user experience.

PMF driver acts as a central manager in this case to supply the
inputs required to the TA (either by getting the information from
the other kernel subsystems or from userland)

2) Enact: Enact the output actions from the TA. The action could be
applying a new thermal limit to boost/throttle the power limits or
change system behavior.

Reviewed-by: Mario Limonciello <mario.limonciello@amd.com>
Signed-off-by: Shyam Sundar S K <Shyam-sundar.S-k@amd.com>
---
 drivers/platform/x86/amd/pmf/pmf.h    | 10 +++
 drivers/platform/x86/amd/pmf/tee-if.c | 97 ++++++++++++++++++++++++++-
 2 files changed, 106 insertions(+), 1 deletion(-)

diff --git a/drivers/platform/x86/amd/pmf/pmf.h b/drivers/platform/x86/amd/pmf/pmf.h
index 02460c2a31ea..a9333ff6c0a7 100644
--- a/drivers/platform/x86/amd/pmf/pmf.h
+++ b/drivers/platform/x86/amd/pmf/pmf.h
@@ -59,6 +59,9 @@
 #define ARG_NONE 0
 #define AVG_SAMPLE_SIZE 3
 
+/* TA macros */
+#define PMF_TA_IF_VERSION__MAJOR				1
+
 /* AMD PMF BIOS interfaces */
 struct apmf_verify_interface {
 	u16 size;
@@ -184,6 +187,7 @@ struct amd_pmf_dev {
 	struct tee_shm *fw_shm_pool;
 	u32 session_id;
 	void *shbuf;
+	struct delayed_work pb_work;
 	bool smart_pc_enabled;
 };
 
@@ -395,6 +399,12 @@ struct apmf_dyn_slider_output {
 	struct apmf_cnqf_power_set ps[APMF_CNQF_MAX];
 } __packed;
 
+/* cmd ids for TA communication */
+enum ta_pmf_command {
+	TA_PMF_COMMAND_POLICY_BUILDER__INITIALIZE,
+	TA_PMF_COMMAND_POLICY_BUILDER__ENACT_POLICIES
+};
+
 struct ta_pmf_shared_memory {
 	int command_id;
 	int resp_id;
diff --git a/drivers/platform/x86/amd/pmf/tee-if.c b/drivers/platform/x86/amd/pmf/tee-if.c
index b48340edbf44..1fce04beacb3 100644
--- a/drivers/platform/x86/amd/pmf/tee-if.c
+++ b/drivers/platform/x86/amd/pmf/tee-if.c
@@ -13,9 +13,96 @@
 #include "pmf.h"
 
 #define MAX_TEE_PARAM	4
+
+/* Policy binary actions sampling frequency (in ms) */
+static int pb_actions_ms = 1000;
+#ifdef CONFIG_AMD_PMF_DEBUG
+module_param(pb_actions_ms, int, 0644);
+MODULE_PARM_DESC(pb_actions_ms, "Policy binary actions sampling frequency (default = 1000ms)");
+#endif
+
 static const uuid_t amd_pmf_ta_uuid = UUID_INIT(0x6fd93b77, 0x3fb8, 0x524d,
 						0xb1, 0x2d, 0xc5, 0x29, 0xb1, 0x3d, 0x85, 0x43);
 
+static void amd_pmf_prepare_args(struct amd_pmf_dev *dev, int cmd,
+				 struct tee_ioctl_invoke_arg *arg,
+				 struct tee_param *param)
+{
+	memset(arg, 0, sizeof(*arg));
+	memset(param, 0, MAX_TEE_PARAM * sizeof(*param));
+
+	arg->func = cmd;
+	arg->session = dev->session_id;
+	arg->num_params = MAX_TEE_PARAM;
+
+	/* Fill invoke cmd params */
+	param[0].u.memref.size = sizeof(struct ta_pmf_shared_memory);
+	param[0].attr = TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INOUT;
+	param[0].u.memref.shm = dev->fw_shm_pool;
+	param[0].u.memref.shm_offs = 0;
+}
+
+static int amd_pmf_invoke_cmd_enact(struct amd_pmf_dev *dev)
+{
+	struct ta_pmf_shared_memory *ta_sm = NULL;
+	struct tee_param param[MAX_TEE_PARAM];
+	struct tee_ioctl_invoke_arg arg;
+	int ret = 0;
+
+	if (!dev->tee_ctx)
+		return -ENODEV;
+
+	ta_sm = (struct ta_pmf_shared_memory *)dev->shbuf;
+	memset(ta_sm, 0, sizeof(struct ta_pmf_shared_memory));
+	ta_sm->command_id = TA_PMF_COMMAND_POLICY_BUILDER__ENACT_POLICIES;
+	ta_sm->if_version = PMF_TA_IF_VERSION__MAJOR;
+
+	amd_pmf_prepare_args(dev, TA_PMF_COMMAND_POLICY_BUILDER__ENACT_POLICIES, &arg, param);
+
+	ret = tee_client_invoke_func(dev->tee_ctx, &arg, param);
+	if (ret < 0 || arg.ret != 0) {
+		dev_err(dev->dev, "%s failed TEE err: %x, ret:%x\n", __func__, arg.ret, ret);
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static int amd_pmf_invoke_cmd_init(struct amd_pmf_dev *dev)
+{
+	struct ta_pmf_shared_memory *ta_sm = NULL;
+	struct tee_param param[MAX_TEE_PARAM];
+	struct tee_ioctl_invoke_arg arg;
+	int ret = 0;
+
+	if (!dev->tee_ctx) {
+		dev_err(dev->dev, "%s tee_ctx no context\n", __func__);
+		return -ENODEV;
+	}
+
+	ta_sm = (struct ta_pmf_shared_memory *)dev->shbuf;
+	ta_sm->command_id = TA_PMF_COMMAND_POLICY_BUILDER__INITIALIZE;
+	ta_sm->if_version = PMF_TA_IF_VERSION__MAJOR;
+
+	amd_pmf_prepare_args(dev, TA_PMF_COMMAND_POLICY_BUILDER__INITIALIZE, &arg, param);
+
+	ret = tee_client_invoke_func(dev->tee_ctx, &arg, param);
+	if (ret < 0 || arg.ret != 0) {
+		dev_err(dev->dev, "%s failed TEE err: %x, ret:%x\n", __func__, arg.ret, ret);
+		return -EINVAL;
+	}
+
+	return ta_sm->pmf_result;
+}
+
+static void amd_pmf_invoke_cmd(struct work_struct *work)
+{
+	struct amd_pmf_dev *dev = container_of(work, struct amd_pmf_dev, pb_work.work);
+
+	amd_pmf_invoke_cmd_enact(dev);
+	schedule_delayed_work(&dev->pb_work, msecs_to_jiffies(pb_actions_ms));
+}
+
 static int amd_pmf_amdtee_ta_match(struct tee_ioctl_version_data *ver, const void *data)
 {
 	return ver->impl_id == TEE_IMPL_ID_AMDTEE;
@@ -97,10 +184,18 @@ static void amd_pmf_tee_deinit(struct amd_pmf_dev *dev)
 
 int amd_pmf_init_smart_pc(struct amd_pmf_dev *dev)
 {
-	return amd_pmf_tee_init(dev);
+	int ret;
+
+	ret = amd_pmf_tee_init(dev);
+	if (ret)
+		return ret;
+
+	INIT_DELAYED_WORK(&dev->pb_work, amd_pmf_invoke_cmd);
+	return 0;
 }
 
 void amd_pmf_deinit_smart_pc(struct amd_pmf_dev *dev)
 {
+	cancel_delayed_work_sync(&dev->pb_work);
 	amd_pmf_tee_deinit(dev);
 }
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 54+ messages in thread

* [PATCH 03/15] platform/x86/amd/pmf: Change signature of amd_pmf_set_dram_addr
  2023-09-22 17:50 [PATCH 00/15] Introduce PMF Smart PC Solution Builder Feature Shyam Sundar S K
  2023-09-22 17:50 ` [PATCH 01/15] platform/x86/amd/pmf: Add PMF TEE interface Shyam Sundar S K
  2023-09-22 17:50 ` [PATCH 02/15] platform/x86/amd/pmf: Add support PMF-TA interaction Shyam Sundar S K
@ 2023-09-22 17:50 ` Shyam Sundar S K
  2023-09-26 16:52   ` Ilpo Järvinen
  2023-09-22 17:50 ` [PATCH 04/15] platform/x86/amd/pmf: Add support for PMF Policy Binary Shyam Sundar S K
                   ` (11 subsequent siblings)
  14 siblings, 1 reply; 54+ messages in thread
From: Shyam Sundar S K @ 2023-09-22 17:50 UTC (permalink / raw)
  To: hdegoede, markgross, basavaraj.natikar, jikos,
	benjamin.tissoires, alexander.deucher, christian.koenig,
	Xinhui.Pan, airlied, daniel
  Cc: Shyam Sundar S K, amd-gfx, platform-driver-x86, dri-devel,
	Patil.Reddy, linux-input, mario.limonciello

Make amd_pmf_set_dram_addr() as non-static so that same function
can be used across files.

Reviewed-by: Mario Limonciello <mario.limonciello@amd.com>
Signed-off-by: Shyam Sundar S K <Shyam-sundar.S-k@amd.com>
---
 drivers/platform/x86/amd/pmf/core.c | 14 ++++++++------
 drivers/platform/x86/amd/pmf/pmf.h  |  1 +
 2 files changed, 9 insertions(+), 6 deletions(-)

diff --git a/drivers/platform/x86/amd/pmf/core.c b/drivers/platform/x86/amd/pmf/core.c
index 68f1389dda3e..5fb03ed614ff 100644
--- a/drivers/platform/x86/amd/pmf/core.c
+++ b/drivers/platform/x86/amd/pmf/core.c
@@ -251,26 +251,28 @@ static const struct pci_device_id pmf_pci_ids[] = {
 	{ }
 };
 
-static void amd_pmf_set_dram_addr(struct amd_pmf_dev *dev)
+int amd_pmf_set_dram_addr(struct amd_pmf_dev *dev)
 {
 	u64 phys_addr;
 	u32 hi, low;
 
+	/* Get Metrics Table Address */
+	dev->buf = kzalloc(sizeof(dev->m_table), GFP_KERNEL);
+	if (!dev->buf)
+		return -ENOMEM;
+
 	phys_addr = virt_to_phys(dev->buf);
 	hi = phys_addr >> 32;
 	low = phys_addr & GENMASK(31, 0);
 
 	amd_pmf_send_cmd(dev, SET_DRAM_ADDR_HIGH, 0, hi, NULL);
 	amd_pmf_send_cmd(dev, SET_DRAM_ADDR_LOW, 0, low, NULL);
+
+	return 0;
 }
 
 int amd_pmf_init_metrics_table(struct amd_pmf_dev *dev)
 {
-	/* Get Metrics Table Address */
-	dev->buf = kzalloc(sizeof(dev->m_table), GFP_KERNEL);
-	if (!dev->buf)
-		return -ENOMEM;
-
 	INIT_DELAYED_WORK(&dev->work_buffer, amd_pmf_get_metrics);
 
 	amd_pmf_set_dram_addr(dev);
diff --git a/drivers/platform/x86/amd/pmf/pmf.h b/drivers/platform/x86/amd/pmf/pmf.h
index a9333ff6c0a7..ea15ce547d24 100644
--- a/drivers/platform/x86/amd/pmf/pmf.h
+++ b/drivers/platform/x86/amd/pmf/pmf.h
@@ -421,6 +421,7 @@ int amd_pmf_init_metrics_table(struct amd_pmf_dev *dev);
 int amd_pmf_get_power_source(void);
 int apmf_install_handler(struct amd_pmf_dev *pmf_dev);
 int apmf_os_power_slider_update(struct amd_pmf_dev *dev, u8 flag);
+int amd_pmf_set_dram_addr(struct amd_pmf_dev *dev);
 
 /* SPS Layer */
 int amd_pmf_get_pprof_modes(struct amd_pmf_dev *pmf);
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 54+ messages in thread

* [PATCH 04/15] platform/x86/amd/pmf: Add support for PMF Policy Binary
  2023-09-22 17:50 [PATCH 00/15] Introduce PMF Smart PC Solution Builder Feature Shyam Sundar S K
                   ` (2 preceding siblings ...)
  2023-09-22 17:50 ` [PATCH 03/15] platform/x86/amd/pmf: Change signature of amd_pmf_set_dram_addr Shyam Sundar S K
@ 2023-09-22 17:50 ` Shyam Sundar S K
  2023-09-22 18:51   ` Mario Limonciello
                     ` (2 more replies)
  2023-09-22 17:50 ` [PATCH 05/15] platform/x86/amd/pmf: change debugfs init sequence Shyam Sundar S K
                   ` (10 subsequent siblings)
  14 siblings, 3 replies; 54+ messages in thread
From: Shyam Sundar S K @ 2023-09-22 17:50 UTC (permalink / raw)
  To: hdegoede, markgross, basavaraj.natikar, jikos,
	benjamin.tissoires, alexander.deucher, christian.koenig,
	Xinhui.Pan, airlied, daniel
  Cc: Shyam Sundar S K, amd-gfx, platform-driver-x86, dri-devel,
	Patil.Reddy, linux-input, mario.limonciello

PMF Policy binary is a encrypted and signed binary that will be part
of the BIOS. PMF driver via the ACPI interface checks the existence
of Smart PC bit. If the advertised bit is found, PMF driver walks
the acpi namespace to find out the policy binary size and the address
which has to be passed to the TA during the TA init sequence.

The policy binary is comprised of inputs (or the events) and outputs
(or the actions). With the PMF ecosystem, OEMs generate the policy
binary (or could be multiple binaries) that contains a supported set
of inputs and outputs which could be specifically carved out for each
usage segment (or for each user also) that could influence the system
behavior either by enriching the user experience or/and boost/throttle
power limits.

Once the TA init command succeeds, the PMF driver sends the changing
events in the current environment to the TA for a constant sampling
frequency time (the event here could be a lid close or open) and
if the policy binary has corresponding action built within it, the
TA sends the action for it in the subsequent enact command.

If the inputs sent to the TA has no output defined in the policy
binary generated by OEMs, there will be no action to be performed
by the PMF driver.

Example policies:

1) if slider is performance ; set the SPL to 40W
Here PMF driver registers with the platform profile interface and
when the slider position is changed, PMF driver lets the TA know
about this. TA sends back an action to update the Sustained
Power Limit (SPL). PMF driver updates this limit via the PMFW mailbox.

2) if user_away ; then lock the system
Here PMF driver hooks to the AMD SFH driver to know the user presence
and send the inputs to TA and if the condition is met, the TA sends
the action of locking the system. PMF driver generates a uevent and
based on the udev rule in the userland the system gets locked with
systemctl.

The intent here is to provide the OEM's to make a policy to lock the
system when the user is away ; but the userland can make a choice to
ignore it.

and so on.

The OEMs will have an utility to create numerous such policies and
the policies shall be reviewed by AMD before signing and encrypting
them. Policies are shared between operating systems to have seemless user
experience.

Since all this action has to happen via the "amdtee" driver, currently
there is no caller for it in the kernel which can load the amdtee driver.
Without amdtee driver loading onto the system the "tee" calls shall fail
from the PMF driver. Hence an explicit "request_module" has been added
to address this.

Signed-off-by: Shyam Sundar S K <Shyam-sundar.S-k@amd.com>
---
 drivers/platform/x86/amd/pmf/Kconfig  |   1 +
 drivers/platform/x86/amd/pmf/acpi.c   |  37 +++++++
 drivers/platform/x86/amd/pmf/core.c   |  12 +++
 drivers/platform/x86/amd/pmf/pmf.h    | 132 ++++++++++++++++++++++++
 drivers/platform/x86/amd/pmf/tee-if.c | 141 +++++++++++++++++++++++++-
 5 files changed, 321 insertions(+), 2 deletions(-)

diff --git a/drivers/platform/x86/amd/pmf/Kconfig b/drivers/platform/x86/amd/pmf/Kconfig
index 3064bc8ea167..437b78c6d1c5 100644
--- a/drivers/platform/x86/amd/pmf/Kconfig
+++ b/drivers/platform/x86/amd/pmf/Kconfig
@@ -9,6 +9,7 @@ config AMD_PMF
 	depends on POWER_SUPPLY
 	depends on AMD_NB
 	select ACPI_PLATFORM_PROFILE
+	depends on AMDTEE
 	help
 	  This driver provides support for the AMD Platform Management Framework.
 	  The goal is to enhance end user experience by making AMD PCs smarter,
diff --git a/drivers/platform/x86/amd/pmf/acpi.c b/drivers/platform/x86/amd/pmf/acpi.c
index 3fc5e4547d9f..d0512af2cd42 100644
--- a/drivers/platform/x86/amd/pmf/acpi.c
+++ b/drivers/platform/x86/amd/pmf/acpi.c
@@ -286,6 +286,43 @@ int apmf_install_handler(struct amd_pmf_dev *pmf_dev)
 	return 0;
 }
 
+static acpi_status apmf_walk_resources(struct acpi_resource *res, void *data)
+{
+	struct amd_pmf_dev *dev = data;
+
+	switch (res->type) {
+	case ACPI_RESOURCE_TYPE_ADDRESS64:
+		dev->policy_addr = res->data.address64.address.minimum;
+		dev->policy_sz = res->data.address64.address.address_length;
+		break;
+	case ACPI_RESOURCE_TYPE_FIXED_MEMORY32:
+		dev->policy_addr = res->data.fixed_memory32.address;
+		dev->policy_sz = res->data.fixed_memory32.address_length;
+		break;
+	}
+
+	if (!dev->policy_addr || dev->policy_sz > POLICY_BUF_MAX_SZ || dev->policy_sz == 0) {
+		pr_err("Incorrect Policy params, possibly a SBIOS bug\n");
+		return AE_ERROR;
+	}
+
+	return AE_OK;
+}
+
+int apmf_check_smart_pc(struct amd_pmf_dev *pmf_dev)
+{
+	acpi_handle ahandle = ACPI_HANDLE(pmf_dev->dev);
+	acpi_status status;
+
+	status = acpi_walk_resources(ahandle, METHOD_NAME__CRS, apmf_walk_resources, pmf_dev);
+	if (ACPI_FAILURE(status)) {
+		dev_err(pmf_dev->dev, "acpi_walk_resources failed\n");
+		return status;
+	}
+
+	return 0;
+}
+
 void apmf_acpi_deinit(struct amd_pmf_dev *pmf_dev)
 {
 	acpi_handle ahandle = ACPI_HANDLE(pmf_dev->dev);
diff --git a/drivers/platform/x86/amd/pmf/core.c b/drivers/platform/x86/amd/pmf/core.c
index 5fb03ed614ff..6f36c43e081e 100644
--- a/drivers/platform/x86/amd/pmf/core.c
+++ b/drivers/platform/x86/amd/pmf/core.c
@@ -376,6 +376,18 @@ static int amd_pmf_probe(struct platform_device *pdev)
 		return -ENOMEM;
 
 	dev->dev = &pdev->dev;
+	err = apmf_check_smart_pc(dev);
+	if (!err) {
+		/* in order for Smart PC solution to work it has a hard dependency
+		 * on the amdtee driver to be loaded first even before the PMF driver
+		 * loads. PMF ASL has a _CRS method that advertises the existence
+		 * of Smart PC bit. If this information is present, use this to
+		 * explicitly probe the amdtee driver, so that "tee" plumbing is done
+		 * before the PMF Smart PC init happens.
+		 */
+		if (request_module("amdtee"))
+			pr_err("Failed to load amdtee. PMF Smart PC not enabled!\n");
+	}
 
 	rdev = pci_get_domain_bus_and_slot(0, 0, PCI_DEVFN(0, 0));
 	if (!rdev || !pci_match_id(pmf_pci_ids, rdev)) {
diff --git a/drivers/platform/x86/amd/pmf/pmf.h b/drivers/platform/x86/amd/pmf/pmf.h
index ea15ce547d24..81acf2a37366 100644
--- a/drivers/platform/x86/amd/pmf/pmf.h
+++ b/drivers/platform/x86/amd/pmf/pmf.h
@@ -13,6 +13,8 @@
 
 #include <linux/acpi.h>
 #include <linux/platform_profile.h>
+#define POLICY_BUF_MAX_SZ		0x4b000
+#define POLICY_SIGN_COOKIE		0x31535024
 
 /* APMF Functions */
 #define APMF_FUNC_VERIFY_INTERFACE			0
@@ -59,8 +61,20 @@
 #define ARG_NONE 0
 #define AVG_SAMPLE_SIZE 3
 
+/* Policy Actions */
+#define PMF_POLICY_SPL						2
+#define PMF_POLICY_SPPT						3
+#define PMF_POLICY_FPPT						4
+#define PMF_POLICY_SPPT_APU_ONLY				5
+#define PMF_POLICY_STT_MIN					6
+#define PMF_POLICY_STT_SKINTEMP_APU				7
+#define PMF_POLICY_STT_SKINTEMP_HS2				8
+
 /* TA macros */
 #define PMF_TA_IF_VERSION__MAJOR				1
+#define TA_PMF_ACTION_MAX					32
+#define TA_PMF_UNDO_MAX						8
+#define MAX_OPERATION_PARAMS					4
 
 /* AMD PMF BIOS interfaces */
 struct apmf_verify_interface {
@@ -183,11 +197,16 @@ struct amd_pmf_dev {
 	bool cnqf_supported;
 	struct notifier_block pwr_src_notifier;
 	/* Smart PC solution builder */
+	unsigned char *policy_buf;
+	u32 policy_sz;
 	struct tee_context *tee_ctx;
 	struct tee_shm *fw_shm_pool;
 	u32 session_id;
 	void *shbuf;
 	struct delayed_work pb_work;
+	struct pmf_action_table *prev_data;
+	u64 policy_addr;
+	void *policy_base;
 	bool smart_pc_enabled;
 };
 
@@ -399,17 +418,129 @@ struct apmf_dyn_slider_output {
 	struct apmf_cnqf_power_set ps[APMF_CNQF_MAX];
 } __packed;
 
+/* Smart PC - TA internals */
+enum ta_slider {
+	TA_BEST_BATTERY, /* Best Battery */
+	TA_BETTER_BATTERY, /* Better Battery */
+	TA_BETTER_PERFORMANCE, /* Better Performance */
+	TA_BEST_PERFORMANCE, /* Best Performance */
+	TA_MAX,
+};
+
 /* cmd ids for TA communication */
 enum ta_pmf_command {
 	TA_PMF_COMMAND_POLICY_BUILDER__INITIALIZE,
 	TA_PMF_COMMAND_POLICY_BUILDER__ENACT_POLICIES
 };
 
+enum ta_pmf_error_type {
+	TA_PMF_TYPE__SUCCESS,
+	TA_PMF_ERROR_TYPE__GENERIC,
+	TA_PMF_ERROR_TYPE__CRYPTO,
+	TA_PMF_ERROR_TYPE__CRYPTO_VALIDATE,
+	TA_PMF_ERROR_TYPE__CRYPTO_VERIFY_OEM,
+	TA_PMF_ERROR_TYPE__POLICY_BUILDER,
+	TA_PMF_ERROR_TYPE__PB_CONVERT,
+	TA_PMF_ERROR_TYPE__PB_SETUP,
+	TA_PMF_ERROR_TYPE__PB_ENACT,
+	TA_PMF_ERROR_TYPE__ASD_GET_DEVICE_INFO,
+	TA_PMF_ERROR_TYPE__ASD_GET_DEVICE_PCIE_INFO,
+	TA_PMF_ERROR_TYPE__SYS_DRV_FW_VALIDATION,
+	TA_PMF_ERROR_TYPE__MAX,
+};
+
+struct pmf_action_table {
+	unsigned long spl; /* in mW */
+	unsigned long sppt; /* in mW */
+	unsigned long sppt_apuonly; /* in mW */
+	unsigned long fppt; /* in mW */
+	unsigned long stt_minlimit; /* in mW */
+	unsigned long stt_skintemp_apu; /* in C */
+	unsigned long stt_skintemp_hs2; /* in C */
+};
+
+/* Input conditions */
+struct ta_pmf_condition_info {
+	u32 power_source;
+	u32 bat_percentage;
+	u32 power_slider;
+	u32 lid_state;
+	bool user_present;
+	u32 rsvd1[2];
+	u32 monitor_count;
+	u32 rsvd2[2];
+	u32 bat_design;
+	u32 full_charge_capacity;
+	int drain_rate;
+	bool user_engaged;
+	u32 device_state;
+	u32 socket_power;
+	u32 skin_temperature;
+	u32 rsvd3[5];
+	u32 ambient_light;
+	u32 length;
+	u32 avg_c0residency;
+	u32 max_c0residency;
+	u32 s0i3_entry;
+	u32 gfx_busy;
+	u32 rsvd4[7];
+	bool camera_state;
+	u32 workload_type;
+	u32 display_type;
+	u32 display_state;
+	u32 rsvd5[150];
+};
+
+struct ta_pmf_load_policy_table {
+	u32 table_size;
+	u8 table[POLICY_BUF_MAX_SZ];
+};
+
+/* TA initialization params */
+struct ta_pmf_init_table {
+	u32 frequency; /* SMU sampling frequency */
+	bool validate;
+	bool sku_check;
+	bool metadata_macrocheck;
+	struct ta_pmf_load_policy_table policies_table;
+};
+
+/* Everything the TA needs to Enact Policies */
+struct ta_pmf_enact_table {
+	struct ta_pmf_condition_info ev_info;
+	u32 name;
+};
+
+struct ta_pmf_action {
+	u32 action_index;
+	u32 value;
+};
+
+/* output actions from TA */
+struct ta_pmf_enact_result {
+	u32 actions_count;
+	struct ta_pmf_action actions_list[TA_PMF_ACTION_MAX];
+	u32 undo_count;
+	struct ta_pmf_action undo_list[TA_PMF_UNDO_MAX];
+};
+
+union ta_pmf_input {
+	struct ta_pmf_enact_table enact_table;
+	struct ta_pmf_init_table init_table;
+};
+
+union ta_pmf_output {
+	struct ta_pmf_enact_result policy_apply_table;
+	u32 rsvd[906];
+};
+
 struct ta_pmf_shared_memory {
 	int command_id;
 	int resp_id;
 	u32 pmf_result;
 	u32 if_version;
+	union ta_pmf_output pmf_output;
+	union ta_pmf_input pmf_input;
 };
 
 /* Core Layer */
@@ -460,4 +591,5 @@ extern const struct attribute_group cnqf_feature_attribute_group;
 /* Smart PC builder Layer*/
 int amd_pmf_init_smart_pc(struct amd_pmf_dev *dev);
 void amd_pmf_deinit_smart_pc(struct amd_pmf_dev *dev);
+int apmf_check_smart_pc(struct amd_pmf_dev *pmf_dev);
 #endif /* PMF_H */
diff --git a/drivers/platform/x86/amd/pmf/tee-if.c b/drivers/platform/x86/amd/pmf/tee-if.c
index 1fce04beacb3..a8b05e746efd 100644
--- a/drivers/platform/x86/amd/pmf/tee-if.c
+++ b/drivers/platform/x86/amd/pmf/tee-if.c
@@ -42,9 +42,77 @@ static void amd_pmf_prepare_args(struct amd_pmf_dev *dev, int cmd,
 	param[0].u.memref.shm_offs = 0;
 }
 
+static void amd_pmf_apply_policies(struct amd_pmf_dev *dev, struct ta_pmf_enact_result *out)
+{
+	u32 val;
+	int idx;
+
+	for (idx = 0; idx < out->actions_count; idx++) {
+		val = out->actions_list[idx].value;
+		switch (out->actions_list[idx].action_index) {
+		case PMF_POLICY_SPL:
+			if (dev->prev_data->spl != val) {
+				amd_pmf_send_cmd(dev, SET_SPL, false, val, NULL);
+				dev_dbg(dev->dev, "update SPL : %d\n", val);
+				dev->prev_data->spl = val;
+			}
+			break;
+
+		case PMF_POLICY_SPPT:
+			if (dev->prev_data->sppt != val) {
+				amd_pmf_send_cmd(dev, SET_SPPT, false, val, NULL);
+				dev_dbg(dev->dev, "update SPPT : %d\n", val);
+				dev->prev_data->sppt = val;
+			}
+			break;
+
+		case PMF_POLICY_FPPT:
+			if (dev->prev_data->fppt != val) {
+				amd_pmf_send_cmd(dev, SET_FPPT, false, val, NULL);
+				dev_dbg(dev->dev, "update FPPT : %d\n", val);
+				dev->prev_data->fppt = val;
+			}
+			break;
+
+		case PMF_POLICY_SPPT_APU_ONLY:
+			if (dev->prev_data->sppt_apuonly != val) {
+				amd_pmf_send_cmd(dev, SET_SPPT_APU_ONLY, false, val, NULL);
+				dev_dbg(dev->dev, "update SPPT_APU_ONLY : %d\n", val);
+				dev->prev_data->sppt_apuonly = val;
+			}
+			break;
+
+		case PMF_POLICY_STT_MIN:
+			if (dev->prev_data->stt_minlimit != val) {
+				amd_pmf_send_cmd(dev, SET_STT_MIN_LIMIT, false, val, NULL);
+				dev_dbg(dev->dev, "update STT_MIN : %d\n", val);
+				dev->prev_data->stt_minlimit = val;
+			}
+			break;
+
+		case PMF_POLICY_STT_SKINTEMP_APU:
+			if (dev->prev_data->stt_skintemp_apu != val) {
+				amd_pmf_send_cmd(dev, SET_STT_LIMIT_APU, false, val, NULL);
+				dev_dbg(dev->dev, "update STT_SKINTEMP_APU : %d\n", val);
+				dev->prev_data->stt_skintemp_apu = val;
+			}
+			break;
+
+		case PMF_POLICY_STT_SKINTEMP_HS2:
+			if (dev->prev_data->stt_skintemp_hs2 != val) {
+				amd_pmf_send_cmd(dev, SET_STT_LIMIT_HS2, false, val, NULL);
+				dev_dbg(dev->dev, "update STT_SKINTEMP_HS2 : %d\n", val);
+				dev->prev_data->stt_skintemp_hs2 = val;
+			}
+			break;
+		}
+	}
+}
+
 static int amd_pmf_invoke_cmd_enact(struct amd_pmf_dev *dev)
 {
 	struct ta_pmf_shared_memory *ta_sm = NULL;
+	struct ta_pmf_enact_result *out = NULL;
 	struct tee_param param[MAX_TEE_PARAM];
 	struct tee_ioctl_invoke_arg arg;
 	int ret = 0;
@@ -52,7 +120,10 @@ static int amd_pmf_invoke_cmd_enact(struct amd_pmf_dev *dev)
 	if (!dev->tee_ctx)
 		return -ENODEV;
 
+	memset(dev->shbuf, 0, dev->policy_sz);
 	ta_sm = (struct ta_pmf_shared_memory *)dev->shbuf;
+	out = &ta_sm->pmf_output.policy_apply_table;
+
 	memset(ta_sm, 0, sizeof(struct ta_pmf_shared_memory));
 	ta_sm->command_id = TA_PMF_COMMAND_POLICY_BUILDER__ENACT_POLICIES;
 	ta_sm->if_version = PMF_TA_IF_VERSION__MAJOR;
@@ -65,6 +136,12 @@ static int amd_pmf_invoke_cmd_enact(struct amd_pmf_dev *dev)
 		return -EINVAL;
 	}
 
+	if (ta_sm->pmf_result == TA_PMF_TYPE__SUCCESS && out->actions_count) {
+		dev_dbg(dev->dev, "action count:%d result:%x\n", out->actions_count,
+			ta_sm->pmf_result);
+		amd_pmf_apply_policies(dev, out);
+	}
+
 	return 0;
 }
 
@@ -72,6 +149,7 @@ static int amd_pmf_invoke_cmd_init(struct amd_pmf_dev *dev)
 {
 	struct ta_pmf_shared_memory *ta_sm = NULL;
 	struct tee_param param[MAX_TEE_PARAM];
+	struct ta_pmf_init_table *in = NULL;
 	struct tee_ioctl_invoke_arg arg;
 	int ret = 0;
 
@@ -80,10 +158,20 @@ static int amd_pmf_invoke_cmd_init(struct amd_pmf_dev *dev)
 		return -ENODEV;
 	}
 
+	dev_dbg(dev->dev, "Policy Binary size: %d bytes\n", dev->policy_sz);
+	memset(dev->shbuf, 0, dev->policy_sz);
 	ta_sm = (struct ta_pmf_shared_memory *)dev->shbuf;
+	in = &ta_sm->pmf_input.init_table;
+
 	ta_sm->command_id = TA_PMF_COMMAND_POLICY_BUILDER__INITIALIZE;
 	ta_sm->if_version = PMF_TA_IF_VERSION__MAJOR;
+	in->metadata_macrocheck = false;
+	in->sku_check = false;
+	in->validate = true;
+	in->frequency = pb_actions_ms;
+	in->policies_table.table_size = dev->policy_sz;
 
+	memcpy(in->policies_table.table, dev->policy_buf, dev->policy_sz);
 	amd_pmf_prepare_args(dev, TA_PMF_COMMAND_POLICY_BUILDER__INITIALIZE, &arg, param);
 
 	ret = tee_client_invoke_func(dev->tee_ctx, &arg, param);
@@ -103,6 +191,47 @@ static void amd_pmf_invoke_cmd(struct work_struct *work)
 	schedule_delayed_work(&dev->pb_work, msecs_to_jiffies(pb_actions_ms));
 }
 
+static int amd_pmf_start_policy_engine(struct amd_pmf_dev *dev)
+{
+	u32 cookie, length;
+	int res;
+
+	cookie = readl(dev->policy_buf + 0x10);
+	length = readl(dev->policy_buf + 0x14);
+
+	if (cookie != POLICY_SIGN_COOKIE || !length)
+		return -EINVAL;
+
+	/* update the actual length */
+	dev->policy_sz = length + 512;
+	res = amd_pmf_invoke_cmd_init(dev);
+	if (res == TA_PMF_TYPE__SUCCESS) {
+		/* now its safe to announce that smart pc is enabled */
+		dev->smart_pc_enabled = 1;
+		schedule_delayed_work(&dev->pb_work, msecs_to_jiffies(pb_actions_ms * 3));
+	} else {
+		dev_err(dev->dev, "%s ta invoke_cmd_init failed err: %x\n", __func__, res);
+		return res;
+	}
+
+	return 0;
+}
+
+static int amd_pmf_get_bios_buffer(struct amd_pmf_dev *dev)
+{
+	dev->policy_buf = kzalloc(dev->policy_sz, GFP_KERNEL);
+	if (!dev->policy_buf)
+		return -ENOMEM;
+
+	dev->policy_base = ioremap(dev->policy_addr, dev->policy_sz);
+	if (!dev->policy_base)
+		return -ENOMEM;
+
+	memcpy(dev->policy_buf, dev->policy_base, dev->policy_sz);
+
+	return amd_pmf_start_policy_engine(dev);
+}
+
 static int amd_pmf_amdtee_ta_match(struct tee_ioctl_version_data *ver, const void *data)
 {
 	return ver->impl_id == TEE_IMPL_ID_AMDTEE;
@@ -149,7 +278,7 @@ static int amd_pmf_tee_init(struct amd_pmf_dev *dev)
 		goto out_ctx;
 	}
 
-	size = sizeof(struct ta_pmf_shared_memory);
+	size = sizeof(struct ta_pmf_shared_memory) + dev->policy_sz;
 	dev->fw_shm_pool = tee_shm_alloc_kernel_buf(dev->tee_ctx, size);
 	if (IS_ERR(dev->fw_shm_pool)) {
 		dev_err(dev->dev, "%s: tee_shm_alloc_kernel_buf failed\n", __func__);
@@ -191,11 +320,19 @@ int amd_pmf_init_smart_pc(struct amd_pmf_dev *dev)
 		return ret;
 
 	INIT_DELAYED_WORK(&dev->pb_work, amd_pmf_invoke_cmd);
-	return 0;
+	amd_pmf_set_dram_addr(dev);
+	amd_pmf_get_bios_buffer(dev);
+	dev->prev_data = kzalloc(sizeof(*dev->prev_data), GFP_KERNEL);
+	if (!dev->prev_data)
+		return -ENOMEM;
+
+	return dev->smart_pc_enabled;
 }
 
 void amd_pmf_deinit_smart_pc(struct amd_pmf_dev *dev)
 {
+	kfree(dev->prev_data);
+	kfree(dev->policy_buf);
 	cancel_delayed_work_sync(&dev->pb_work);
 	amd_pmf_tee_deinit(dev);
 }
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 54+ messages in thread

* [PATCH 05/15] platform/x86/amd/pmf: change debugfs init sequence
  2023-09-22 17:50 [PATCH 00/15] Introduce PMF Smart PC Solution Builder Feature Shyam Sundar S K
                   ` (3 preceding siblings ...)
  2023-09-22 17:50 ` [PATCH 04/15] platform/x86/amd/pmf: Add support for PMF Policy Binary Shyam Sundar S K
@ 2023-09-22 17:50 ` Shyam Sundar S K
  2023-09-26 16:53   ` Ilpo Järvinen
  2023-09-22 17:50 ` [PATCH 06/15] platform/x86/amd/pmf: Add support to get inputs from other subsystems Shyam Sundar S K
                   ` (9 subsequent siblings)
  14 siblings, 1 reply; 54+ messages in thread
From: Shyam Sundar S K @ 2023-09-22 17:50 UTC (permalink / raw)
  To: hdegoede, markgross, basavaraj.natikar, jikos,
	benjamin.tissoires, alexander.deucher, christian.koenig,
	Xinhui.Pan, airlied, daniel
  Cc: Shyam Sundar S K, amd-gfx, platform-driver-x86, dri-devel,
	Patil.Reddy, linux-input, mario.limonciello

amd_pmf_dbgfs_register() needs to be called before amd_pmf_init_features().
Hence change the sequence.

Reviewed-by: Mario Limonciello <mario.limonciello@amd.com>
Signed-off-by: Shyam Sundar S K <Shyam-sundar.S-k@amd.com>
---
 drivers/platform/x86/amd/pmf/core.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/platform/x86/amd/pmf/core.c b/drivers/platform/x86/amd/pmf/core.c
index 6f36c43e081e..dbfe7c1d6fc4 100644
--- a/drivers/platform/x86/amd/pmf/core.c
+++ b/drivers/platform/x86/amd/pmf/core.c
@@ -427,9 +427,9 @@ static int amd_pmf_probe(struct platform_device *pdev)
 
 	apmf_acpi_init(dev);
 	platform_set_drvdata(pdev, dev);
+	amd_pmf_dbgfs_register(dev);
 	amd_pmf_init_features(dev);
 	apmf_install_handler(dev);
-	amd_pmf_dbgfs_register(dev);
 
 	dev_info(dev->dev, "registered PMF device successfully\n");
 
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 54+ messages in thread

* [PATCH 06/15] platform/x86/amd/pmf: Add support to get inputs from other subsystems
  2023-09-22 17:50 [PATCH 00/15] Introduce PMF Smart PC Solution Builder Feature Shyam Sundar S K
                   ` (4 preceding siblings ...)
  2023-09-22 17:50 ` [PATCH 05/15] platform/x86/amd/pmf: change debugfs init sequence Shyam Sundar S K
@ 2023-09-22 17:50 ` Shyam Sundar S K
  2023-09-26 17:08   ` Ilpo Järvinen
  2023-09-22 17:50 ` [PATCH 07/15] platform/x86/amd/pmf: Add support update p3t limit Shyam Sundar S K
                   ` (8 subsequent siblings)
  14 siblings, 1 reply; 54+ messages in thread
From: Shyam Sundar S K @ 2023-09-22 17:50 UTC (permalink / raw)
  To: hdegoede, markgross, basavaraj.natikar, jikos,
	benjamin.tissoires, alexander.deucher, christian.koenig,
	Xinhui.Pan, airlied, daniel
  Cc: Shyam Sundar S K, amd-gfx, platform-driver-x86, dri-devel,
	Patil.Reddy, linux-input, mario.limonciello

PMF driver sends changing inputs from each subystem to TA for evaluating
the conditions in the policy binary.

Add initial support of plumbing in the PMF driver for Smart PC to get
information from other subsystems in the kernel.

Signed-off-by: Shyam Sundar S K <Shyam-sundar.S-k@amd.com>
---
 drivers/platform/x86/amd/pmf/Makefile |   2 +-
 drivers/platform/x86/amd/pmf/pmf.h    |  18 ++++
 drivers/platform/x86/amd/pmf/spc.c    | 118 ++++++++++++++++++++++++++
 drivers/platform/x86/amd/pmf/tee-if.c |   3 +
 4 files changed, 140 insertions(+), 1 deletion(-)
 create mode 100644 drivers/platform/x86/amd/pmf/spc.c

diff --git a/drivers/platform/x86/amd/pmf/Makefile b/drivers/platform/x86/amd/pmf/Makefile
index d2746ee7369f..6b26e48ce8ad 100644
--- a/drivers/platform/x86/amd/pmf/Makefile
+++ b/drivers/platform/x86/amd/pmf/Makefile
@@ -7,4 +7,4 @@
 obj-$(CONFIG_AMD_PMF) += amd-pmf.o
 amd-pmf-objs := core.o acpi.o sps.o \
 		auto-mode.o cnqf.o \
-		tee-if.o
+		tee-if.o spc.o
diff --git a/drivers/platform/x86/amd/pmf/pmf.h b/drivers/platform/x86/amd/pmf/pmf.h
index 81acf2a37366..e64b4d285624 100644
--- a/drivers/platform/x86/amd/pmf/pmf.h
+++ b/drivers/platform/x86/amd/pmf/pmf.h
@@ -146,6 +146,21 @@ struct smu_pmf_metrics {
 	u16 infra_gfx_maxfreq; /* in MHz */
 	u16 skin_temp; /* in centi-Celsius */
 	u16 device_state;
+	u16 curtemp; /* in centi-Celsius */
+	u16 filter_alpha_value;
+	u16 avg_gfx_clkfrequency;
+	u16 avg_fclk_frequency;
+	u16 avg_gfx_activity;
+	u16 avg_socclk_frequency;
+	u16 avg_vclk_frequency;
+	u16 avg_vcn_activity;
+	u16 avg_dram_reads;
+	u16 avg_dram_writes;
+	u16 avg_socket_power;
+	u16 avg_core_power[2];
+	u16 avg_core_c0residency[16];
+	u16 spare1;
+	u32 metrics_counter;
 } __packed;
 
 enum amd_stt_skin_temp {
@@ -592,4 +607,7 @@ extern const struct attribute_group cnqf_feature_attribute_group;
 int amd_pmf_init_smart_pc(struct amd_pmf_dev *dev);
 void amd_pmf_deinit_smart_pc(struct amd_pmf_dev *dev);
 int apmf_check_smart_pc(struct amd_pmf_dev *pmf_dev);
+
+/* Smart PC - TA interfaces */
+void amd_pmf_populate_ta_inputs(struct amd_pmf_dev *dev, struct ta_pmf_enact_table *in);
 #endif /* PMF_H */
diff --git a/drivers/platform/x86/amd/pmf/spc.c b/drivers/platform/x86/amd/pmf/spc.c
new file mode 100644
index 000000000000..08159cd5f853
--- /dev/null
+++ b/drivers/platform/x86/amd/pmf/spc.c
@@ -0,0 +1,118 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * AMD Platform Management Framework Driver - Smart PC Capabilities
+ *
+ * Copyright (c) 2023, Advanced Micro Devices, Inc.
+ * All Rights Reserved.
+ *
+ * Authors: Shyam Sundar S K <Shyam-sundar.S-k@amd.com>
+ *          Patil Rajesh Reddy <Patil.Reddy@amd.com>
+ */
+
+#include <acpi/button.h>
+#include <linux/power_supply.h>
+#include "pmf.h"
+
+static void amd_pmf_get_smu_info(struct amd_pmf_dev *dev, struct ta_pmf_enact_table *in)
+{
+	u16 max, avg = 0;
+	int i;
+
+	memset(dev->buf, 0, sizeof(dev->m_table));
+	amd_pmf_send_cmd(dev, SET_TRANSFER_TABLE, 0, 7, NULL);
+	memcpy(&dev->m_table, dev->buf, sizeof(dev->m_table));
+
+	in->ev_info.socket_power = dev->m_table.apu_power + dev->m_table.dgpu_power;
+	in->ev_info.skin_temperature = dev->m_table.skin_temp;
+
+	/* get the avg C0 residency of all the cores */
+	for (i = 0; i < ARRAY_SIZE(dev->m_table.avg_core_c0residency); i++)
+		avg += dev->m_table.avg_core_c0residency[i];
+
+	/* get the max C0 residency of all the cores */
+	max = dev->m_table.avg_core_c0residency[0];
+	for (i = 1; i < ARRAY_SIZE(dev->m_table.avg_core_c0residency); i++) {
+		if (dev->m_table.avg_core_c0residency[i] > max)
+			max = dev->m_table.avg_core_c0residency[i];
+	}
+
+	in->ev_info.avg_c0residency = avg / ARRAY_SIZE(dev->m_table.avg_core_c0residency);
+	in->ev_info.max_c0residency = max;
+	in->ev_info.gfx_busy = dev->m_table.avg_gfx_activity;
+}
+
+static const char * const pmf_battery_supply_name[] = {
+	"BATT",
+	"BAT0",
+};
+
+static int get_battery_prop(enum power_supply_property prop)
+{
+	union power_supply_propval value;
+	struct power_supply *psy;
+	int i, ret = -EINVAL;
+
+	for (i = 0; i < ARRAY_SIZE(pmf_battery_supply_name); i++) {
+		psy = power_supply_get_by_name(pmf_battery_supply_name[i]);
+		if (!psy)
+			continue;
+
+		ret = power_supply_get_property(psy, prop, &value);
+		if (ret) {
+			power_supply_put(psy);
+			return ret;
+		}
+	}
+
+	return value.intval;
+}
+
+static int amd_pmf_get_battery_info(struct amd_pmf_dev *dev, struct ta_pmf_enact_table *in)
+{
+	int val;
+
+	val = get_battery_prop(POWER_SUPPLY_PROP_PRESENT);
+	if (val != 1)
+		return -EINVAL;
+
+	in->ev_info.bat_percentage = get_battery_prop(POWER_SUPPLY_PROP_CAPACITY);
+	/* all values in mWh metrics */
+	in->ev_info.bat_design = get_battery_prop(POWER_SUPPLY_PROP_ENERGY_FULL_DESIGN) / 1000;
+	in->ev_info.full_charge_capacity = get_battery_prop(POWER_SUPPLY_PROP_ENERGY_FULL) / 1000;
+	in->ev_info.drain_rate = get_battery_prop(POWER_SUPPLY_PROP_POWER_NOW) / 1000;
+
+	return 0;
+}
+
+static int amd_pmf_get_slider_info(struct amd_pmf_dev *dev, struct ta_pmf_enact_table *in)
+{
+	int val;
+
+	switch (dev->current_profile) {
+	case PLATFORM_PROFILE_PERFORMANCE:
+		val = TA_BEST_PERFORMANCE;
+		break;
+	case PLATFORM_PROFILE_BALANCED:
+		val = TA_BETTER_PERFORMANCE;
+		break;
+	case PLATFORM_PROFILE_LOW_POWER:
+		val = TA_BEST_BATTERY;
+		break;
+	default:
+		dev_err(dev->dev, "Unknown Platform Profile.\n");
+		return -EOPNOTSUPP;
+	}
+	in->ev_info.power_slider = val;
+
+	return 0;
+}
+
+void amd_pmf_populate_ta_inputs(struct amd_pmf_dev *dev, struct ta_pmf_enact_table *in)
+{
+	/* TA side lid open is 1 and close is 0, hence the ! here */
+	in->ev_info.lid_state = !acpi_lid_open();
+	in->ev_info.power_source = amd_pmf_get_power_source();
+	amd_pmf_get_smu_info(dev, in);
+	amd_pmf_get_battery_info(dev, in);
+	amd_pmf_get_slider_info(dev, in);
+}
diff --git a/drivers/platform/x86/amd/pmf/tee-if.c b/drivers/platform/x86/amd/pmf/tee-if.c
index a8b05e746efd..eb25d5ce3a9a 100644
--- a/drivers/platform/x86/amd/pmf/tee-if.c
+++ b/drivers/platform/x86/amd/pmf/tee-if.c
@@ -113,6 +113,7 @@ static int amd_pmf_invoke_cmd_enact(struct amd_pmf_dev *dev)
 {
 	struct ta_pmf_shared_memory *ta_sm = NULL;
 	struct ta_pmf_enact_result *out = NULL;
+	struct ta_pmf_enact_table *in = NULL;
 	struct tee_param param[MAX_TEE_PARAM];
 	struct tee_ioctl_invoke_arg arg;
 	int ret = 0;
@@ -123,11 +124,13 @@ static int amd_pmf_invoke_cmd_enact(struct amd_pmf_dev *dev)
 	memset(dev->shbuf, 0, dev->policy_sz);
 	ta_sm = (struct ta_pmf_shared_memory *)dev->shbuf;
 	out = &ta_sm->pmf_output.policy_apply_table;
+	in = &ta_sm->pmf_input.enact_table;
 
 	memset(ta_sm, 0, sizeof(struct ta_pmf_shared_memory));
 	ta_sm->command_id = TA_PMF_COMMAND_POLICY_BUILDER__ENACT_POLICIES;
 	ta_sm->if_version = PMF_TA_IF_VERSION__MAJOR;
 
+	amd_pmf_populate_ta_inputs(dev, in);
 	amd_pmf_prepare_args(dev, TA_PMF_COMMAND_POLICY_BUILDER__ENACT_POLICIES, &arg, param);
 
 	ret = tee_client_invoke_func(dev->tee_ctx, &arg, param);
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 54+ messages in thread

* [PATCH 07/15] platform/x86/amd/pmf: Add support update p3t limit
  2023-09-22 17:50 [PATCH 00/15] Introduce PMF Smart PC Solution Builder Feature Shyam Sundar S K
                   ` (5 preceding siblings ...)
  2023-09-22 17:50 ` [PATCH 06/15] platform/x86/amd/pmf: Add support to get inputs from other subsystems Shyam Sundar S K
@ 2023-09-22 17:50 ` Shyam Sundar S K
  2023-09-27 12:19   ` Ilpo Järvinen
  2023-09-22 17:50 ` [PATCH 08/15] platform/x86/amd/pmf: Add support to update system state Shyam Sundar S K
                   ` (7 subsequent siblings)
  14 siblings, 1 reply; 54+ messages in thread
From: Shyam Sundar S K @ 2023-09-22 17:50 UTC (permalink / raw)
  To: hdegoede, markgross, basavaraj.natikar, jikos,
	benjamin.tissoires, alexander.deucher, christian.koenig,
	Xinhui.Pan, airlied, daniel
  Cc: Shyam Sundar S K, amd-gfx, platform-driver-x86, dri-devel,
	Patil.Reddy, linux-input, mario.limonciello

P3T (Peak Package Power Limit) is a metric within the SMU controller
that can influence the power limits. Add support from the driver
to update P3T limits accordingly.

Reviewed-by: Mario Limonciello <mario.limonciello@amd.com>
Signed-off-by: Shyam Sundar S K <Shyam-sundar.S-k@amd.com>
---
 drivers/platform/x86/amd/pmf/pmf.h    | 3 +++
 drivers/platform/x86/amd/pmf/tee-if.c | 8 ++++++++
 2 files changed, 11 insertions(+)

diff --git a/drivers/platform/x86/amd/pmf/pmf.h b/drivers/platform/x86/amd/pmf/pmf.h
index e64b4d285624..897f61b75e2f 100644
--- a/drivers/platform/x86/amd/pmf/pmf.h
+++ b/drivers/platform/x86/amd/pmf/pmf.h
@@ -46,6 +46,7 @@
 #define GET_STT_MIN_LIMIT	0x1F
 #define GET_STT_LIMIT_APU	0x20
 #define GET_STT_LIMIT_HS2	0x21
+#define SET_P3T				0x23 /* P3T: Peak Package Power Limit */
 
 /* OS slider update notification */
 #define DC_BEST_PERF		0
@@ -69,6 +70,7 @@
 #define PMF_POLICY_STT_MIN					6
 #define PMF_POLICY_STT_SKINTEMP_APU				7
 #define PMF_POLICY_STT_SKINTEMP_HS2				8
+#define PMF_POLICY_P3T						38
 
 /* TA macros */
 #define PMF_TA_IF_VERSION__MAJOR				1
@@ -472,6 +474,7 @@ struct pmf_action_table {
 	unsigned long stt_minlimit; /* in mW */
 	unsigned long stt_skintemp_apu; /* in C */
 	unsigned long stt_skintemp_hs2; /* in C */
+	unsigned long p3t_limit; /* in mW */
 };
 
 /* Input conditions */
diff --git a/drivers/platform/x86/amd/pmf/tee-if.c b/drivers/platform/x86/amd/pmf/tee-if.c
index eb25d5ce3a9a..883dd143375a 100644
--- a/drivers/platform/x86/amd/pmf/tee-if.c
+++ b/drivers/platform/x86/amd/pmf/tee-if.c
@@ -105,6 +105,14 @@ static void amd_pmf_apply_policies(struct amd_pmf_dev *dev, struct ta_pmf_enact_
 				dev->prev_data->stt_skintemp_hs2 = val;
 			}
 			break;
+
+		case PMF_POLICY_P3T:
+			if (dev->prev_data->p3t_limit != val) {
+				amd_pmf_send_cmd(dev, SET_P3T, false, val, NULL);
+				dev_dbg(dev->dev, "update P3T : %d\n", val);
+				dev->prev_data->p3t_limit = val;
+			}
+			break;
 		}
 	}
 }
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 54+ messages in thread

* [PATCH 08/15] platform/x86/amd/pmf: Add support to update system state
  2023-09-22 17:50 [PATCH 00/15] Introduce PMF Smart PC Solution Builder Feature Shyam Sundar S K
                   ` (6 preceding siblings ...)
  2023-09-22 17:50 ` [PATCH 07/15] platform/x86/amd/pmf: Add support update p3t limit Shyam Sundar S K
@ 2023-09-22 17:50 ` Shyam Sundar S K
  2023-09-25 21:42   ` kernel test robot
  2023-09-27 12:22   ` Ilpo Järvinen
  2023-09-22 17:50 ` [PATCH 09/15] platform/x86/amd/pmf: Add facility to dump TA inputs Shyam Sundar S K
                   ` (6 subsequent siblings)
  14 siblings, 2 replies; 54+ messages in thread
From: Shyam Sundar S K @ 2023-09-22 17:50 UTC (permalink / raw)
  To: hdegoede, markgross, basavaraj.natikar, jikos,
	benjamin.tissoires, alexander.deucher, christian.koenig,
	Xinhui.Pan, airlied, daniel
  Cc: Shyam Sundar S K, amd-gfx, platform-driver-x86, dri-devel,
	Patil.Reddy, linux-input, mario.limonciello

PMF driver based on the output actions from the TA can request to update
the system states like entering s0i3, lock screen etc. by generating
an uevent. Based on the udev rules set in the userspace the event id
matching the uevent shall get updated accordingly using the systemctl.

Sample udev rules under Documentation/admin-guide/pmf.rst.

Signed-off-by: Shyam Sundar S K <Shyam-sundar.S-k@amd.com>
---
 Documentation/admin-guide/pmf.rst     | 24 ++++++++++++++++
 drivers/platform/x86/amd/pmf/pmf.h    |  9 ++++++
 drivers/platform/x86/amd/pmf/tee-if.c | 40 ++++++++++++++++++++++++++-
 3 files changed, 72 insertions(+), 1 deletion(-)
 create mode 100644 Documentation/admin-guide/pmf.rst

diff --git a/Documentation/admin-guide/pmf.rst b/Documentation/admin-guide/pmf.rst
new file mode 100644
index 000000000000..b60f381410c3
--- /dev/null
+++ b/Documentation/admin-guide/pmf.rst
@@ -0,0 +1,24 @@
+.. SPDX-License-Identifier: GPL-2.0
+
+Set udev rules for PMF Smart PC Builder
+---------------------------------------
+
+AMD PMF(Platform Management Framework) Smart PC Solution builder has to set the system states
+like S0i3, Screen lock, hibernate etc, based on the output actions provided by the PMF
+TA (Trusted Application).
+
+In order for this to work the PMF driver generates a uevent for userspace to react to. Below are
+sample udev rules that can facilitate this experience when a machine has PMF Smart PC solution builder
+enabled.
+
+Please add the following line(s) to
+``/etc/udev/rules.d/99-local.rules``::
+        DRIVERS=="amd-pmf", ACTION=="change", ENV{EVENT_ID}=="1", RUN+="/usr/bin/systemctl suspend"
+        DRIVERS=="amd-pmf", ACTION=="change", ENV{EVENT_ID}=="2", RUN+="/usr/bin/systemctl hibernate"
+        DRIVERS=="amd-pmf", ACTION=="change", ENV{EVENT_ID}=="3", RUN+="/bin/loginctl lock-sessions"
+
+EVENT_ID values:
+1= Put the system to S0i3/S2Idle
+2= Put the system to hibernate
+3= Lock the screen
+
diff --git a/drivers/platform/x86/amd/pmf/pmf.h b/drivers/platform/x86/amd/pmf/pmf.h
index 897f61b75e2f..c5334f1177a4 100644
--- a/drivers/platform/x86/amd/pmf/pmf.h
+++ b/drivers/platform/x86/amd/pmf/pmf.h
@@ -70,6 +70,7 @@
 #define PMF_POLICY_STT_MIN					6
 #define PMF_POLICY_STT_SKINTEMP_APU				7
 #define PMF_POLICY_STT_SKINTEMP_HS2				8
+#define PMF_POLICY_SYSTEM_STATE					9
 #define PMF_POLICY_P3T						38
 
 /* TA macros */
@@ -436,6 +437,13 @@ struct apmf_dyn_slider_output {
 } __packed;
 
 /* Smart PC - TA internals */
+enum system_state {
+	SYSTEM_STATE__S0i3 = 1,
+	SYSTEM_STATE__S4,
+	SYSTEM_STATE__SCREEN_LOCK,
+	SYSTEM_STATE__MAX
+};
+
 enum ta_slider {
 	TA_BEST_BATTERY, /* Best Battery */
 	TA_BETTER_BATTERY, /* Better Battery */
@@ -467,6 +475,7 @@ enum ta_pmf_error_type {
 };
 
 struct pmf_action_table {
+	enum system_state system_state;
 	unsigned long spl; /* in mW */
 	unsigned long sppt; /* in mW */
 	unsigned long sppt_apuonly; /* in mW */
diff --git a/drivers/platform/x86/amd/pmf/tee-if.c b/drivers/platform/x86/amd/pmf/tee-if.c
index 883dd143375a..1629856c20b4 100644
--- a/drivers/platform/x86/amd/pmf/tee-if.c
+++ b/drivers/platform/x86/amd/pmf/tee-if.c
@@ -24,6 +24,20 @@ MODULE_PARM_DESC(pb_actions_ms, "Policy binary actions sampling frequency (defau
 static const uuid_t amd_pmf_ta_uuid = UUID_INIT(0x6fd93b77, 0x3fb8, 0x524d,
 						0xb1, 0x2d, 0xc5, 0x29, 0xb1, 0x3d, 0x85, 0x43);
 
+static const char *amd_pmf_uevent_as_str(unsigned int state)
+{
+	switch (state) {
+	case SYSTEM_STATE__S0i3:
+		return "S0i3";
+	case SYSTEM_STATE__S4:
+		return "S4";
+	case SYSTEM_STATE__SCREEN_LOCK:
+		return "SCREEN_LOCK";
+	default:
+		return "Unknown Smart PC event";
+	}
+}
+
 static void amd_pmf_prepare_args(struct amd_pmf_dev *dev, int cmd,
 				 struct tee_ioctl_invoke_arg *arg,
 				 struct tee_param *param)
@@ -42,9 +56,23 @@ static void amd_pmf_prepare_args(struct amd_pmf_dev *dev, int cmd,
 	param[0].u.memref.shm_offs = 0;
 }
 
+static int amd_pmf_update_uevents(struct amd_pmf_dev *dev, u16 event)
+{
+	char *envp[2] = {};
+
+	envp[0] = kasprintf(GFP_KERNEL, "EVENT_ID=%d", event);
+	if (!envp[0])
+		return -EINVAL;
+
+	kobject_uevent_env(&dev->dev->kobj, KOBJ_CHANGE, envp);
+
+	kfree(envp[0]);
+	return 0;
+}
+
 static void amd_pmf_apply_policies(struct amd_pmf_dev *dev, struct ta_pmf_enact_result *out)
 {
-	u32 val;
+	u32 val, event = 0;
 	int idx;
 
 	for (idx = 0; idx < out->actions_count; idx++) {
@@ -113,6 +141,16 @@ static void amd_pmf_apply_policies(struct amd_pmf_dev *dev, struct ta_pmf_enact_
 				dev->prev_data->p3t_limit = val;
 			}
 			break;
+
+		case PMF_POLICY_SYSTEM_STATE:
+			event = val + 1;
+			if (dev->prev_data->system_state != event) {
+				amd_pmf_update_uevents(dev, event);
+				dev_dbg(dev->dev, "update SYSTEM_STATE : %s\n",
+					amd_pmf_uevent_as_str(event));
+				dev->prev_data->system_state = 0;
+			}
+			break;
 		}
 	}
 }
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 54+ messages in thread

* [PATCH 09/15] platform/x86/amd/pmf: Add facility to dump TA inputs
  2023-09-22 17:50 [PATCH 00/15] Introduce PMF Smart PC Solution Builder Feature Shyam Sundar S K
                   ` (7 preceding siblings ...)
  2023-09-22 17:50 ` [PATCH 08/15] platform/x86/amd/pmf: Add support to update system state Shyam Sundar S K
@ 2023-09-22 17:50 ` Shyam Sundar S K
  2023-09-27 12:25   ` Ilpo Järvinen
  2023-09-22 17:50 ` [PATCH 10/15] platform/x86/amd/pmf: Add capability to sideload of policy binary Shyam Sundar S K
                   ` (5 subsequent siblings)
  14 siblings, 1 reply; 54+ messages in thread
From: Shyam Sundar S K @ 2023-09-22 17:50 UTC (permalink / raw)
  To: hdegoede, markgross, basavaraj.natikar, jikos,
	benjamin.tissoires, alexander.deucher, christian.koenig,
	Xinhui.Pan, airlied, daniel
  Cc: Shyam Sundar S K, amd-gfx, platform-driver-x86, dri-devel,
	Patil.Reddy, linux-input, mario.limonciello

PMF driver sends constant inputs to TA which its gets via the other
subsystems in the kernel. To debug certain TA issues knowing what inputs
being sent to TA becomes critical. Add debug facility to the driver which
can isolate Smart PC and TA related issues.

Reviewed-by: Mario Limonciello <mario.limonciello@amd.com>
Signed-off-by: Shyam Sundar S K <Shyam-sundar.S-k@amd.com>
---
 drivers/platform/x86/amd/pmf/pmf.h    |  3 +++
 drivers/platform/x86/amd/pmf/spc.c    | 37 +++++++++++++++++++++++++++
 drivers/platform/x86/amd/pmf/sps.c    |  2 +-
 drivers/platform/x86/amd/pmf/tee-if.c |  1 +
 4 files changed, 42 insertions(+), 1 deletion(-)

diff --git a/drivers/platform/x86/amd/pmf/pmf.h b/drivers/platform/x86/amd/pmf/pmf.h
index c5334f1177a4..61a0f3225b62 100644
--- a/drivers/platform/x86/amd/pmf/pmf.h
+++ b/drivers/platform/x86/amd/pmf/pmf.h
@@ -592,6 +592,7 @@ int apmf_get_static_slider_granular(struct amd_pmf_dev *pdev,
 bool is_pprof_balanced(struct amd_pmf_dev *pmf);
 int amd_pmf_power_slider_update_event(struct amd_pmf_dev *dev);
 
+const char *source_as_str(unsigned int state);
 
 int apmf_update_fan_idx(struct amd_pmf_dev *pdev, bool manual, u32 idx);
 int amd_pmf_set_sps_power_limits(struct amd_pmf_dev *pmf);
@@ -622,4 +623,6 @@ int apmf_check_smart_pc(struct amd_pmf_dev *pmf_dev);
 
 /* Smart PC - TA interfaces */
 void amd_pmf_populate_ta_inputs(struct amd_pmf_dev *dev, struct ta_pmf_enact_table *in);
+void amd_pmf_dump_ta_inputs(struct amd_pmf_dev *dev, struct ta_pmf_enact_table *in);
+
 #endif /* PMF_H */
diff --git a/drivers/platform/x86/amd/pmf/spc.c b/drivers/platform/x86/amd/pmf/spc.c
index 08159cd5f853..5c6745f56ed1 100644
--- a/drivers/platform/x86/amd/pmf/spc.c
+++ b/drivers/platform/x86/amd/pmf/spc.c
@@ -13,6 +13,43 @@
 #include <linux/power_supply.h>
 #include "pmf.h"
 
+#ifdef CONFIG_AMD_PMF_DEBUG
+static const char *ta_slider_as_str(unsigned int state)
+{
+	switch (state) {
+	case TA_BEST_PERFORMANCE:
+		return "PERFORMANCE";
+	case TA_BETTER_PERFORMANCE:
+		return "BALANCED";
+	case TA_BEST_BATTERY:
+		return "POWER_SAVER";
+	default:
+		return "Unknown TA Slider State";
+	}
+}
+
+void amd_pmf_dump_ta_inputs(struct amd_pmf_dev *dev, struct ta_pmf_enact_table *in)
+{
+	dev_dbg(dev->dev, "==== TA inputs START ====\n");
+	dev_dbg(dev->dev, "Slider State : %s\n", ta_slider_as_str(in->ev_info.power_slider));
+	dev_dbg(dev->dev, "Power Source : %s\n", source_as_str(in->ev_info.power_source));
+	dev_dbg(dev->dev, "Battery Percentage : %d\n", in->ev_info.bat_percentage);
+	dev_dbg(dev->dev, "Designed Battery Capacity : %d\n", in->ev_info.bat_design);
+	dev_dbg(dev->dev, "Fully Charged Capacity : %d\n", in->ev_info.full_charge_capacity);
+	dev_dbg(dev->dev, "Drain Rate : %d\n", in->ev_info.drain_rate);
+	dev_dbg(dev->dev, "Socket Power : %d\n", in->ev_info.socket_power);
+	dev_dbg(dev->dev, "Skin Temperature : %d\n", in->ev_info.skin_temperature);
+	dev_dbg(dev->dev, "Avg C0 Residency : %d\n", in->ev_info.avg_c0residency);
+	dev_dbg(dev->dev, "Max C0 Residency : %d\n", in->ev_info.max_c0residency);
+	dev_dbg(dev->dev, "GFX Busy : %d\n", in->ev_info.gfx_busy);
+	dev_dbg(dev->dev, "Connected Display Count : %d\n", in->ev_info.monitor_count);
+	dev_dbg(dev->dev, "LID State : %s\n", in->ev_info.lid_state ? "Close" : "Open");
+	dev_dbg(dev->dev, "==== TA inputs END ====\n");
+}
+#else
+void amd_pmf_dump_ta_inputs(struct amd_pmf_dev *dev, struct ta_pmf_enact_table *in) {}
+#endif
+
 static void amd_pmf_get_smu_info(struct amd_pmf_dev *dev, struct ta_pmf_enact_table *in)
 {
 	u16 max, avg = 0;
diff --git a/drivers/platform/x86/amd/pmf/sps.c b/drivers/platform/x86/amd/pmf/sps.c
index a70e67749be3..13e36b52dfe8 100644
--- a/drivers/platform/x86/amd/pmf/sps.c
+++ b/drivers/platform/x86/amd/pmf/sps.c
@@ -27,7 +27,7 @@ static const char *slider_as_str(unsigned int state)
 	}
 }
 
-static const char *source_as_str(unsigned int state)
+const char *source_as_str(unsigned int state)
 {
 	switch (state) {
 	case POWER_SOURCE_AC:
diff --git a/drivers/platform/x86/amd/pmf/tee-if.c b/drivers/platform/x86/amd/pmf/tee-if.c
index 1629856c20b4..4844782d93c7 100644
--- a/drivers/platform/x86/amd/pmf/tee-if.c
+++ b/drivers/platform/x86/amd/pmf/tee-if.c
@@ -186,6 +186,7 @@ static int amd_pmf_invoke_cmd_enact(struct amd_pmf_dev *dev)
 	}
 
 	if (ta_sm->pmf_result == TA_PMF_TYPE__SUCCESS && out->actions_count) {
+		amd_pmf_dump_ta_inputs(dev, in);
 		dev_dbg(dev->dev, "action count:%d result:%x\n", out->actions_count,
 			ta_sm->pmf_result);
 		amd_pmf_apply_policies(dev, out);
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 54+ messages in thread

* [PATCH 10/15] platform/x86/amd/pmf: Add capability to sideload of policy binary
  2023-09-22 17:50 [PATCH 00/15] Introduce PMF Smart PC Solution Builder Feature Shyam Sundar S K
                   ` (8 preceding siblings ...)
  2023-09-22 17:50 ` [PATCH 09/15] platform/x86/amd/pmf: Add facility to dump TA inputs Shyam Sundar S K
@ 2023-09-22 17:50 ` Shyam Sundar S K
  2023-09-25  2:14   ` kernel test robot
  2023-09-27 12:33   ` Ilpo Järvinen
  2023-09-22 17:50 ` [PATCH 11/15] platform/x86/amd/pmf: dump policy binary data Shyam Sundar S K
                   ` (4 subsequent siblings)
  14 siblings, 2 replies; 54+ messages in thread
From: Shyam Sundar S K @ 2023-09-22 17:50 UTC (permalink / raw)
  To: hdegoede, markgross, basavaraj.natikar, jikos,
	benjamin.tissoires, alexander.deucher, christian.koenig,
	Xinhui.Pan, airlied, daniel
  Cc: Shyam Sundar S K, amd-gfx, platform-driver-x86, dri-devel,
	Patil.Reddy, linux-input, mario.limonciello

A policy binary is OS agnostic, and the same policies are expected to work
across the OSes.  At times it becomes difficult to debug when the policies
inside the policy binaries starts to misbehave. Add a way to sideload such
policies independently to debug them via a debugfs entry.

Reviewed-by: Mario Limonciello <mario.limonciello@amd.com>
Signed-off-by: Shyam Sundar S K <Shyam-sundar.S-k@amd.com>
---
 drivers/platform/x86/amd/pmf/pmf.h    |  1 +
 drivers/platform/x86/amd/pmf/tee-if.c | 60 +++++++++++++++++++++++++++
 2 files changed, 61 insertions(+)

diff --git a/drivers/platform/x86/amd/pmf/pmf.h b/drivers/platform/x86/amd/pmf/pmf.h
index 61a0f3225b62..780c442239e3 100644
--- a/drivers/platform/x86/amd/pmf/pmf.h
+++ b/drivers/platform/x86/amd/pmf/pmf.h
@@ -215,6 +215,7 @@ struct amd_pmf_dev {
 	bool cnqf_supported;
 	struct notifier_block pwr_src_notifier;
 	/* Smart PC solution builder */
+	struct dentry *esbin;
 	unsigned char *policy_buf;
 	u32 policy_sz;
 	struct tee_context *tee_ctx;
diff --git a/drivers/platform/x86/amd/pmf/tee-if.c b/drivers/platform/x86/amd/pmf/tee-if.c
index 4844782d93c7..fa37cfab2dc7 100644
--- a/drivers/platform/x86/amd/pmf/tee-if.c
+++ b/drivers/platform/x86/amd/pmf/tee-if.c
@@ -8,6 +8,7 @@
  * Author: Shyam Sundar S K <Shyam-sundar.S-k@amd.com>
  */
 
+#include <linux/debugfs.h>
 #include <linux/tee_drv.h>
 #include <linux/uuid.h>
 #include "pmf.h"
@@ -21,6 +22,13 @@ module_param(pb_actions_ms, int, 0644);
 MODULE_PARM_DESC(pb_actions_ms, "Policy binary actions sampling frequency (default = 1000ms)");
 #endif
 
+#ifdef CONFIG_AMD_PMF_DEBUG
+/* Sideload policy binaries to debug policy failures */
+static bool pb_side_load;
+module_param(pb_side_load, bool, 0444);
+MODULE_PARM_DESC(pb_side_load, "Sideload policy binaries debug policy failures");
+#endif
+
 static const uuid_t amd_pmf_ta_uuid = UUID_INIT(0x6fd93b77, 0x3fb8, 0x524d,
 						0xb1, 0x2d, 0xc5, 0x29, 0xb1, 0x3d, 0x85, 0x43);
 
@@ -267,6 +275,49 @@ static int amd_pmf_start_policy_engine(struct amd_pmf_dev *dev)
 	return 0;
 }
 
+#ifdef CONFIG_AMD_PMF_DEBUG
+static ssize_t amd_pmf_get_pb_data(struct file *filp, const char __user *buf,
+				   size_t length, loff_t *pos)
+{
+	struct amd_pmf_dev *dev = filp->private_data;
+	int ret;
+
+	/* policy binary size cannot exceed POLICY_BUF_MAX_SZ */
+	if (length > POLICY_BUF_MAX_SZ || length == 0)
+		return -EINVAL;
+
+	dev->policy_sz = length;
+	if (copy_from_user(dev->policy_buf, buf, dev->policy_sz))
+		return -EFAULT;
+
+	ret = amd_pmf_start_policy_engine(dev);
+	if (ret)
+		return -EINVAL;
+
+	return length;
+}
+
+static const struct file_operations pb_fops = {
+	.write = amd_pmf_get_pb_data,
+	.open = simple_open,
+};
+
+int amd_pmf_open_pb(struct amd_pmf_dev *dev, struct dentry *debugfs_root)
+{
+	struct dentry *file = NULL;
+
+	dev->esbin = debugfs_create_dir("pb", debugfs_root);
+	if (IS_ERR(dev->esbin))
+		return -EINVAL;
+
+	file = debugfs_create_file("update_policy", 0644, dev->esbin, dev, &pb_fops);
+	if (!file)
+		return -EINVAL;
+
+	return 0;
+}
+#endif
+
 static int amd_pmf_get_bios_buffer(struct amd_pmf_dev *dev)
 {
 	dev->policy_buf = kzalloc(dev->policy_sz, GFP_KERNEL);
@@ -279,6 +330,11 @@ static int amd_pmf_get_bios_buffer(struct amd_pmf_dev *dev)
 
 	memcpy(dev->policy_buf, dev->policy_base, dev->policy_sz);
 
+#ifdef CONFIG_AMD_PMF_DEBUG
+	if (pb_side_load)
+		amd_pmf_open_pb(dev, dev->dbgfs_dir);
+#endif
+
 	return amd_pmf_start_policy_engine(dev);
 }
 
@@ -381,6 +437,10 @@ int amd_pmf_init_smart_pc(struct amd_pmf_dev *dev)
 
 void amd_pmf_deinit_smart_pc(struct amd_pmf_dev *dev)
 {
+#ifdef CONFIG_AMD_PMF_DEBUG
+	if (pb_side_load)
+		debugfs_remove_recursive(dev->esbin);
+#endif
 	kfree(dev->prev_data);
 	kfree(dev->policy_buf);
 	cancel_delayed_work_sync(&dev->pb_work);
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 54+ messages in thread

* [PATCH 11/15] platform/x86/amd/pmf: dump policy binary data
  2023-09-22 17:50 [PATCH 00/15] Introduce PMF Smart PC Solution Builder Feature Shyam Sundar S K
                   ` (9 preceding siblings ...)
  2023-09-22 17:50 ` [PATCH 10/15] platform/x86/amd/pmf: Add capability to sideload of policy binary Shyam Sundar S K
@ 2023-09-22 17:50 ` Shyam Sundar S K
  2023-09-22 19:01   ` Mario Limonciello
  2023-09-22 17:50 ` [PATCH 12/15] platform/x86/amd/pmf: Add PMF-AMDGPU get interface Shyam Sundar S K
                   ` (3 subsequent siblings)
  14 siblings, 1 reply; 54+ messages in thread
From: Shyam Sundar S K @ 2023-09-22 17:50 UTC (permalink / raw)
  To: hdegoede, markgross, basavaraj.natikar, jikos,
	benjamin.tissoires, alexander.deucher, christian.koenig,
	Xinhui.Pan, airlied, daniel
  Cc: Shyam Sundar S K, amd-gfx, platform-driver-x86, dri-devel,
	Patil.Reddy, linux-input, mario.limonciello

Sometimes policy binary retrieved from the BIOS maybe incorrect that can
end up in failing to enable the Smart PC solution feature.

Use print_hex_dump_debug() to dump the policy binary in hex, so that we
debug the issues related to the binary even before sending that to TA.

Signed-off-by: Shyam Sundar S K <Shyam-sundar.S-k@amd.com>
---
 drivers/platform/x86/amd/pmf/tee-if.c | 7 +++++++
 1 file changed, 7 insertions(+)

diff --git a/drivers/platform/x86/amd/pmf/tee-if.c b/drivers/platform/x86/amd/pmf/tee-if.c
index fa37cfab2dc7..3daa122f35d5 100644
--- a/drivers/platform/x86/amd/pmf/tee-if.c
+++ b/drivers/platform/x86/amd/pmf/tee-if.c
@@ -290,6 +290,9 @@ static ssize_t amd_pmf_get_pb_data(struct file *filp, const char __user *buf,
 	if (copy_from_user(dev->policy_buf, buf, dev->policy_sz))
 		return -EFAULT;
 
+	print_hex_dump_debug("(pb):  ", DUMP_PREFIX_OFFSET, 16, 1, dev->policy_buf,
+			     dev->policy_sz, false);
+
 	ret = amd_pmf_start_policy_engine(dev);
 	if (ret)
 		return -EINVAL;
@@ -329,6 +332,10 @@ static int amd_pmf_get_bios_buffer(struct amd_pmf_dev *dev)
 		return -ENOMEM;
 
 	memcpy(dev->policy_buf, dev->policy_base, dev->policy_sz);
+#ifdef CONFIG_AMD_PMF_DEBUG
+	print_hex_dump_debug("(pb):  ", DUMP_PREFIX_OFFSET, 16, 1, dev->policy_buf,
+			     dev->policy_sz, false);
+#endif
 
 #ifdef CONFIG_AMD_PMF_DEBUG
 	if (pb_side_load)
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 54+ messages in thread

* [PATCH 12/15] platform/x86/amd/pmf: Add PMF-AMDGPU get interface
  2023-09-22 17:50 [PATCH 00/15] Introduce PMF Smart PC Solution Builder Feature Shyam Sundar S K
                   ` (10 preceding siblings ...)
  2023-09-22 17:50 ` [PATCH 11/15] platform/x86/amd/pmf: dump policy binary data Shyam Sundar S K
@ 2023-09-22 17:50 ` Shyam Sundar S K
  2023-09-27 12:54   ` Ilpo Järvinen
  2023-09-22 17:50 ` [PATCH 13/15] platform/x86/amd/pmf: Add PMF-AMDGPU set interface Shyam Sundar S K
                   ` (2 subsequent siblings)
  14 siblings, 1 reply; 54+ messages in thread
From: Shyam Sundar S K @ 2023-09-22 17:50 UTC (permalink / raw)
  To: hdegoede, markgross, basavaraj.natikar, jikos,
	benjamin.tissoires, alexander.deucher, christian.koenig,
	Xinhui.Pan, airlied, daniel
  Cc: Shyam Sundar S K, amd-gfx, platform-driver-x86, dri-devel,
	Patil.Reddy, linux-input, mario.limonciello

In order to provide GPU inputs to TA for the Smart PC solution to work, we
need to have interface between the PMF driver and the AMDGPU driver.

Add the initial code path for get interface from AMDGPU.

Co-developed-by: Mario Limonciello <mario.limonciello@amd.com>
Signed-off-by: Mario Limonciello <mario.limonciello@amd.com>
Signed-off-by: Shyam Sundar S K <Shyam-sundar.S-k@amd.com>
---
 drivers/gpu/drm/amd/amdgpu/Makefile     |  2 +
 drivers/gpu/drm/amd/amdgpu/amdgpu.h     |  1 +
 drivers/gpu/drm/amd/amdgpu/amdgpu_pmf.c | 70 +++++++++++++++++++++++++
 drivers/platform/x86/amd/pmf/Kconfig    |  1 +
 drivers/platform/x86/amd/pmf/core.c     |  1 +
 drivers/platform/x86/amd/pmf/pmf.h      |  4 ++
 drivers/platform/x86/amd/pmf/spc.c      | 13 +++++
 drivers/platform/x86/amd/pmf/tee-if.c   | 22 ++++++++
 include/linux/amd-pmf-io.h              | 28 ++++++++++
 9 files changed, 142 insertions(+)
 create mode 100644 drivers/gpu/drm/amd/amdgpu/amdgpu_pmf.c
 create mode 100644 include/linux/amd-pmf-io.h

diff --git a/drivers/gpu/drm/amd/amdgpu/Makefile b/drivers/gpu/drm/amd/amdgpu/Makefile
index 384b798a9bad..7fafccefbd7a 100644
--- a/drivers/gpu/drm/amd/amdgpu/Makefile
+++ b/drivers/gpu/drm/amd/amdgpu/Makefile
@@ -86,6 +86,8 @@ amdgpu-$(CONFIG_PROC_FS) += amdgpu_fdinfo.o
 
 amdgpu-$(CONFIG_PERF_EVENTS) += amdgpu_pmu.o
 
+amdgpu-$(CONFIG_AMD_PMF) += amdgpu_pmf.o
+
 # add asic specific block
 amdgpu-$(CONFIG_DRM_AMDGPU_CIK)+= cik.o cik_ih.o \
 	dce_v8_0.o gfx_v7_0.o cik_sdma.o uvd_v4_2.o vce_v2_0.o
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu.h b/drivers/gpu/drm/amd/amdgpu/amdgpu.h
index dc2d53081e80..475f3e248f35 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu.h
@@ -50,6 +50,7 @@
 #include <linux/hashtable.h>
 #include <linux/dma-fence.h>
 #include <linux/pci.h>
+#include <linux/amd-pmf-io.h>
 
 #include <drm/ttm/ttm_bo.h>
 #include <drm/ttm/ttm_placement.h>
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_pmf.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_pmf.c
new file mode 100644
index 000000000000..232d11833ddc
--- /dev/null
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_pmf.c
@@ -0,0 +1,70 @@
+/*
+ * Copyright 2023 Advanced Micro Devices, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+
+ * * Author: Shyam Sundar S K <Shyam-sundar.S-k@amd.com>
+ */
+
+#include <linux/backlight.h>
+#include "amdgpu.h"
+
+int amd_pmf_get_gfx_data(struct amd_gpu_pmf_data *pmf)
+{
+	struct drm_device *drm_dev = pci_get_drvdata(pmf->gpu_dev);
+	struct drm_mode_config *mode_config = &drm_dev->mode_config;
+	struct amdgpu_device *adev = drm_to_adev(drm_dev);
+	struct drm_connector_list_iter iter;
+	struct drm_connector *connector;
+	struct backlight_device *bd;
+	int i = 0;
+
+	/* reset the count to zero */
+	pmf->display_count = 0;
+	if (!(adev->flags & AMD_IS_APU)) {
+		DRM_ERROR("PMF-AMDGPU interface not supported\n");
+		return -ENODEV;
+	}
+
+	bd = backlight_device_get_by_type(BACKLIGHT_RAW);
+	if (!bd)
+		return -ENODEV;
+
+	pmf->brightness = backlight_get_brightness(bd);
+
+	mutex_lock(&mode_config->mutex);
+	drm_connector_list_iter_begin(drm_dev, &iter);
+
+	drm_for_each_connector_iter(connector, &iter) {
+		if (i > MAX_SUPPORTED)
+			break;
+
+		if (connector->status == connector_status_connected) {
+			pmf->con_status[i] = connector->status;
+			pmf->connector_type[i] = connector->connector_type;
+			pmf->display_count++;
+		}
+		i++;
+	}
+	drm_connector_list_iter_end(&iter);
+	mutex_unlock(&mode_config->mutex);
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(amd_pmf_get_gfx_data);
diff --git a/drivers/platform/x86/amd/pmf/Kconfig b/drivers/platform/x86/amd/pmf/Kconfig
index 437b78c6d1c5..0cd08f9ab51b 100644
--- a/drivers/platform/x86/amd/pmf/Kconfig
+++ b/drivers/platform/x86/amd/pmf/Kconfig
@@ -10,6 +10,7 @@ config AMD_PMF
 	depends on AMD_NB
 	select ACPI_PLATFORM_PROFILE
 	depends on AMDTEE
+	depends on DRM_AMDGPU
 	help
 	  This driver provides support for the AMD Platform Management Framework.
 	  The goal is to enhance end user experience by making AMD PCs smarter,
diff --git a/drivers/platform/x86/amd/pmf/core.c b/drivers/platform/x86/amd/pmf/core.c
index dbfe7c1d6fc4..c468d208b1dc 100644
--- a/drivers/platform/x86/amd/pmf/core.c
+++ b/drivers/platform/x86/amd/pmf/core.c
@@ -396,6 +396,7 @@ static int amd_pmf_probe(struct platform_device *pdev)
 	}
 
 	dev->cpu_id = rdev->device;
+	dev->root = rdev;
 
 	err = amd_smn_read(0, AMD_PMF_BASE_ADDR_LO, &val);
 	if (err) {
diff --git a/drivers/platform/x86/amd/pmf/pmf.h b/drivers/platform/x86/amd/pmf/pmf.h
index 780c442239e3..9032df4ba48a 100644
--- a/drivers/platform/x86/amd/pmf/pmf.h
+++ b/drivers/platform/x86/amd/pmf/pmf.h
@@ -13,6 +13,8 @@
 
 #include <linux/acpi.h>
 #include <linux/platform_profile.h>
+#include <linux/amd-pmf-io.h>
+
 #define POLICY_BUF_MAX_SZ		0x4b000
 #define POLICY_SIGN_COOKIE		0x31535024
 
@@ -224,9 +226,11 @@ struct amd_pmf_dev {
 	void *shbuf;
 	struct delayed_work pb_work;
 	struct pmf_action_table *prev_data;
+	struct amd_gpu_pmf_data gfx_data;
 	u64 policy_addr;
 	void *policy_base;
 	bool smart_pc_enabled;
+	struct pci_dev *root;
 };
 
 struct apmf_sps_prop_granular {
diff --git a/drivers/platform/x86/amd/pmf/spc.c b/drivers/platform/x86/amd/pmf/spc.c
index 5c6745f56ed1..5f3ab1ce09d2 100644
--- a/drivers/platform/x86/amd/pmf/spc.c
+++ b/drivers/platform/x86/amd/pmf/spc.c
@@ -43,6 +43,10 @@ void amd_pmf_dump_ta_inputs(struct amd_pmf_dev *dev, struct ta_pmf_enact_table *
 	dev_dbg(dev->dev, "Max C0 Residency : %d\n", in->ev_info.max_c0residency);
 	dev_dbg(dev->dev, "GFX Busy : %d\n", in->ev_info.gfx_busy);
 	dev_dbg(dev->dev, "Connected Display Count : %d\n", in->ev_info.monitor_count);
+	dev_dbg(dev->dev, "Primary Display Type : %s\n",
+		drm_get_connector_type_name(in->ev_info.display_type));
+	dev_dbg(dev->dev, "Primary Display State : %s\n", in->ev_info.display_state ?
+			"Connected" : "disconnected/unknown");
 	dev_dbg(dev->dev, "LID State : %s\n", in->ev_info.lid_state ? "Close" : "Open");
 	dev_dbg(dev->dev, "==== TA inputs END ====\n");
 }
@@ -144,6 +148,14 @@ static int amd_pmf_get_slider_info(struct amd_pmf_dev *dev, struct ta_pmf_enact_
 	return 0;
 }
 
+static void amd_pmf_get_gpu_info(struct amd_pmf_dev *dev, struct ta_pmf_enact_table *in)
+{
+	amd_pmf_get_gfx_data(&dev->gfx_data);
+	in->ev_info.monitor_count = dev->gfx_data.display_count;
+	in->ev_info.display_type = dev->gfx_data.connector_type[0];
+	in->ev_info.display_state = dev->gfx_data.con_status[0];
+}
+
 void amd_pmf_populate_ta_inputs(struct amd_pmf_dev *dev, struct ta_pmf_enact_table *in)
 {
 	/* TA side lid open is 1 and close is 0, hence the ! here */
@@ -152,4 +164,5 @@ void amd_pmf_populate_ta_inputs(struct amd_pmf_dev *dev, struct ta_pmf_enact_tab
 	amd_pmf_get_smu_info(dev, in);
 	amd_pmf_get_battery_info(dev, in);
 	amd_pmf_get_slider_info(dev, in);
+	amd_pmf_get_gpu_info(dev, in);
 }
diff --git a/drivers/platform/x86/amd/pmf/tee-if.c b/drivers/platform/x86/amd/pmf/tee-if.c
index 3daa122f35d5..1608996654e8 100644
--- a/drivers/platform/x86/amd/pmf/tee-if.c
+++ b/drivers/platform/x86/amd/pmf/tee-if.c
@@ -9,6 +9,7 @@
  */
 
 #include <linux/debugfs.h>
+#include <linux/pci.h>
 #include <linux/tee_drv.h>
 #include <linux/uuid.h>
 #include "pmf.h"
@@ -345,6 +346,20 @@ static int amd_pmf_get_bios_buffer(struct amd_pmf_dev *dev)
 	return amd_pmf_start_policy_engine(dev);
 }
 
+static int amd_pmf_get_gpu_handle(struct pci_dev *pdev, void *data)
+{
+	struct amd_pmf_dev *dev = data;
+
+	if (pdev->vendor == PCI_VENDOR_ID_ATI && pdev->devfn == 0) {
+		dev->gfx_data.gpu_dev = pci_get_device(pdev->vendor, pdev->device, NULL);
+		if (dev->gfx_data.gpu_dev) {
+			pci_dev_put(pdev);
+			return 1; /* stop walking */
+		}
+	}
+	return 0; /* continue walking */
+}
+
 static int amd_pmf_amdtee_ta_match(struct tee_ioctl_version_data *ver, const void *data)
 {
 	return ver->impl_id == TEE_IMPL_ID_AMDTEE;
@@ -435,6 +450,12 @@ int amd_pmf_init_smart_pc(struct amd_pmf_dev *dev)
 	INIT_DELAYED_WORK(&dev->pb_work, amd_pmf_invoke_cmd);
 	amd_pmf_set_dram_addr(dev);
 	amd_pmf_get_bios_buffer(dev);
+
+	/* get amdgpu handle */
+	pci_walk_bus(dev->root->bus, amd_pmf_get_gpu_handle, dev);
+	if (!dev->gfx_data.gpu_dev)
+		dev_err(dev->dev, "GPU handle not found!\n");
+
 	dev->prev_data = kzalloc(sizeof(*dev->prev_data), GFP_KERNEL);
 	if (!dev->prev_data)
 		return -ENOMEM;
@@ -451,5 +472,6 @@ void amd_pmf_deinit_smart_pc(struct amd_pmf_dev *dev)
 	kfree(dev->prev_data);
 	kfree(dev->policy_buf);
 	cancel_delayed_work_sync(&dev->pb_work);
+	pci_dev_put(dev->gfx_data.gpu_dev);
 	amd_pmf_tee_deinit(dev);
 }
diff --git a/include/linux/amd-pmf-io.h b/include/linux/amd-pmf-io.h
new file mode 100644
index 000000000000..a2d4af231362
--- /dev/null
+++ b/include/linux/amd-pmf-io.h
@@ -0,0 +1,28 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * AMD Platform Management Framework Interface
+ *
+ * Copyright (c) 2023, Advanced Micro Devices, Inc.
+ * All Rights Reserved.
+ *
+ * Author: Shyam Sundar S K <Shyam-sundar.S-k@amd.com>
+ */
+
+#ifndef AMD_PMF_IO_H
+#define AMD_PMF_IO_H
+
+#include <drm/drm_connector.h>
+
+#define MAX_SUPPORTED 4
+
+/* amdgpu */
+struct amd_gpu_pmf_data {
+	struct pci_dev *gpu_dev;
+	enum drm_connector_status con_status[MAX_SUPPORTED];
+	int display_count;
+	int connector_type[MAX_SUPPORTED];
+	int brightness;
+};
+
+int amd_pmf_get_gfx_data(struct amd_gpu_pmf_data *pmf);
+#endif
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 54+ messages in thread

* [PATCH 13/15] platform/x86/amd/pmf: Add PMF-AMDGPU set interface
  2023-09-22 17:50 [PATCH 00/15] Introduce PMF Smart PC Solution Builder Feature Shyam Sundar S K
                   ` (11 preceding siblings ...)
  2023-09-22 17:50 ` [PATCH 12/15] platform/x86/amd/pmf: Add PMF-AMDGPU get interface Shyam Sundar S K
@ 2023-09-22 17:50 ` Shyam Sundar S K
  2023-09-25 16:27   ` Deucher, Alexander
                     ` (2 more replies)
  2023-09-22 17:50 ` [PATCH 14/15] platform/x86/amd/pmf: Add PMF-AMDSFH interface for HPD Shyam Sundar S K
  2023-09-22 17:50 ` [PATCH 15/15] platform/x86/amd/pmf: Add PMF-AMDSFH interface for ALS Shyam Sundar S K
  14 siblings, 3 replies; 54+ messages in thread
From: Shyam Sundar S K @ 2023-09-22 17:50 UTC (permalink / raw)
  To: hdegoede, markgross, basavaraj.natikar, jikos,
	benjamin.tissoires, alexander.deucher, christian.koenig,
	Xinhui.Pan, airlied, daniel
  Cc: Shyam Sundar S K, amd-gfx, platform-driver-x86, dri-devel,
	Patil.Reddy, linux-input, mario.limonciello

For the Smart PC Solution to fully work, it has to enact to the actions
coming from TA. Add the initial code path for set interface to AMDGPU.

Co-developed-by: Mario Limonciello <mario.limonciello@amd.com>
Signed-off-by: Mario Limonciello <mario.limonciello@amd.com>
Signed-off-by: Shyam Sundar S K <Shyam-sundar.S-k@amd.com>
---
 drivers/gpu/drm/amd/amdgpu/amdgpu_pmf.c | 21 +++++++++++++++++++++
 drivers/platform/x86/amd/pmf/pmf.h      |  2 ++
 drivers/platform/x86/amd/pmf/tee-if.c   | 19 +++++++++++++++++--
 include/linux/amd-pmf-io.h              |  1 +
 4 files changed, 41 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_pmf.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_pmf.c
index 232d11833ddc..5c567bff0548 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_pmf.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_pmf.c
@@ -68,3 +68,24 @@ int amd_pmf_get_gfx_data(struct amd_gpu_pmf_data *pmf)
 	return 0;
 }
 EXPORT_SYMBOL_GPL(amd_pmf_get_gfx_data);
+
+int amd_pmf_set_gfx_data(struct amd_gpu_pmf_data *pmf)
+{
+	struct drm_device *drm_dev = pci_get_drvdata(pmf->gpu_dev);
+	struct amdgpu_device *adev = drm_to_adev(drm_dev);
+	struct backlight_device *bd;
+
+	if (!(adev->flags & AMD_IS_APU)) {
+		DRM_ERROR("PMF-AMDGPU interface not supported\n");
+		return -ENODEV;
+	}
+
+	bd = backlight_device_get_by_type(BACKLIGHT_RAW);
+	if (!bd)
+		return -ENODEV;
+
+	backlight_device_set_brightness(bd, pmf->brightness);
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(amd_pmf_set_gfx_data);
diff --git a/drivers/platform/x86/amd/pmf/pmf.h b/drivers/platform/x86/amd/pmf/pmf.h
index 9032df4ba48a..ce89cc0daa5a 100644
--- a/drivers/platform/x86/amd/pmf/pmf.h
+++ b/drivers/platform/x86/amd/pmf/pmf.h
@@ -73,6 +73,7 @@
 #define PMF_POLICY_STT_SKINTEMP_APU				7
 #define PMF_POLICY_STT_SKINTEMP_HS2				8
 #define PMF_POLICY_SYSTEM_STATE					9
+#define PMF_POLICY_DISPLAY_BRIGHTNESS				12
 #define PMF_POLICY_P3T						38
 
 /* TA macros */
@@ -480,6 +481,7 @@ enum ta_pmf_error_type {
 };
 
 struct pmf_action_table {
+	unsigned long display_brightness;
 	enum system_state system_state;
 	unsigned long spl; /* in mW */
 	unsigned long sppt; /* in mW */
diff --git a/drivers/platform/x86/amd/pmf/tee-if.c b/drivers/platform/x86/amd/pmf/tee-if.c
index 1608996654e8..eefffff83a4c 100644
--- a/drivers/platform/x86/amd/pmf/tee-if.c
+++ b/drivers/platform/x86/amd/pmf/tee-if.c
@@ -79,10 +79,10 @@ static int amd_pmf_update_uevents(struct amd_pmf_dev *dev, u16 event)
 	return 0;
 }
 
-static void amd_pmf_apply_policies(struct amd_pmf_dev *dev, struct ta_pmf_enact_result *out)
+static int amd_pmf_apply_policies(struct amd_pmf_dev *dev, struct ta_pmf_enact_result *out)
 {
 	u32 val, event = 0;
-	int idx;
+	int idx, ret;
 
 	for (idx = 0; idx < out->actions_count; idx++) {
 		val = out->actions_list[idx].value;
@@ -160,8 +160,23 @@ static void amd_pmf_apply_policies(struct amd_pmf_dev *dev, struct ta_pmf_enact_
 				dev->prev_data->system_state = 0;
 			}
 			break;
+
+		case PMF_POLICY_DISPLAY_BRIGHTNESS:
+			ret = amd_pmf_get_gfx_data(&dev->gfx_data);
+			if (ret)
+				return ret;
+
+			dev->prev_data->display_brightness = dev->gfx_data.brightness;
+			if (dev->prev_data->display_brightness != val) {
+				dev->gfx_data.brightness = val;
+				amd_pmf_set_gfx_data(&dev->gfx_data);
+				dev_dbg(dev->dev, "update DISPLAY_BRIGHTNESS : %d\n", val);
+			}
+			break;
 		}
 	}
+
+	return 0;
 }
 
 static int amd_pmf_invoke_cmd_enact(struct amd_pmf_dev *dev)
diff --git a/include/linux/amd-pmf-io.h b/include/linux/amd-pmf-io.h
index a2d4af231362..ecae387ddaa6 100644
--- a/include/linux/amd-pmf-io.h
+++ b/include/linux/amd-pmf-io.h
@@ -25,4 +25,5 @@ struct amd_gpu_pmf_data {
 };
 
 int amd_pmf_get_gfx_data(struct amd_gpu_pmf_data *pmf);
+int amd_pmf_set_gfx_data(struct amd_gpu_pmf_data *pmf);
 #endif
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 54+ messages in thread

* [PATCH 14/15] platform/x86/amd/pmf: Add PMF-AMDSFH interface for HPD
  2023-09-22 17:50 [PATCH 00/15] Introduce PMF Smart PC Solution Builder Feature Shyam Sundar S K
                   ` (12 preceding siblings ...)
  2023-09-22 17:50 ` [PATCH 13/15] platform/x86/amd/pmf: Add PMF-AMDGPU set interface Shyam Sundar S K
@ 2023-09-22 17:50 ` Shyam Sundar S K
  2023-09-22 19:04   ` Mario Limonciello
  2023-09-27 13:32   ` Ilpo Järvinen
  2023-09-22 17:50 ` [PATCH 15/15] platform/x86/amd/pmf: Add PMF-AMDSFH interface for ALS Shyam Sundar S K
  14 siblings, 2 replies; 54+ messages in thread
From: Shyam Sundar S K @ 2023-09-22 17:50 UTC (permalink / raw)
  To: hdegoede, markgross, basavaraj.natikar, jikos,
	benjamin.tissoires, alexander.deucher, christian.koenig,
	Xinhui.Pan, airlied, daniel
  Cc: Shyam Sundar S K, Basavaraj Natikar, amd-gfx,
	platform-driver-x86, dri-devel, Patil.Reddy, linux-input,
	mario.limonciello

From: Basavaraj Natikar <Basavaraj.Natikar@amd.com>

AMDSFH has information about the User presence information via the Human
Presence Detection (HPD) sensor which is part of the AMD sensor fusion hub.
Add PMF and AMDSFH interface to get this information.

Co-developed-by: Shyam Sundar S K <Shyam-sundar.S-k@amd.com>
Signed-off-by: Shyam Sundar S K <Shyam-sundar.S-k@amd.com>
Signed-off-by: Basavaraj Natikar <Basavaraj.Natikar@amd.com>
---
 drivers/hid/amd-sfh-hid/amd_sfh_common.h      |  5 ++++
 drivers/hid/amd-sfh-hid/sfh1_1/amd_sfh_desc.c |  2 +-
 drivers/hid/amd-sfh-hid/sfh1_1/amd_sfh_init.c | 11 ++++++++
 .../amd-sfh-hid/sfh1_1/amd_sfh_interface.c    | 28 +++++++++++++++++++
 .../amd-sfh-hid/sfh1_1/amd_sfh_interface.h    |  1 +
 drivers/platform/x86/amd/pmf/spc.c            | 21 ++++++++++++++
 include/linux/amd-pmf-io.h                    | 22 ++++++++++++++-
 7 files changed, 88 insertions(+), 2 deletions(-)

diff --git a/drivers/hid/amd-sfh-hid/amd_sfh_common.h b/drivers/hid/amd-sfh-hid/amd_sfh_common.h
index 2643bb14fee2..cd57037bf217 100644
--- a/drivers/hid/amd-sfh-hid/amd_sfh_common.h
+++ b/drivers/hid/amd-sfh-hid/amd_sfh_common.h
@@ -37,6 +37,10 @@ struct amd_mp2_sensor_info {
 	dma_addr_t dma_address;
 };
 
+struct sfh_dev_status {
+	bool is_hpd_present;
+};
+
 struct amd_mp2_dev {
 	struct pci_dev *pdev;
 	struct amdtp_cl_data *cl_data;
@@ -47,6 +51,7 @@ struct amd_mp2_dev {
 	struct amd_input_data in_data;
 	/* mp2 active control status */
 	u32 mp2_acs;
+	struct sfh_dev_status dev_en;
 };
 
 struct amd_mp2_ops {
diff --git a/drivers/hid/amd-sfh-hid/sfh1_1/amd_sfh_desc.c b/drivers/hid/amd-sfh-hid/sfh1_1/amd_sfh_desc.c
index 06bdcf072d10..d7467c41ad3b 100644
--- a/drivers/hid/amd-sfh-hid/sfh1_1/amd_sfh_desc.c
+++ b/drivers/hid/amd-sfh-hid/sfh1_1/amd_sfh_desc.c
@@ -132,7 +132,7 @@ static void get_common_inputs(struct common_input_property *common, int report_i
 	common->event_type = HID_USAGE_SENSOR_EVENT_DATA_UPDATED_ENUM;
 }
 
-static int float_to_int(u32 flt32_val)
+int float_to_int(u32 flt32_val)
 {
 	int fraction, shift, mantissa, sign, exp, zeropre;
 
diff --git a/drivers/hid/amd-sfh-hid/sfh1_1/amd_sfh_init.c b/drivers/hid/amd-sfh-hid/sfh1_1/amd_sfh_init.c
index e9c6413af24a..9c623456ee12 100644
--- a/drivers/hid/amd-sfh-hid/sfh1_1/amd_sfh_init.c
+++ b/drivers/hid/amd-sfh-hid/sfh1_1/amd_sfh_init.c
@@ -73,6 +73,12 @@ static int amd_sfh_hid_client_deinit(struct amd_mp2_dev *privdata)
 	int i, status;
 
 	for (i = 0; i < cl_data->num_hid_devices; i++) {
+		switch (cl_data->sensor_idx[i]) {
+		case HPD_IDX:
+			privdata->dev_en.is_hpd_present = false;
+			break;
+		}
+
 		if (cl_data->sensor_sts[i] == SENSOR_ENABLED) {
 			privdata->mp2_ops->stop(privdata, cl_data->sensor_idx[i]);
 			status = amd_sfh_wait_for_response
@@ -178,6 +184,11 @@ static int amd_sfh1_1_hid_client_init(struct amd_mp2_dev *privdata)
 			rc = amdtp_hid_probe(i, cl_data);
 			if (rc)
 				goto cleanup;
+			switch (cl_data->sensor_idx[i]) {
+			case HPD_IDX:
+			privdata->dev_en.is_hpd_present = true;
+				break;
+			}
 		}
 		dev_dbg(dev, "sid 0x%x (%s) status 0x%x\n",
 			cl_data->sensor_idx[i], get_sensor_name(cl_data->sensor_idx[i]),
diff --git a/drivers/hid/amd-sfh-hid/sfh1_1/amd_sfh_interface.c b/drivers/hid/amd-sfh-hid/sfh1_1/amd_sfh_interface.c
index 4f81ef2d4f56..63a5bbca5a09 100644
--- a/drivers/hid/amd-sfh-hid/sfh1_1/amd_sfh_interface.c
+++ b/drivers/hid/amd-sfh-hid/sfh1_1/amd_sfh_interface.c
@@ -7,11 +7,14 @@
  *
  * Author: Basavaraj Natikar <Basavaraj.Natikar@amd.com>
  */
+#include <linux/amd-pmf-io.h>
 #include <linux/io-64-nonatomic-lo-hi.h>
 #include <linux/iopoll.h>
 
 #include "amd_sfh_interface.h"
 
+static struct amd_mp2_dev *emp2;
+
 static int amd_sfh_wait_response(struct amd_mp2_dev *mp2, u8 sid, u32 cmd_id)
 {
 	struct sfh_cmd_response cmd_resp;
@@ -76,4 +79,29 @@ static struct amd_mp2_ops amd_sfh_ops = {
 void sfh_interface_init(struct amd_mp2_dev *mp2)
 {
 	mp2->mp2_ops = &amd_sfh_ops;
+	emp2 = mp2;
+}
+
+static int amd_sfh_hpd_info(u8 *user_present)
+{
+	if (emp2 && emp2->dev_en.is_hpd_present) {
+		struct hpd_status hpdstatus;
+
+		hpdstatus.val = readl(emp2->mmio + AMD_C2P_MSG(4));
+		*user_present = hpdstatus.shpd.presence;
+		return 0;
+	}
+	return  -ENODEV;
+}
+
+int amd_get_sfh_info(struct amd_sfh_info *sfh_info, enum sfh_message_type op)
+{
+	if (sfh_info) {
+		switch (op) {
+		case MT_HPD:
+			return amd_sfh_hpd_info(&sfh_info->user_present);
+		}
+	}
+	return -1;
 }
+EXPORT_SYMBOL_GPL(amd_get_sfh_info);
diff --git a/drivers/hid/amd-sfh-hid/sfh1_1/amd_sfh_interface.h b/drivers/hid/amd-sfh-hid/sfh1_1/amd_sfh_interface.h
index 9d31d5b510eb..8a36386e6bce 100644
--- a/drivers/hid/amd-sfh-hid/sfh1_1/amd_sfh_interface.h
+++ b/drivers/hid/amd-sfh-hid/sfh1_1/amd_sfh_interface.h
@@ -149,6 +149,7 @@ struct hpd_status {
 	};
 };
 
+int float_to_int(u32 flt32_val);
 void sfh_interface_init(struct amd_mp2_dev *mp2);
 void amd_sfh1_1_set_desc_ops(struct amd_mp2_ops *mp2_ops);
 #endif
diff --git a/drivers/platform/x86/amd/pmf/spc.c b/drivers/platform/x86/amd/pmf/spc.c
index 5f3ab1ce09d2..97293ae25cf5 100644
--- a/drivers/platform/x86/amd/pmf/spc.c
+++ b/drivers/platform/x86/amd/pmf/spc.c
@@ -48,6 +48,7 @@ void amd_pmf_dump_ta_inputs(struct amd_pmf_dev *dev, struct ta_pmf_enact_table *
 	dev_dbg(dev->dev, "Primary Display State : %s\n", in->ev_info.display_state ?
 			"Connected" : "disconnected/unknown");
 	dev_dbg(dev->dev, "LID State : %s\n", in->ev_info.lid_state ? "Close" : "Open");
+	dev_dbg(dev->dev, "User Presence : %s\n", in->ev_info.user_present ? "Present" : "Away");
 	dev_dbg(dev->dev, "==== TA inputs END ====\n");
 }
 #else
@@ -156,6 +157,25 @@ static void amd_pmf_get_gpu_info(struct amd_pmf_dev *dev, struct ta_pmf_enact_ta
 	in->ev_info.display_state = dev->gfx_data.con_status[0];
 }
 
+static void amd_pmf_get_sensor_info(struct amd_pmf_dev *dev, struct ta_pmf_enact_table *in)
+{
+	struct amd_sfh_info sfh_info;
+
+	/* get HPD data */
+	amd_get_sfh_info(&sfh_info, MT_HPD);
+	switch (sfh_info.user_present) {
+	case SFH_NOT_DETECTED:
+		in->ev_info.user_present = 0xff; /* assume no sensors connected */
+		break;
+	case SFH_USER_PRESENT:
+		in->ev_info.user_present = 1;
+		break;
+	case SFH_USER_AWAY:
+		in->ev_info.user_present = 0;
+		break;
+	}
+}
+
 void amd_pmf_populate_ta_inputs(struct amd_pmf_dev *dev, struct ta_pmf_enact_table *in)
 {
 	/* TA side lid open is 1 and close is 0, hence the ! here */
@@ -165,4 +185,5 @@ void amd_pmf_populate_ta_inputs(struct amd_pmf_dev *dev, struct ta_pmf_enact_tab
 	amd_pmf_get_battery_info(dev, in);
 	amd_pmf_get_slider_info(dev, in);
 	amd_pmf_get_gpu_info(dev, in);
+	amd_pmf_get_sensor_info(dev, in);
 }
diff --git a/include/linux/amd-pmf-io.h b/include/linux/amd-pmf-io.h
index ecae387ddaa6..4f82973f6ad2 100644
--- a/include/linux/amd-pmf-io.h
+++ b/include/linux/amd-pmf-io.h
@@ -5,7 +5,8 @@
  * Copyright (c) 2023, Advanced Micro Devices, Inc.
  * All Rights Reserved.
  *
- * Author: Shyam Sundar S K <Shyam-sundar.S-k@amd.com>
+ * Authors: Shyam Sundar S K <Shyam-sundar.S-k@amd.com>
+ *          Basavaraj Natikar <Basavaraj.Natikar@amd.com>
  */
 
 #ifndef AMD_PMF_IO_H
@@ -26,4 +27,23 @@ struct amd_gpu_pmf_data {
 
 int amd_pmf_get_gfx_data(struct amd_gpu_pmf_data *pmf);
 int amd_pmf_set_gfx_data(struct amd_gpu_pmf_data *pmf);
+
+/* amd-sfh */
+enum sfh_message_type {
+	MT_HPD,
+};
+
+enum hpd_info {
+	SFH_NOT_DETECTED,
+	SFH_USER_PRESENT,
+	SFH_USER_AWAY
+};
+
+struct amd_sfh_info {
+	u8 user_present;
+	/* add future caps below */
+};
+
+int amd_get_sfh_info(struct amd_sfh_info *sfh_info, enum sfh_message_type op);
+
 #endif
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 54+ messages in thread

* [PATCH 15/15] platform/x86/amd/pmf: Add PMF-AMDSFH interface for ALS
  2023-09-22 17:50 [PATCH 00/15] Introduce PMF Smart PC Solution Builder Feature Shyam Sundar S K
                   ` (13 preceding siblings ...)
  2023-09-22 17:50 ` [PATCH 14/15] platform/x86/amd/pmf: Add PMF-AMDSFH interface for HPD Shyam Sundar S K
@ 2023-09-22 17:50 ` Shyam Sundar S K
  2023-09-22 19:06   ` Mario Limonciello
  2023-09-27 13:33   ` Ilpo Järvinen
  14 siblings, 2 replies; 54+ messages in thread
From: Shyam Sundar S K @ 2023-09-22 17:50 UTC (permalink / raw)
  To: hdegoede, markgross, basavaraj.natikar, jikos,
	benjamin.tissoires, alexander.deucher, christian.koenig,
	Xinhui.Pan, airlied, daniel
  Cc: Shyam Sundar S K, Basavaraj Natikar, amd-gfx,
	platform-driver-x86, dri-devel, Patil.Reddy, linux-input,
	mario.limonciello

From: Basavaraj Natikar <Basavaraj.Natikar@amd.com>

AMDSFH has information about the Ambient light via the Ambient
Light Sensor (ALS) which is part of the AMD sensor fusion hub.
Add PMF and AMDSFH interface to get this information.

Co-developed-by: Shyam Sundar S K <Shyam-sundar.S-k@amd.com>
Signed-off-by: Shyam Sundar S K <Shyam-sundar.S-k@amd.com>
Signed-off-by: Basavaraj Natikar <Basavaraj.Natikar@amd.com>
---
 drivers/hid/amd-sfh-hid/amd_sfh_common.h      |  1 +
 drivers/hid/amd-sfh-hid/sfh1_1/amd_sfh_init.c |  6 ++++++
 .../amd-sfh-hid/sfh1_1/amd_sfh_interface.c    | 20 +++++++++++++++++++
 drivers/platform/x86/amd/pmf/spc.c            |  5 +++++
 include/linux/amd-pmf-io.h                    |  2 ++
 5 files changed, 34 insertions(+)

diff --git a/drivers/hid/amd-sfh-hid/amd_sfh_common.h b/drivers/hid/amd-sfh-hid/amd_sfh_common.h
index cd57037bf217..a1950bc6e6ce 100644
--- a/drivers/hid/amd-sfh-hid/amd_sfh_common.h
+++ b/drivers/hid/amd-sfh-hid/amd_sfh_common.h
@@ -39,6 +39,7 @@ struct amd_mp2_sensor_info {
 
 struct sfh_dev_status {
 	bool is_hpd_present;
+	bool is_als_present;
 };
 
 struct amd_mp2_dev {
diff --git a/drivers/hid/amd-sfh-hid/sfh1_1/amd_sfh_init.c b/drivers/hid/amd-sfh-hid/sfh1_1/amd_sfh_init.c
index 9c623456ee12..d8dad39d68b5 100644
--- a/drivers/hid/amd-sfh-hid/sfh1_1/amd_sfh_init.c
+++ b/drivers/hid/amd-sfh-hid/sfh1_1/amd_sfh_init.c
@@ -77,6 +77,9 @@ static int amd_sfh_hid_client_deinit(struct amd_mp2_dev *privdata)
 		case HPD_IDX:
 			privdata->dev_en.is_hpd_present = false;
 			break;
+		case ALS_IDX:
+			privdata->dev_en.is_als_present = false;
+			break;
 		}
 
 		if (cl_data->sensor_sts[i] == SENSOR_ENABLED) {
@@ -188,6 +191,9 @@ static int amd_sfh1_1_hid_client_init(struct amd_mp2_dev *privdata)
 			case HPD_IDX:
 			privdata->dev_en.is_hpd_present = true;
 				break;
+			case ALS_IDX:
+			privdata->dev_en.is_als_present = true;
+				break;
 			}
 		}
 		dev_dbg(dev, "sid 0x%x (%s) status 0x%x\n",
diff --git a/drivers/hid/amd-sfh-hid/sfh1_1/amd_sfh_interface.c b/drivers/hid/amd-sfh-hid/sfh1_1/amd_sfh_interface.c
index 63a5bbca5a09..2f8200fc3062 100644
--- a/drivers/hid/amd-sfh-hid/sfh1_1/amd_sfh_interface.c
+++ b/drivers/hid/amd-sfh-hid/sfh1_1/amd_sfh_interface.c
@@ -94,12 +94,32 @@ static int amd_sfh_hpd_info(u8 *user_present)
 	return  -ENODEV;
 }
 
+static int amd_sfh_als_info(u32 *ambient_light)
+{
+	if (emp2 && emp2->dev_en.is_als_present) {
+		struct sfh_als_data als_data;
+		void __iomem *sensoraddr;
+
+		sensoraddr = emp2->vsbase +
+			(ALS_IDX * SENSOR_DATA_MEM_SIZE_DEFAULT) +
+			OFFSET_SENSOR_DATA_DEFAULT;
+		memcpy_fromio(&als_data, sensoraddr, sizeof(struct sfh_als_data));
+		*ambient_light = float_to_int(als_data.lux);
+
+		return 0;
+	}
+
+	return -ENODEV;
+}
+
 int amd_get_sfh_info(struct amd_sfh_info *sfh_info, enum sfh_message_type op)
 {
 	if (sfh_info) {
 		switch (op) {
 		case MT_HPD:
 			return amd_sfh_hpd_info(&sfh_info->user_present);
+		case MT_ALS:
+			return amd_sfh_als_info(&sfh_info->ambient_light);
 		}
 	}
 	return -1;
diff --git a/drivers/platform/x86/amd/pmf/spc.c b/drivers/platform/x86/amd/pmf/spc.c
index 97293ae25cf5..8e19b351e76f 100644
--- a/drivers/platform/x86/amd/pmf/spc.c
+++ b/drivers/platform/x86/amd/pmf/spc.c
@@ -49,6 +49,7 @@ void amd_pmf_dump_ta_inputs(struct amd_pmf_dev *dev, struct ta_pmf_enact_table *
 			"Connected" : "disconnected/unknown");
 	dev_dbg(dev->dev, "LID State : %s\n", in->ev_info.lid_state ? "Close" : "Open");
 	dev_dbg(dev->dev, "User Presence : %s\n", in->ev_info.user_present ? "Present" : "Away");
+	dev_dbg(dev->dev, "Ambient Light : %d\n", in->ev_info.ambient_light);
 	dev_dbg(dev->dev, "==== TA inputs END ====\n");
 }
 #else
@@ -161,6 +162,10 @@ static void amd_pmf_get_sensor_info(struct amd_pmf_dev *dev, struct ta_pmf_enact
 {
 	struct amd_sfh_info sfh_info;
 
+	/* get ALS data */
+	amd_get_sfh_info(&sfh_info, MT_ALS);
+	in->ev_info.ambient_light = sfh_info.ambient_light;
+
 	/* get HPD data */
 	amd_get_sfh_info(&sfh_info, MT_HPD);
 	switch (sfh_info.user_present) {
diff --git a/include/linux/amd-pmf-io.h b/include/linux/amd-pmf-io.h
index 4f82973f6ad2..dac0af573a16 100644
--- a/include/linux/amd-pmf-io.h
+++ b/include/linux/amd-pmf-io.h
@@ -31,6 +31,7 @@ int amd_pmf_set_gfx_data(struct amd_gpu_pmf_data *pmf);
 /* amd-sfh */
 enum sfh_message_type {
 	MT_HPD,
+	MT_ALS,
 };
 
 enum hpd_info {
@@ -40,6 +41,7 @@ enum hpd_info {
 };
 
 struct amd_sfh_info {
+	u32 ambient_light;
 	u8 user_present;
 	/* add future caps below */
 };
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 54+ messages in thread

* Re: [PATCH 04/15] platform/x86/amd/pmf: Add support for PMF Policy Binary
  2023-09-22 17:50 ` [PATCH 04/15] platform/x86/amd/pmf: Add support for PMF Policy Binary Shyam Sundar S K
@ 2023-09-22 18:51   ` Mario Limonciello
  2023-09-30  3:55     ` Shyam Sundar S K
  2023-09-26 17:05   ` Ilpo Järvinen
  2023-09-27 12:19   ` Ilpo Järvinen
  2 siblings, 1 reply; 54+ messages in thread
From: Mario Limonciello @ 2023-09-22 18:51 UTC (permalink / raw)
  To: Shyam Sundar S K, hdegoede, markgross, basavaraj.natikar, jikos,
	benjamin.tissoires, alexander.deucher, christian.koenig,
	Xinhui.Pan, airlied, daniel
  Cc: dri-devel, linux-input, amd-gfx, Patil.Reddy, platform-driver-x86

On 9/22/2023 12:50, Shyam Sundar S K wrote:
> PMF Policy binary is a encrypted and signed binary that will be part
> of the BIOS. PMF driver via the ACPI interface checks the existence
> of Smart PC bit. If the advertised bit is found, PMF driver walks
> the acpi namespace to find out the policy binary size and the address
> which has to be passed to the TA during the TA init sequence.
> 
> The policy binary is comprised of inputs (or the events) and outputs
> (or the actions). With the PMF ecosystem, OEMs generate the policy
> binary (or could be multiple binaries) that contains a supported set
> of inputs and outputs which could be specifically carved out for each
> usage segment (or for each user also) that could influence the system
> behavior either by enriching the user experience or/and boost/throttle
> power limits.
> 
> Once the TA init command succeeds, the PMF driver sends the changing
> events in the current environment to the TA for a constant sampling
> frequency time (the event here could be a lid close or open) and
> if the policy binary has corresponding action built within it, the
> TA sends the action for it in the subsequent enact command.
> 
> If the inputs sent to the TA has no output defined in the policy
> binary generated by OEMs, there will be no action to be performed
> by the PMF driver.
> 
> Example policies:
> 
> 1) if slider is performance ; set the SPL to 40W
> Here PMF driver registers with the platform profile interface and
> when the slider position is changed, PMF driver lets the TA know
> about this. TA sends back an action to update the Sustained
> Power Limit (SPL). PMF driver updates this limit via the PMFW mailbox.
> 
> 2) if user_away ; then lock the system
> Here PMF driver hooks to the AMD SFH driver to know the user presence
> and send the inputs to TA and if the condition is met, the TA sends
> the action of locking the system. PMF driver generates a uevent and
> based on the udev rule in the userland the system gets locked with
> systemctl.
> 
> The intent here is to provide the OEM's to make a policy to lock the
> system when the user is away ; but the userland can make a choice to
> ignore it.
> 
> and so on.
> 
> The OEMs will have an utility to create numerous such policies and
> the policies shall be reviewed by AMD before signing and encrypting
> them. Policies are shared between operating systems to have seemless user
> experience.
> 
> Since all this action has to happen via the "amdtee" driver, currently
> there is no caller for it in the kernel which can load the amdtee driver.
> Without amdtee driver loading onto the system the "tee" calls shall fail
> from the PMF driver. Hence an explicit "request_module" has been added
> to address this.
> 
> Signed-off-by: Shyam Sundar S K <Shyam-sundar.S-k@amd.com>
> ---
>   drivers/platform/x86/amd/pmf/Kconfig  |   1 +
>   drivers/platform/x86/amd/pmf/acpi.c   |  37 +++++++
>   drivers/platform/x86/amd/pmf/core.c   |  12 +++
>   drivers/platform/x86/amd/pmf/pmf.h    | 132 ++++++++++++++++++++++++
>   drivers/platform/x86/amd/pmf/tee-if.c | 141 +++++++++++++++++++++++++-
>   5 files changed, 321 insertions(+), 2 deletions(-)
> 
> diff --git a/drivers/platform/x86/amd/pmf/Kconfig b/drivers/platform/x86/amd/pmf/Kconfig
> index 3064bc8ea167..437b78c6d1c5 100644
> --- a/drivers/platform/x86/amd/pmf/Kconfig
> +++ b/drivers/platform/x86/amd/pmf/Kconfig
> @@ -9,6 +9,7 @@ config AMD_PMF
>   	depends on POWER_SUPPLY
>   	depends on AMD_NB
>   	select ACPI_PLATFORM_PROFILE
> +	depends on AMDTEE
>   	help
>   	  This driver provides support for the AMD Platform Management Framework.
>   	  The goal is to enhance end user experience by making AMD PCs smarter,
> diff --git a/drivers/platform/x86/amd/pmf/acpi.c b/drivers/platform/x86/amd/pmf/acpi.c
> index 3fc5e4547d9f..d0512af2cd42 100644
> --- a/drivers/platform/x86/amd/pmf/acpi.c
> +++ b/drivers/platform/x86/amd/pmf/acpi.c
> @@ -286,6 +286,43 @@ int apmf_install_handler(struct amd_pmf_dev *pmf_dev)
>   	return 0;
>   }
>   
> +static acpi_status apmf_walk_resources(struct acpi_resource *res, void *data)
> +{
> +	struct amd_pmf_dev *dev = data;
> +
> +	switch (res->type) {
> +	case ACPI_RESOURCE_TYPE_ADDRESS64:
> +		dev->policy_addr = res->data.address64.address.minimum;
> +		dev->policy_sz = res->data.address64.address.address_length;
> +		break;
> +	case ACPI_RESOURCE_TYPE_FIXED_MEMORY32:
> +		dev->policy_addr = res->data.fixed_memory32.address;
> +		dev->policy_sz = res->data.fixed_memory32.address_length;
> +		break;
> +	}
> +
> +	if (!dev->policy_addr || dev->policy_sz > POLICY_BUF_MAX_SZ || dev->policy_sz == 0) {
> +		pr_err("Incorrect Policy params, possibly a SBIOS bug\n");
> +		return AE_ERROR;
> +	}
> +
> +	return AE_OK;
> +}
> +
> +int apmf_check_smart_pc(struct amd_pmf_dev *pmf_dev)
> +{
> +	acpi_handle ahandle = ACPI_HANDLE(pmf_dev->dev);
> +	acpi_status status;
> +
> +	status = acpi_walk_resources(ahandle, METHOD_NAME__CRS, apmf_walk_resources, pmf_dev);
> +	if (ACPI_FAILURE(status)) {
> +		dev_err(pmf_dev->dev, "acpi_walk_resources failed\n");
> +		return status;
> +	}
> +
> +	return 0;
> +}
> +
>   void apmf_acpi_deinit(struct amd_pmf_dev *pmf_dev)
>   {
>   	acpi_handle ahandle = ACPI_HANDLE(pmf_dev->dev);
> diff --git a/drivers/platform/x86/amd/pmf/core.c b/drivers/platform/x86/amd/pmf/core.c
> index 5fb03ed614ff..6f36c43e081e 100644
> --- a/drivers/platform/x86/amd/pmf/core.c
> +++ b/drivers/platform/x86/amd/pmf/core.c
> @@ -376,6 +376,18 @@ static int amd_pmf_probe(struct platform_device *pdev)
>   		return -ENOMEM;
>   
>   	dev->dev = &pdev->dev;
> +	err = apmf_check_smart_pc(dev);
> +	if (!err) {
> +		/* in order for Smart PC solution to work it has a hard dependency
> +		 * on the amdtee driver to be loaded first even before the PMF driver
> +		 * loads. PMF ASL has a _CRS method that advertises the existence
> +		 * of Smart PC bit. If this information is present, use this to
> +		 * explicitly probe the amdtee driver, so that "tee" plumbing is done
> +		 * before the PMF Smart PC init happens.
> +		 */
> +		if (request_module("amdtee"))
> +			pr_err("Failed to load amdtee. PMF Smart PC not enabled!\n");

In this case; would it make sense to fail the driver load entirely?
I tend to think yes.

My argument for failing driver load is that if the platform uses Smart 
PC policies, then falling back will basically leave you with at best a 
broken static slider and at worst a driver that you can't fix by loading 
amdtee manually later on.

> +	}
>   
>   	rdev = pci_get_domain_bus_and_slot(0, 0, PCI_DEVFN(0, 0));
>   	if (!rdev || !pci_match_id(pmf_pci_ids, rdev)) {
> diff --git a/drivers/platform/x86/amd/pmf/pmf.h b/drivers/platform/x86/amd/pmf/pmf.h
> index ea15ce547d24..81acf2a37366 100644
> --- a/drivers/platform/x86/amd/pmf/pmf.h
> +++ b/drivers/platform/x86/amd/pmf/pmf.h
> @@ -13,6 +13,8 @@
>   
>   #include <linux/acpi.h>
>   #include <linux/platform_profile.h>
> +#define POLICY_BUF_MAX_SZ		0x4b000
> +#define POLICY_SIGN_COOKIE		0x31535024
>   
>   /* APMF Functions */
>   #define APMF_FUNC_VERIFY_INTERFACE			0
> @@ -59,8 +61,20 @@
>   #define ARG_NONE 0
>   #define AVG_SAMPLE_SIZE 3
>   
> +/* Policy Actions */
> +#define PMF_POLICY_SPL						2
> +#define PMF_POLICY_SPPT						3
> +#define PMF_POLICY_FPPT						4
> +#define PMF_POLICY_SPPT_APU_ONLY				5
> +#define PMF_POLICY_STT_MIN					6
> +#define PMF_POLICY_STT_SKINTEMP_APU				7
> +#define PMF_POLICY_STT_SKINTEMP_HS2				8
> +
>   /* TA macros */
>   #define PMF_TA_IF_VERSION__MAJOR				1
> +#define TA_PMF_ACTION_MAX					32
> +#define TA_PMF_UNDO_MAX						8
> +#define MAX_OPERATION_PARAMS					4
>   
>   /* AMD PMF BIOS interfaces */
>   struct apmf_verify_interface {
> @@ -183,11 +197,16 @@ struct amd_pmf_dev {
>   	bool cnqf_supported;
>   	struct notifier_block pwr_src_notifier;
>   	/* Smart PC solution builder */
> +	unsigned char *policy_buf;
> +	u32 policy_sz;
>   	struct tee_context *tee_ctx;
>   	struct tee_shm *fw_shm_pool;
>   	u32 session_id;
>   	void *shbuf;
>   	struct delayed_work pb_work;
> +	struct pmf_action_table *prev_data;
> +	u64 policy_addr;
> +	void *policy_base;
>   	bool smart_pc_enabled;
>   };
>   
> @@ -399,17 +418,129 @@ struct apmf_dyn_slider_output {
>   	struct apmf_cnqf_power_set ps[APMF_CNQF_MAX];
>   } __packed;
>   
> +/* Smart PC - TA internals */
> +enum ta_slider {
> +	TA_BEST_BATTERY, /* Best Battery */
> +	TA_BETTER_BATTERY, /* Better Battery */
> +	TA_BETTER_PERFORMANCE, /* Better Performance */
> +	TA_BEST_PERFORMANCE, /* Best Performance */
> +	TA_MAX,
> +};
> +
>   /* cmd ids for TA communication */
>   enum ta_pmf_command {
>   	TA_PMF_COMMAND_POLICY_BUILDER__INITIALIZE,
>   	TA_PMF_COMMAND_POLICY_BUILDER__ENACT_POLICIES
>   };
>   
> +enum ta_pmf_error_type {
> +	TA_PMF_TYPE__SUCCESS,
> +	TA_PMF_ERROR_TYPE__GENERIC,
> +	TA_PMF_ERROR_TYPE__CRYPTO,
> +	TA_PMF_ERROR_TYPE__CRYPTO_VALIDATE,
> +	TA_PMF_ERROR_TYPE__CRYPTO_VERIFY_OEM,
> +	TA_PMF_ERROR_TYPE__POLICY_BUILDER,
> +	TA_PMF_ERROR_TYPE__PB_CONVERT,
> +	TA_PMF_ERROR_TYPE__PB_SETUP,
> +	TA_PMF_ERROR_TYPE__PB_ENACT,
> +	TA_PMF_ERROR_TYPE__ASD_GET_DEVICE_INFO,
> +	TA_PMF_ERROR_TYPE__ASD_GET_DEVICE_PCIE_INFO,
> +	TA_PMF_ERROR_TYPE__SYS_DRV_FW_VALIDATION,
> +	TA_PMF_ERROR_TYPE__MAX,
> +};
> +
> +struct pmf_action_table {
> +	unsigned long spl; /* in mW */
> +	unsigned long sppt; /* in mW */
> +	unsigned long sppt_apuonly; /* in mW */
> +	unsigned long fppt; /* in mW */
> +	unsigned long stt_minlimit; /* in mW */
> +	unsigned long stt_skintemp_apu; /* in C */
> +	unsigned long stt_skintemp_hs2; /* in C */
> +};
> +
> +/* Input conditions */
> +struct ta_pmf_condition_info {
> +	u32 power_source;
> +	u32 bat_percentage;
> +	u32 power_slider;
> +	u32 lid_state;
> +	bool user_present;
> +	u32 rsvd1[2];
> +	u32 monitor_count;
> +	u32 rsvd2[2];
> +	u32 bat_design;
> +	u32 full_charge_capacity;
> +	int drain_rate;
> +	bool user_engaged;
> +	u32 device_state;
> +	u32 socket_power;
> +	u32 skin_temperature;
> +	u32 rsvd3[5];
> +	u32 ambient_light;
> +	u32 length;
> +	u32 avg_c0residency;
> +	u32 max_c0residency;
> +	u32 s0i3_entry;
> +	u32 gfx_busy;
> +	u32 rsvd4[7];
> +	bool camera_state;
> +	u32 workload_type;
> +	u32 display_type;
> +	u32 display_state;
> +	u32 rsvd5[150];
> +};
> +
> +struct ta_pmf_load_policy_table {
> +	u32 table_size;
> +	u8 table[POLICY_BUF_MAX_SZ];
> +};
> +
> +/* TA initialization params */
> +struct ta_pmf_init_table {
> +	u32 frequency; /* SMU sampling frequency */
> +	bool validate;
> +	bool sku_check;
> +	bool metadata_macrocheck;
> +	struct ta_pmf_load_policy_table policies_table;
> +};
> +
> +/* Everything the TA needs to Enact Policies */
> +struct ta_pmf_enact_table {
> +	struct ta_pmf_condition_info ev_info;
> +	u32 name;
> +};
> +
> +struct ta_pmf_action {
> +	u32 action_index;
> +	u32 value;
> +};
> +
> +/* output actions from TA */
> +struct ta_pmf_enact_result {
> +	u32 actions_count;
> +	struct ta_pmf_action actions_list[TA_PMF_ACTION_MAX];
> +	u32 undo_count;
> +	struct ta_pmf_action undo_list[TA_PMF_UNDO_MAX];
> +};
> +
> +union ta_pmf_input {
> +	struct ta_pmf_enact_table enact_table;
> +	struct ta_pmf_init_table init_table;
> +};
> +
> +union ta_pmf_output {
> +	struct ta_pmf_enact_result policy_apply_table;
> +	u32 rsvd[906];
> +};
> +
>   struct ta_pmf_shared_memory {
>   	int command_id;
>   	int resp_id;
>   	u32 pmf_result;
>   	u32 if_version;
> +	union ta_pmf_output pmf_output;
> +	union ta_pmf_input pmf_input;
>   };
>   
>   /* Core Layer */
> @@ -460,4 +591,5 @@ extern const struct attribute_group cnqf_feature_attribute_group;
>   /* Smart PC builder Layer*/
>   int amd_pmf_init_smart_pc(struct amd_pmf_dev *dev);
>   void amd_pmf_deinit_smart_pc(struct amd_pmf_dev *dev);
> +int apmf_check_smart_pc(struct amd_pmf_dev *pmf_dev);
>   #endif /* PMF_H */
> diff --git a/drivers/platform/x86/amd/pmf/tee-if.c b/drivers/platform/x86/amd/pmf/tee-if.c
> index 1fce04beacb3..a8b05e746efd 100644
> --- a/drivers/platform/x86/amd/pmf/tee-if.c
> +++ b/drivers/platform/x86/amd/pmf/tee-if.c
> @@ -42,9 +42,77 @@ static void amd_pmf_prepare_args(struct amd_pmf_dev *dev, int cmd,
>   	param[0].u.memref.shm_offs = 0;
>   }
>   
> +static void amd_pmf_apply_policies(struct amd_pmf_dev *dev, struct ta_pmf_enact_result *out)
> +{
> +	u32 val;
> +	int idx;
> +
> +	for (idx = 0; idx < out->actions_count; idx++) {
> +		val = out->actions_list[idx].value;
> +		switch (out->actions_list[idx].action_index) {
> +		case PMF_POLICY_SPL:
> +			if (dev->prev_data->spl != val) {
> +				amd_pmf_send_cmd(dev, SET_SPL, false, val, NULL);
> +				dev_dbg(dev->dev, "update SPL : %d\n", val);
> +				dev->prev_data->spl = val;
> +			}
> +			break;
> +
> +		case PMF_POLICY_SPPT:
> +			if (dev->prev_data->sppt != val) {
> +				amd_pmf_send_cmd(dev, SET_SPPT, false, val, NULL);
> +				dev_dbg(dev->dev, "update SPPT : %d\n", val);
> +				dev->prev_data->sppt = val;
> +			}
> +			break;
> +
> +		case PMF_POLICY_FPPT:
> +			if (dev->prev_data->fppt != val) {
> +				amd_pmf_send_cmd(dev, SET_FPPT, false, val, NULL);
> +				dev_dbg(dev->dev, "update FPPT : %d\n", val);
> +				dev->prev_data->fppt = val;
> +			}
> +			break;
> +
> +		case PMF_POLICY_SPPT_APU_ONLY:
> +			if (dev->prev_data->sppt_apuonly != val) {
> +				amd_pmf_send_cmd(dev, SET_SPPT_APU_ONLY, false, val, NULL);
> +				dev_dbg(dev->dev, "update SPPT_APU_ONLY : %d\n", val);
> +				dev->prev_data->sppt_apuonly = val;
> +			}
> +			break;
> +
> +		case PMF_POLICY_STT_MIN:
> +			if (dev->prev_data->stt_minlimit != val) {
> +				amd_pmf_send_cmd(dev, SET_STT_MIN_LIMIT, false, val, NULL);
> +				dev_dbg(dev->dev, "update STT_MIN : %d\n", val);
> +				dev->prev_data->stt_minlimit = val;
> +			}
> +			break;
> +
> +		case PMF_POLICY_STT_SKINTEMP_APU:
> +			if (dev->prev_data->stt_skintemp_apu != val) {
> +				amd_pmf_send_cmd(dev, SET_STT_LIMIT_APU, false, val, NULL);
> +				dev_dbg(dev->dev, "update STT_SKINTEMP_APU : %d\n", val);
> +				dev->prev_data->stt_skintemp_apu = val;
> +			}
> +			break;
> +
> +		case PMF_POLICY_STT_SKINTEMP_HS2:
> +			if (dev->prev_data->stt_skintemp_hs2 != val) {
> +				amd_pmf_send_cmd(dev, SET_STT_LIMIT_HS2, false, val, NULL);
> +				dev_dbg(dev->dev, "update STT_SKINTEMP_HS2 : %d\n", val);
> +				dev->prev_data->stt_skintemp_hs2 = val;
> +			}
> +			break;
> +		}
> +	}
> +}
> +
>   static int amd_pmf_invoke_cmd_enact(struct amd_pmf_dev *dev)
>   {
>   	struct ta_pmf_shared_memory *ta_sm = NULL;
> +	struct ta_pmf_enact_result *out = NULL;
>   	struct tee_param param[MAX_TEE_PARAM];
>   	struct tee_ioctl_invoke_arg arg;
>   	int ret = 0;
> @@ -52,7 +120,10 @@ static int amd_pmf_invoke_cmd_enact(struct amd_pmf_dev *dev)
>   	if (!dev->tee_ctx)
>   		return -ENODEV;
>   
> +	memset(dev->shbuf, 0, dev->policy_sz);
>   	ta_sm = (struct ta_pmf_shared_memory *)dev->shbuf;
> +	out = &ta_sm->pmf_output.policy_apply_table;
> +
>   	memset(ta_sm, 0, sizeof(struct ta_pmf_shared_memory));
>   	ta_sm->command_id = TA_PMF_COMMAND_POLICY_BUILDER__ENACT_POLICIES;
>   	ta_sm->if_version = PMF_TA_IF_VERSION__MAJOR;
> @@ -65,6 +136,12 @@ static int amd_pmf_invoke_cmd_enact(struct amd_pmf_dev *dev)
>   		return -EINVAL;
>   	}
>   
> +	if (ta_sm->pmf_result == TA_PMF_TYPE__SUCCESS && out->actions_count) {
> +		dev_dbg(dev->dev, "action count:%d result:%x\n", out->actions_count,
> +			ta_sm->pmf_result);
> +		amd_pmf_apply_policies(dev, out);
> +	}
> +
>   	return 0;
>   }
>   
> @@ -72,6 +149,7 @@ static int amd_pmf_invoke_cmd_init(struct amd_pmf_dev *dev)
>   {
>   	struct ta_pmf_shared_memory *ta_sm = NULL;
>   	struct tee_param param[MAX_TEE_PARAM];
> +	struct ta_pmf_init_table *in = NULL;
>   	struct tee_ioctl_invoke_arg arg;
>   	int ret = 0;
>   
> @@ -80,10 +158,20 @@ static int amd_pmf_invoke_cmd_init(struct amd_pmf_dev *dev)
>   		return -ENODEV;
>   	}
>   
> +	dev_dbg(dev->dev, "Policy Binary size: %d bytes\n", dev->policy_sz);
> +	memset(dev->shbuf, 0, dev->policy_sz);
>   	ta_sm = (struct ta_pmf_shared_memory *)dev->shbuf;
> +	in = &ta_sm->pmf_input.init_table;
> +
>   	ta_sm->command_id = TA_PMF_COMMAND_POLICY_BUILDER__INITIALIZE;
>   	ta_sm->if_version = PMF_TA_IF_VERSION__MAJOR;
> +	in->metadata_macrocheck = false;
> +	in->sku_check = false;
> +	in->validate = true;
> +	in->frequency = pb_actions_ms;
> +	in->policies_table.table_size = dev->policy_sz;
>   
> +	memcpy(in->policies_table.table, dev->policy_buf, dev->policy_sz);
>   	amd_pmf_prepare_args(dev, TA_PMF_COMMAND_POLICY_BUILDER__INITIALIZE, &arg, param);
>   
>   	ret = tee_client_invoke_func(dev->tee_ctx, &arg, param);
> @@ -103,6 +191,47 @@ static void amd_pmf_invoke_cmd(struct work_struct *work)
>   	schedule_delayed_work(&dev->pb_work, msecs_to_jiffies(pb_actions_ms));
>   }
>   
> +static int amd_pmf_start_policy_engine(struct amd_pmf_dev *dev)
> +{
> +	u32 cookie, length;
> +	int res;
> +
> +	cookie = readl(dev->policy_buf + 0x10);
> +	length = readl(dev->policy_buf + 0x14);
> +
> +	if (cookie != POLICY_SIGN_COOKIE || !length)
> +		return -EINVAL;
> +
> +	/* update the actual length */
> +	dev->policy_sz = length + 512;
> +	res = amd_pmf_invoke_cmd_init(dev);
> +	if (res == TA_PMF_TYPE__SUCCESS) {
> +		/* now its safe to announce that smart pc is enabled */
> +		dev->smart_pc_enabled = 1;
> +		schedule_delayed_work(&dev->pb_work, msecs_to_jiffies(pb_actions_ms * 3));
> +	} else {
> +		dev_err(dev->dev, "%s ta invoke_cmd_init failed err: %x\n", __func__, res);
> +		return res;
> +	}
> +
> +	return 0;
> +}
> +
> +static int amd_pmf_get_bios_buffer(struct amd_pmf_dev *dev)
> +{
> +	dev->policy_buf = kzalloc(dev->policy_sz, GFP_KERNEL);
> +	if (!dev->policy_buf)
> +		return -ENOMEM;
> +
> +	dev->policy_base = ioremap(dev->policy_addr, dev->policy_sz);
> +	if (!dev->policy_base)
> +		return -ENOMEM;
> +
> +	memcpy(dev->policy_buf, dev->policy_base, dev->policy_sz);
> +
> +	return amd_pmf_start_policy_engine(dev);
> +}
> +
>   static int amd_pmf_amdtee_ta_match(struct tee_ioctl_version_data *ver, const void *data)
>   {
>   	return ver->impl_id == TEE_IMPL_ID_AMDTEE;
> @@ -149,7 +278,7 @@ static int amd_pmf_tee_init(struct amd_pmf_dev *dev)
>   		goto out_ctx;
>   	}
>   
> -	size = sizeof(struct ta_pmf_shared_memory);
> +	size = sizeof(struct ta_pmf_shared_memory) + dev->policy_sz;
>   	dev->fw_shm_pool = tee_shm_alloc_kernel_buf(dev->tee_ctx, size);
>   	if (IS_ERR(dev->fw_shm_pool)) {
>   		dev_err(dev->dev, "%s: tee_shm_alloc_kernel_buf failed\n", __func__);
> @@ -191,11 +320,19 @@ int amd_pmf_init_smart_pc(struct amd_pmf_dev *dev)
>   		return ret;
>   
>   	INIT_DELAYED_WORK(&dev->pb_work, amd_pmf_invoke_cmd);
> -	return 0;
> +	amd_pmf_set_dram_addr(dev);
> +	amd_pmf_get_bios_buffer(dev);
> +	dev->prev_data = kzalloc(sizeof(*dev->prev_data), GFP_KERNEL);
> +	if (!dev->prev_data)
> +		return -ENOMEM;
> +
> +	return dev->smart_pc_enabled;
>   }
>   
>   void amd_pmf_deinit_smart_pc(struct amd_pmf_dev *dev)
>   {
> +	kfree(dev->prev_data);
> +	kfree(dev->policy_buf);
>   	cancel_delayed_work_sync(&dev->pb_work);
>   	amd_pmf_tee_deinit(dev);
>   }


^ permalink raw reply	[flat|nested] 54+ messages in thread

* Re: [PATCH 11/15] platform/x86/amd/pmf: dump policy binary data
  2023-09-22 17:50 ` [PATCH 11/15] platform/x86/amd/pmf: dump policy binary data Shyam Sundar S K
@ 2023-09-22 19:01   ` Mario Limonciello
  2023-09-30  4:41     ` Shyam Sundar S K
  0 siblings, 1 reply; 54+ messages in thread
From: Mario Limonciello @ 2023-09-22 19:01 UTC (permalink / raw)
  To: Shyam Sundar S K, hdegoede, markgross, basavaraj.natikar, jikos,
	benjamin.tissoires, alexander.deucher, christian.koenig,
	Xinhui.Pan, airlied, daniel
  Cc: dri-devel, linux-input, amd-gfx, Patil.Reddy, platform-driver-x86

On 9/22/2023 12:50, Shyam Sundar S K wrote:
> Sometimes policy binary retrieved from the BIOS maybe incorrect that can
> end up in failing to enable the Smart PC solution feature.
> 
> Use print_hex_dump_debug() to dump the policy binary in hex, so that we
> debug the issues related to the binary even before sending that to TA.
> 
> Signed-off-by: Shyam Sundar S K <Shyam-sundar.S-k@amd.com>
> ---
>   drivers/platform/x86/amd/pmf/tee-if.c | 7 +++++++
>   1 file changed, 7 insertions(+)
> 
> diff --git a/drivers/platform/x86/amd/pmf/tee-if.c b/drivers/platform/x86/amd/pmf/tee-if.c
> index fa37cfab2dc7..3daa122f35d5 100644
> --- a/drivers/platform/x86/amd/pmf/tee-if.c
> +++ b/drivers/platform/x86/amd/pmf/tee-if.c
> @@ -290,6 +290,9 @@ static ssize_t amd_pmf_get_pb_data(struct file *filp, const char __user *buf,
>   	if (copy_from_user(dev->policy_buf, buf, dev->policy_sz))
>   		return -EFAULT;
>   
> +	print_hex_dump_debug("(pb):  ", DUMP_PREFIX_OFFSET, 16, 1, dev->policy_buf,
> +			     dev->policy_sz, false);
> +

Should this one also be guarded by CONFIG_AMD_PMF_DEBUG or no?

>   	ret = amd_pmf_start_policy_engine(dev);
>   	if (ret)
>   		return -EINVAL;
> @@ -329,6 +332,10 @@ static int amd_pmf_get_bios_buffer(struct amd_pmf_dev *dev)
>   		return -ENOMEM;
>   
>   	memcpy(dev->policy_buf, dev->policy_base, dev->policy_sz);
> +#ifdef CONFIG_AMD_PMF_DEBUG
> +	print_hex_dump_debug("(pb):  ", DUMP_PREFIX_OFFSET, 16, 1, dev->policy_buf,
> +			     dev->policy_sz, false);
> +#endif
>   
>   #ifdef CONFIG_AMD_PMF_DEBUG
>   	if (pb_side_load)

It looks like you can combine the two #ifdef from the previous patches.

^ permalink raw reply	[flat|nested] 54+ messages in thread

* Re: [PATCH 14/15] platform/x86/amd/pmf: Add PMF-AMDSFH interface for HPD
  2023-09-22 17:50 ` [PATCH 14/15] platform/x86/amd/pmf: Add PMF-AMDSFH interface for HPD Shyam Sundar S K
@ 2023-09-22 19:04   ` Mario Limonciello
  2023-09-22 21:04     ` Mario Limonciello
  2023-09-27 13:32   ` Ilpo Järvinen
  1 sibling, 1 reply; 54+ messages in thread
From: Mario Limonciello @ 2023-09-22 19:04 UTC (permalink / raw)
  To: Shyam Sundar S K, hdegoede, markgross, basavaraj.natikar, jikos,
	benjamin.tissoires, alexander.deucher, christian.koenig,
	Xinhui.Pan, airlied, daniel
  Cc: dri-devel, linux-input, amd-gfx, Patil.Reddy, platform-driver-x86

On 9/22/2023 12:50, Shyam Sundar S K wrote:
> From: Basavaraj Natikar <Basavaraj.Natikar@amd.com>
> 
> AMDSFH has information about the User presence information via the Human
> Presence Detection (HPD) sensor which is part of the AMD sensor fusion hub.
> Add PMF and AMDSFH interface to get this information.
> 
> Co-developed-by: Shyam Sundar S K <Shyam-sundar.S-k@amd.com>
> Signed-off-by: Shyam Sundar S K <Shyam-sundar.S-k@amd.com>
> Signed-off-by: Basavaraj Natikar <Basavaraj.Natikar@amd.com>
> ---
>   drivers/hid/amd-sfh-hid/amd_sfh_common.h      |  5 ++++
>   drivers/hid/amd-sfh-hid/sfh1_1/amd_sfh_desc.c |  2 +-
>   drivers/hid/amd-sfh-hid/sfh1_1/amd_sfh_init.c | 11 ++++++++
>   .../amd-sfh-hid/sfh1_1/amd_sfh_interface.c    | 28 +++++++++++++++++++
>   .../amd-sfh-hid/sfh1_1/amd_sfh_interface.h    |  1 +
>   drivers/platform/x86/amd/pmf/spc.c            | 21 ++++++++++++++
>   include/linux/amd-pmf-io.h                    | 22 ++++++++++++++-
>   7 files changed, 88 insertions(+), 2 deletions(-)
> 
> diff --git a/drivers/hid/amd-sfh-hid/amd_sfh_common.h b/drivers/hid/amd-sfh-hid/amd_sfh_common.h
> index 2643bb14fee2..cd57037bf217 100644
> --- a/drivers/hid/amd-sfh-hid/amd_sfh_common.h
> +++ b/drivers/hid/amd-sfh-hid/amd_sfh_common.h
> @@ -37,6 +37,10 @@ struct amd_mp2_sensor_info {
>   	dma_addr_t dma_address;
>   };
>   
> +struct sfh_dev_status {
> +	bool is_hpd_present;
> +};
> +
>   struct amd_mp2_dev {
>   	struct pci_dev *pdev;
>   	struct amdtp_cl_data *cl_data;
> @@ -47,6 +51,7 @@ struct amd_mp2_dev {
>   	struct amd_input_data in_data;
>   	/* mp2 active control status */
>   	u32 mp2_acs;
> +	struct sfh_dev_status dev_en;
>   };
>   
>   struct amd_mp2_ops {
> diff --git a/drivers/hid/amd-sfh-hid/sfh1_1/amd_sfh_desc.c b/drivers/hid/amd-sfh-hid/sfh1_1/amd_sfh_desc.c
> index 06bdcf072d10..d7467c41ad3b 100644
> --- a/drivers/hid/amd-sfh-hid/sfh1_1/amd_sfh_desc.c
> +++ b/drivers/hid/amd-sfh-hid/sfh1_1/amd_sfh_desc.c
> @@ -132,7 +132,7 @@ static void get_common_inputs(struct common_input_property *common, int report_i
>   	common->event_type = HID_USAGE_SENSOR_EVENT_DATA_UPDATED_ENUM;
>   }
>   
> -static int float_to_int(u32 flt32_val)
> +int float_to_int(u32 flt32_val)
>   {
>   	int fraction, shift, mantissa, sign, exp, zeropre;
>   
> diff --git a/drivers/hid/amd-sfh-hid/sfh1_1/amd_sfh_init.c b/drivers/hid/amd-sfh-hid/sfh1_1/amd_sfh_init.c
> index e9c6413af24a..9c623456ee12 100644
> --- a/drivers/hid/amd-sfh-hid/sfh1_1/amd_sfh_init.c
> +++ b/drivers/hid/amd-sfh-hid/sfh1_1/amd_sfh_init.c
> @@ -73,6 +73,12 @@ static int amd_sfh_hid_client_deinit(struct amd_mp2_dev *privdata)
>   	int i, status;
>   
>   	for (i = 0; i < cl_data->num_hid_devices; i++) {
> +		switch (cl_data->sensor_idx[i]) {
> +		case HPD_IDX:
> +			privdata->dev_en.is_hpd_present = false;
> +			break;
> +		}
> +
>   		if (cl_data->sensor_sts[i] == SENSOR_ENABLED) {
>   			privdata->mp2_ops->stop(privdata, cl_data->sensor_idx[i]);
>   			status = amd_sfh_wait_for_response
> @@ -178,6 +184,11 @@ static int amd_sfh1_1_hid_client_init(struct amd_mp2_dev *privdata)
>   			rc = amdtp_hid_probe(i, cl_data);
>   			if (rc)
>   				goto cleanup;
> +			switch (cl_data->sensor_idx[i]) {
> +			case HPD_IDX:
> +			privdata->dev_en.is_hpd_present = true;

Looks like this is missing a tab.

> +				break;
> +			}
>   		}
>   		dev_dbg(dev, "sid 0x%x (%s) status 0x%x\n",
>   			cl_data->sensor_idx[i], get_sensor_name(cl_data->sensor_idx[i]),
> diff --git a/drivers/hid/amd-sfh-hid/sfh1_1/amd_sfh_interface.c b/drivers/hid/amd-sfh-hid/sfh1_1/amd_sfh_interface.c
> index 4f81ef2d4f56..63a5bbca5a09 100644
> --- a/drivers/hid/amd-sfh-hid/sfh1_1/amd_sfh_interface.c
> +++ b/drivers/hid/amd-sfh-hid/sfh1_1/amd_sfh_interface.c
> @@ -7,11 +7,14 @@
>    *
>    * Author: Basavaraj Natikar <Basavaraj.Natikar@amd.com>
>    */
> +#include <linux/amd-pmf-io.h>
>   #include <linux/io-64-nonatomic-lo-hi.h>
>   #include <linux/iopoll.h>
>   
>   #include "amd_sfh_interface.h"
>   
> +static struct amd_mp2_dev *emp2;
> +
>   static int amd_sfh_wait_response(struct amd_mp2_dev *mp2, u8 sid, u32 cmd_id)
>   {
>   	struct sfh_cmd_response cmd_resp;
> @@ -76,4 +79,29 @@ static struct amd_mp2_ops amd_sfh_ops = {
>   void sfh_interface_init(struct amd_mp2_dev *mp2)
>   {
>   	mp2->mp2_ops = &amd_sfh_ops;
> +	emp2 = mp2;
> +}
> +
> +static int amd_sfh_hpd_info(u8 *user_present)
> +{
> +	if (emp2 && emp2->dev_en.is_hpd_present) {
> +		struct hpd_status hpdstatus;
> +
> +		hpdstatus.val = readl(emp2->mmio + AMD_C2P_MSG(4));
> +		*user_present = hpdstatus.shpd.presence;
> +		return 0;
> +	}
> +	return  -ENODEV;

Extra whitespace here.

> +}
> +
> +int amd_get_sfh_info(struct amd_sfh_info *sfh_info, enum sfh_message_type op)
> +{
> +	if (sfh_info) {
> +		switch (op) {
> +		case MT_HPD:
> +			return amd_sfh_hpd_info(&sfh_info->user_present);
> +		}
> +	}
> +	return -1;

This looks like it should probably be -EINVAL.

>   }
> +EXPORT_SYMBOL_GPL(amd_get_sfh_info);
> diff --git a/drivers/hid/amd-sfh-hid/sfh1_1/amd_sfh_interface.h b/drivers/hid/amd-sfh-hid/sfh1_1/amd_sfh_interface.h
> index 9d31d5b510eb..8a36386e6bce 100644
> --- a/drivers/hid/amd-sfh-hid/sfh1_1/amd_sfh_interface.h
> +++ b/drivers/hid/amd-sfh-hid/sfh1_1/amd_sfh_interface.h
> @@ -149,6 +149,7 @@ struct hpd_status {
>   	};
>   };
>   
> +int float_to_int(u32 flt32_val);
>   void sfh_interface_init(struct amd_mp2_dev *mp2);
>   void amd_sfh1_1_set_desc_ops(struct amd_mp2_ops *mp2_ops);
>   #endif
> diff --git a/drivers/platform/x86/amd/pmf/spc.c b/drivers/platform/x86/amd/pmf/spc.c
> index 5f3ab1ce09d2..97293ae25cf5 100644
> --- a/drivers/platform/x86/amd/pmf/spc.c
> +++ b/drivers/platform/x86/amd/pmf/spc.c
> @@ -48,6 +48,7 @@ void amd_pmf_dump_ta_inputs(struct amd_pmf_dev *dev, struct ta_pmf_enact_table *
>   	dev_dbg(dev->dev, "Primary Display State : %s\n", in->ev_info.display_state ?
>   			"Connected" : "disconnected/unknown");
>   	dev_dbg(dev->dev, "LID State : %s\n", in->ev_info.lid_state ? "Close" : "Open");
> +	dev_dbg(dev->dev, "User Presence : %s\n", in->ev_info.user_present ? "Present" : "Away");
>   	dev_dbg(dev->dev, "==== TA inputs END ====\n");
>   }
>   #else
> @@ -156,6 +157,25 @@ static void amd_pmf_get_gpu_info(struct amd_pmf_dev *dev, struct ta_pmf_enact_ta
>   	in->ev_info.display_state = dev->gfx_data.con_status[0];
>   }
>   
> +static void amd_pmf_get_sensor_info(struct amd_pmf_dev *dev, struct ta_pmf_enact_table *in)
> +{
> +	struct amd_sfh_info sfh_info;
> +
> +	/* get HPD data */
> +	amd_get_sfh_info(&sfh_info, MT_HPD);

amd_get_sfh_info() is int.

Shouldn't you look for the return code here?

> +	switch (sfh_info.user_present) {
> +	case SFH_NOT_DETECTED:
> +		in->ev_info.user_present = 0xff; /* assume no sensors connected */
> +		break;
> +	case SFH_USER_PRESENT:
> +		in->ev_info.user_present = 1;
> +		break;
> +	case SFH_USER_AWAY:
> +		in->ev_info.user_present = 0;
> +		break;
> +	}
> +}
> +
>   void amd_pmf_populate_ta_inputs(struct amd_pmf_dev *dev, struct ta_pmf_enact_table *in)
>   {
>   	/* TA side lid open is 1 and close is 0, hence the ! here */
> @@ -165,4 +185,5 @@ void amd_pmf_populate_ta_inputs(struct amd_pmf_dev *dev, struct ta_pmf_enact_tab
>   	amd_pmf_get_battery_info(dev, in);
>   	amd_pmf_get_slider_info(dev, in);
>   	amd_pmf_get_gpu_info(dev, in);
> +	amd_pmf_get_sensor_info(dev, in);
>   }
> diff --git a/include/linux/amd-pmf-io.h b/include/linux/amd-pmf-io.h
> index ecae387ddaa6..4f82973f6ad2 100644
> --- a/include/linux/amd-pmf-io.h
> +++ b/include/linux/amd-pmf-io.h
> @@ -5,7 +5,8 @@
>    * Copyright (c) 2023, Advanced Micro Devices, Inc.
>    * All Rights Reserved.
>    *
> - * Author: Shyam Sundar S K <Shyam-sundar.S-k@amd.com>
> + * Authors: Shyam Sundar S K <Shyam-sundar.S-k@amd.com>
> + *          Basavaraj Natikar <Basavaraj.Natikar@amd.com>
>    */
>   
>   #ifndef AMD_PMF_IO_H
> @@ -26,4 +27,23 @@ struct amd_gpu_pmf_data {
>   
>   int amd_pmf_get_gfx_data(struct amd_gpu_pmf_data *pmf);
>   int amd_pmf_set_gfx_data(struct amd_gpu_pmf_data *pmf);
> +
> +/* amd-sfh */
> +enum sfh_message_type {
> +	MT_HPD,
> +};
> +
> +enum hpd_info {
> +	SFH_NOT_DETECTED,
> +	SFH_USER_PRESENT,
> +	SFH_USER_AWAY
> +};
> +
> +struct amd_sfh_info {
> +	u8 user_present;
> +	/* add future caps below */
> +};
> +
> +int amd_get_sfh_info(struct amd_sfh_info *sfh_info, enum sfh_message_type op);
> +
>   #endif


^ permalink raw reply	[flat|nested] 54+ messages in thread

* Re: [PATCH 15/15] platform/x86/amd/pmf: Add PMF-AMDSFH interface for ALS
  2023-09-22 17:50 ` [PATCH 15/15] platform/x86/amd/pmf: Add PMF-AMDSFH interface for ALS Shyam Sundar S K
@ 2023-09-22 19:06   ` Mario Limonciello
  2023-09-27 13:33   ` Ilpo Järvinen
  1 sibling, 0 replies; 54+ messages in thread
From: Mario Limonciello @ 2023-09-22 19:06 UTC (permalink / raw)
  To: Shyam Sundar S K, hdegoede, markgross, basavaraj.natikar, jikos,
	benjamin.tissoires, alexander.deucher, christian.koenig,
	Xinhui.Pan, airlied, daniel
  Cc: dri-devel, linux-input, amd-gfx, Patil.Reddy, platform-driver-x86

On 9/22/2023 12:50, Shyam Sundar S K wrote:
> From: Basavaraj Natikar <Basavaraj.Natikar@amd.com>
> 
> AMDSFH has information about the Ambient light via the Ambient
> Light Sensor (ALS) which is part of the AMD sensor fusion hub.
> Add PMF and AMDSFH interface to get this information.
> 
> Co-developed-by: Shyam Sundar S K <Shyam-sundar.S-k@amd.com>
> Signed-off-by: Shyam Sundar S K <Shyam-sundar.S-k@amd.com>
> Signed-off-by: Basavaraj Natikar <Basavaraj.Natikar@amd.com>
> ---
>   drivers/hid/amd-sfh-hid/amd_sfh_common.h      |  1 +
>   drivers/hid/amd-sfh-hid/sfh1_1/amd_sfh_init.c |  6 ++++++
>   .../amd-sfh-hid/sfh1_1/amd_sfh_interface.c    | 20 +++++++++++++++++++
>   drivers/platform/x86/amd/pmf/spc.c            |  5 +++++
>   include/linux/amd-pmf-io.h                    |  2 ++
>   5 files changed, 34 insertions(+)
> 
> diff --git a/drivers/hid/amd-sfh-hid/amd_sfh_common.h b/drivers/hid/amd-sfh-hid/amd_sfh_common.h
> index cd57037bf217..a1950bc6e6ce 100644
> --- a/drivers/hid/amd-sfh-hid/amd_sfh_common.h
> +++ b/drivers/hid/amd-sfh-hid/amd_sfh_common.h
> @@ -39,6 +39,7 @@ struct amd_mp2_sensor_info {
>   
>   struct sfh_dev_status {
>   	bool is_hpd_present;
> +	bool is_als_present;
>   };
>   
>   struct amd_mp2_dev {
> diff --git a/drivers/hid/amd-sfh-hid/sfh1_1/amd_sfh_init.c b/drivers/hid/amd-sfh-hid/sfh1_1/amd_sfh_init.c
> index 9c623456ee12..d8dad39d68b5 100644
> --- a/drivers/hid/amd-sfh-hid/sfh1_1/amd_sfh_init.c
> +++ b/drivers/hid/amd-sfh-hid/sfh1_1/amd_sfh_init.c
> @@ -77,6 +77,9 @@ static int amd_sfh_hid_client_deinit(struct amd_mp2_dev *privdata)
>   		case HPD_IDX:
>   			privdata->dev_en.is_hpd_present = false;
>   			break;
> +		case ALS_IDX:
> +			privdata->dev_en.is_als_present = false;
> +			break;
>   		}
>   
>   		if (cl_data->sensor_sts[i] == SENSOR_ENABLED) {
> @@ -188,6 +191,9 @@ static int amd_sfh1_1_hid_client_init(struct amd_mp2_dev *privdata)
>   			case HPD_IDX:
>   			privdata->dev_en.is_hpd_present = true;
>   				break;
> +			case ALS_IDX:
> +			privdata->dev_en.is_als_present = true;
> +				break;

Same missing tab here as previous patch

>   			}
>   		}
>   		dev_dbg(dev, "sid 0x%x (%s) status 0x%x\n",
> diff --git a/drivers/hid/amd-sfh-hid/sfh1_1/amd_sfh_interface.c b/drivers/hid/amd-sfh-hid/sfh1_1/amd_sfh_interface.c
> index 63a5bbca5a09..2f8200fc3062 100644
> --- a/drivers/hid/amd-sfh-hid/sfh1_1/amd_sfh_interface.c
> +++ b/drivers/hid/amd-sfh-hid/sfh1_1/amd_sfh_interface.c
> @@ -94,12 +94,32 @@ static int amd_sfh_hpd_info(u8 *user_present)
>   	return  -ENODEV;
>   }
>   
> +static int amd_sfh_als_info(u32 *ambient_light)
> +{
> +	if (emp2 && emp2->dev_en.is_als_present) {
> +		struct sfh_als_data als_data;
> +		void __iomem *sensoraddr;
> +
> +		sensoraddr = emp2->vsbase +
> +			(ALS_IDX * SENSOR_DATA_MEM_SIZE_DEFAULT) +
> +			OFFSET_SENSOR_DATA_DEFAULT;
> +		memcpy_fromio(&als_data, sensoraddr, sizeof(struct sfh_als_data));
> +		*ambient_light = float_to_int(als_data.lux);
> +
> +		return 0;
> +	}
> +
> +	return -ENODEV;
> +}
> +
>   int amd_get_sfh_info(struct amd_sfh_info *sfh_info, enum sfh_message_type op)
>   {
>   	if (sfh_info) {
>   		switch (op) {
>   		case MT_HPD:
>   			return amd_sfh_hpd_info(&sfh_info->user_present);
> +		case MT_ALS:
> +			return amd_sfh_als_info(&sfh_info->ambient_light);
>   		}
>   	}
>   	return -1;
> diff --git a/drivers/platform/x86/amd/pmf/spc.c b/drivers/platform/x86/amd/pmf/spc.c
> index 97293ae25cf5..8e19b351e76f 100644
> --- a/drivers/platform/x86/amd/pmf/spc.c
> +++ b/drivers/platform/x86/amd/pmf/spc.c
> @@ -49,6 +49,7 @@ void amd_pmf_dump_ta_inputs(struct amd_pmf_dev *dev, struct ta_pmf_enact_table *
>   			"Connected" : "disconnected/unknown");
>   	dev_dbg(dev->dev, "LID State : %s\n", in->ev_info.lid_state ? "Close" : "Open");
>   	dev_dbg(dev->dev, "User Presence : %s\n", in->ev_info.user_present ? "Present" : "Away");
> +	dev_dbg(dev->dev, "Ambient Light : %d\n", in->ev_info.ambient_light);
>   	dev_dbg(dev->dev, "==== TA inputs END ====\n");
>   }
>   #else
> @@ -161,6 +162,10 @@ static void amd_pmf_get_sensor_info(struct amd_pmf_dev *dev, struct ta_pmf_enact
>   {
>   	struct amd_sfh_info sfh_info;
>   
> +	/* get ALS data */
> +	amd_get_sfh_info(&sfh_info, MT_ALS);

Like previous patch, I think you should look at return code here.

> +	in->ev_info.ambient_light = sfh_info.ambient_light;
> +
>   	/* get HPD data */
>   	amd_get_sfh_info(&sfh_info, MT_HPD);
>   	switch (sfh_info.user_present) {
> diff --git a/include/linux/amd-pmf-io.h b/include/linux/amd-pmf-io.h
> index 4f82973f6ad2..dac0af573a16 100644
> --- a/include/linux/amd-pmf-io.h
> +++ b/include/linux/amd-pmf-io.h
> @@ -31,6 +31,7 @@ int amd_pmf_set_gfx_data(struct amd_gpu_pmf_data *pmf);
>   /* amd-sfh */
>   enum sfh_message_type {
>   	MT_HPD,
> +	MT_ALS,
>   };
>   
>   enum hpd_info {
> @@ -40,6 +41,7 @@ enum hpd_info {
>   };
>   
>   struct amd_sfh_info {
> +	u32 ambient_light;
>   	u8 user_present;
>   	/* add future caps below */
>   };


^ permalink raw reply	[flat|nested] 54+ messages in thread

* Re: [PATCH 14/15] platform/x86/amd/pmf: Add PMF-AMDSFH interface for HPD
  2023-09-22 19:04   ` Mario Limonciello
@ 2023-09-22 21:04     ` Mario Limonciello
  0 siblings, 0 replies; 54+ messages in thread
From: Mario Limonciello @ 2023-09-22 21:04 UTC (permalink / raw)
  To: Shyam Sundar S K, hdegoede, markgross, basavaraj.natikar, jikos,
	benjamin.tissoires, alexander.deucher, christian.koenig,
	Xinhui.Pan, airlied, daniel
  Cc: dri-devel, linux-input, amd-gfx, Patil.Reddy, platform-driver-x86

On 9/22/2023 14:04, Mario Limonciello wrote:
> On 9/22/2023 12:50, Shyam Sundar S K wrote:
>> From: Basavaraj Natikar <Basavaraj.Natikar@amd.com>
>>
>> AMDSFH has information about the User presence information via the Human
>> Presence Detection (HPD) sensor which is part of the AMD sensor fusion 
>> hub.
>> Add PMF and AMDSFH interface to get this information.
>>
>> Co-developed-by: Shyam Sundar S K <Shyam-sundar.S-k@amd.com>
>> Signed-off-by: Shyam Sundar S K <Shyam-sundar.S-k@amd.com>
>> Signed-off-by: Basavaraj Natikar <Basavaraj.Natikar@amd.com>
>> ---
>>   drivers/hid/amd-sfh-hid/amd_sfh_common.h      |  5 ++++
>>   drivers/hid/amd-sfh-hid/sfh1_1/amd_sfh_desc.c |  2 +-
>>   drivers/hid/amd-sfh-hid/sfh1_1/amd_sfh_init.c | 11 ++++++++
>>   .../amd-sfh-hid/sfh1_1/amd_sfh_interface.c    | 28 +++++++++++++++++++
>>   .../amd-sfh-hid/sfh1_1/amd_sfh_interface.h    |  1 +
>>   drivers/platform/x86/amd/pmf/spc.c            | 21 ++++++++++++++
>>   include/linux/amd-pmf-io.h                    | 22 ++++++++++++++-
>>   7 files changed, 88 insertions(+), 2 deletions(-)

Somthing else I noticed about this change.

I believe you should be adding to Kconfig:
depends on AMD_SFH_HID

>>
>> diff --git a/drivers/hid/amd-sfh-hid/amd_sfh_common.h 
>> b/drivers/hid/amd-sfh-hid/amd_sfh_common.h
>> index 2643bb14fee2..cd57037bf217 100644
>> --- a/drivers/hid/amd-sfh-hid/amd_sfh_common.h
>> +++ b/drivers/hid/amd-sfh-hid/amd_sfh_common.h
>> @@ -37,6 +37,10 @@ struct amd_mp2_sensor_info {
>>       dma_addr_t dma_address;
>>   };
>> +struct sfh_dev_status {
>> +    bool is_hpd_present;
>> +};
>> +
>>   struct amd_mp2_dev {
>>       struct pci_dev *pdev;
>>       struct amdtp_cl_data *cl_data;
>> @@ -47,6 +51,7 @@ struct amd_mp2_dev {
>>       struct amd_input_data in_data;
>>       /* mp2 active control status */
>>       u32 mp2_acs;
>> +    struct sfh_dev_status dev_en;
>>   };
>>   struct amd_mp2_ops {
>> diff --git a/drivers/hid/amd-sfh-hid/sfh1_1/amd_sfh_desc.c 
>> b/drivers/hid/amd-sfh-hid/sfh1_1/amd_sfh_desc.c
>> index 06bdcf072d10..d7467c41ad3b 100644
>> --- a/drivers/hid/amd-sfh-hid/sfh1_1/amd_sfh_desc.c
>> +++ b/drivers/hid/amd-sfh-hid/sfh1_1/amd_sfh_desc.c
>> @@ -132,7 +132,7 @@ static void get_common_inputs(struct 
>> common_input_property *common, int report_i
>>       common->event_type = HID_USAGE_SENSOR_EVENT_DATA_UPDATED_ENUM;
>>   }
>> -static int float_to_int(u32 flt32_val)
>> +int float_to_int(u32 flt32_val)
>>   {
>>       int fraction, shift, mantissa, sign, exp, zeropre;
>> diff --git a/drivers/hid/amd-sfh-hid/sfh1_1/amd_sfh_init.c 
>> b/drivers/hid/amd-sfh-hid/sfh1_1/amd_sfh_init.c
>> index e9c6413af24a..9c623456ee12 100644
>> --- a/drivers/hid/amd-sfh-hid/sfh1_1/amd_sfh_init.c
>> +++ b/drivers/hid/amd-sfh-hid/sfh1_1/amd_sfh_init.c
>> @@ -73,6 +73,12 @@ static int amd_sfh_hid_client_deinit(struct 
>> amd_mp2_dev *privdata)
>>       int i, status;
>>       for (i = 0; i < cl_data->num_hid_devices; i++) {
>> +        switch (cl_data->sensor_idx[i]) {
>> +        case HPD_IDX:
>> +            privdata->dev_en.is_hpd_present = false;
>> +            break;
>> +        }
>> +
>>           if (cl_data->sensor_sts[i] == SENSOR_ENABLED) {
>>               privdata->mp2_ops->stop(privdata, cl_data->sensor_idx[i]);
>>               status = amd_sfh_wait_for_response
>> @@ -178,6 +184,11 @@ static int amd_sfh1_1_hid_client_init(struct 
>> amd_mp2_dev *privdata)
>>               rc = amdtp_hid_probe(i, cl_data);
>>               if (rc)
>>                   goto cleanup;
>> +            switch (cl_data->sensor_idx[i]) {
>> +            case HPD_IDX:
>> +            privdata->dev_en.is_hpd_present = true;
> 
> Looks like this is missing a tab.
> 
>> +                break;
>> +            }
>>           }
>>           dev_dbg(dev, "sid 0x%x (%s) status 0x%x\n",
>>               cl_data->sensor_idx[i], 
>> get_sensor_name(cl_data->sensor_idx[i]),
>> diff --git a/drivers/hid/amd-sfh-hid/sfh1_1/amd_sfh_interface.c 
>> b/drivers/hid/amd-sfh-hid/sfh1_1/amd_sfh_interface.c
>> index 4f81ef2d4f56..63a5bbca5a09 100644
>> --- a/drivers/hid/amd-sfh-hid/sfh1_1/amd_sfh_interface.c
>> +++ b/drivers/hid/amd-sfh-hid/sfh1_1/amd_sfh_interface.c
>> @@ -7,11 +7,14 @@
>>    *
>>    * Author: Basavaraj Natikar <Basavaraj.Natikar@amd.com>
>>    */
>> +#include <linux/amd-pmf-io.h>
>>   #include <linux/io-64-nonatomic-lo-hi.h>
>>   #include <linux/iopoll.h>
>>   #include "amd_sfh_interface.h"
>> +static struct amd_mp2_dev *emp2;
>> +
>>   static int amd_sfh_wait_response(struct amd_mp2_dev *mp2, u8 sid, 
>> u32 cmd_id)
>>   {
>>       struct sfh_cmd_response cmd_resp;
>> @@ -76,4 +79,29 @@ static struct amd_mp2_ops amd_sfh_ops = {
>>   void sfh_interface_init(struct amd_mp2_dev *mp2)
>>   {
>>       mp2->mp2_ops = &amd_sfh_ops;
>> +    emp2 = mp2;
>> +}
>> +
>> +static int amd_sfh_hpd_info(u8 *user_present)
>> +{
>> +    if (emp2 && emp2->dev_en.is_hpd_present) {
>> +        struct hpd_status hpdstatus;
>> +
>> +        hpdstatus.val = readl(emp2->mmio + AMD_C2P_MSG(4));
>> +        *user_present = hpdstatus.shpd.presence;
>> +        return 0;
>> +    }
>> +    return  -ENODEV;
> 
> Extra whitespace here.
> 
>> +}
>> +

IMO you should add some kernel doc here or in the header as good 
practice for exported symbols.

>> +int amd_get_sfh_info(struct amd_sfh_info *sfh_info, enum 
>> sfh_message_type op)
>> +{
>> +    if (sfh_info) {
>> +        switch (op) {
>> +        case MT_HPD:
>> +            return amd_sfh_hpd_info(&sfh_info->user_present);
>> +        }
>> +    }
>> +    return -1;
> 
> This looks like it should probably be -EINVAL.
> 
>>   }
>> +EXPORT_SYMBOL_GPL(amd_get_sfh_info);
>> diff --git a/drivers/hid/amd-sfh-hid/sfh1_1/amd_sfh_interface.h 
>> b/drivers/hid/amd-sfh-hid/sfh1_1/amd_sfh_interface.h
>> index 9d31d5b510eb..8a36386e6bce 100644
>> --- a/drivers/hid/amd-sfh-hid/sfh1_1/amd_sfh_interface.h
>> +++ b/drivers/hid/amd-sfh-hid/sfh1_1/amd_sfh_interface.h
>> @@ -149,6 +149,7 @@ struct hpd_status {
>>       };
>>   };
>> +int float_to_int(u32 flt32_val);
>>   void sfh_interface_init(struct amd_mp2_dev *mp2);
>>   void amd_sfh1_1_set_desc_ops(struct amd_mp2_ops *mp2_ops);
>>   #endif
>> diff --git a/drivers/platform/x86/amd/pmf/spc.c 
>> b/drivers/platform/x86/amd/pmf/spc.c
>> index 5f3ab1ce09d2..97293ae25cf5 100644
>> --- a/drivers/platform/x86/amd/pmf/spc.c
>> +++ b/drivers/platform/x86/amd/pmf/spc.c
>> @@ -48,6 +48,7 @@ void amd_pmf_dump_ta_inputs(struct amd_pmf_dev *dev, 
>> struct ta_pmf_enact_table *
>>       dev_dbg(dev->dev, "Primary Display State : %s\n", 
>> in->ev_info.display_state ?
>>               "Connected" : "disconnected/unknown");
>>       dev_dbg(dev->dev, "LID State : %s\n", in->ev_info.lid_state ? 
>> "Close" : "Open");
>> +    dev_dbg(dev->dev, "User Presence : %s\n", 
>> in->ev_info.user_present ? "Present" : "Away");
>>       dev_dbg(dev->dev, "==== TA inputs END ====\n");
>>   }
>>   #else
>> @@ -156,6 +157,25 @@ static void amd_pmf_get_gpu_info(struct 
>> amd_pmf_dev *dev, struct ta_pmf_enact_ta
>>       in->ev_info.display_state = dev->gfx_data.con_status[0];
>>   }
>> +static void amd_pmf_get_sensor_info(struct amd_pmf_dev *dev, struct 
>> ta_pmf_enact_table *in)
>> +{
>> +    struct amd_sfh_info sfh_info;
>> +
>> +    /* get HPD data */
>> +    amd_get_sfh_info(&sfh_info, MT_HPD);
> 
> amd_get_sfh_info() is int.
> 
> Shouldn't you look for the return code here?
> 
>> +    switch (sfh_info.user_present) {
>> +    case SFH_NOT_DETECTED:
>> +        in->ev_info.user_present = 0xff; /* assume no sensors 
>> connected */
>> +        break;
>> +    case SFH_USER_PRESENT:
>> +        in->ev_info.user_present = 1;
>> +        break;
>> +    case SFH_USER_AWAY:
>> +        in->ev_info.user_present = 0;
>> +        break;
>> +    }
>> +}
>> +
>>   void amd_pmf_populate_ta_inputs(struct amd_pmf_dev *dev, struct 
>> ta_pmf_enact_table *in)
>>   {
>>       /* TA side lid open is 1 and close is 0, hence the ! here */
>> @@ -165,4 +185,5 @@ void amd_pmf_populate_ta_inputs(struct amd_pmf_dev 
>> *dev, struct ta_pmf_enact_tab
>>       amd_pmf_get_battery_info(dev, in);
>>       amd_pmf_get_slider_info(dev, in);
>>       amd_pmf_get_gpu_info(dev, in);
>> +    amd_pmf_get_sensor_info(dev, in);
>>   }
>> diff --git a/include/linux/amd-pmf-io.h b/include/linux/amd-pmf-io.h
>> index ecae387ddaa6..4f82973f6ad2 100644
>> --- a/include/linux/amd-pmf-io.h
>> +++ b/include/linux/amd-pmf-io.h
>> @@ -5,7 +5,8 @@
>>    * Copyright (c) 2023, Advanced Micro Devices, Inc.
>>    * All Rights Reserved.
>>    *
>> - * Author: Shyam Sundar S K <Shyam-sundar.S-k@amd.com>
>> + * Authors: Shyam Sundar S K <Shyam-sundar.S-k@amd.com>
>> + *          Basavaraj Natikar <Basavaraj.Natikar@amd.com>
>>    */
>>   #ifndef AMD_PMF_IO_H
>> @@ -26,4 +27,23 @@ struct amd_gpu_pmf_data {
>>   int amd_pmf_get_gfx_data(struct amd_gpu_pmf_data *pmf);
>>   int amd_pmf_set_gfx_data(struct amd_gpu_pmf_data *pmf);
>> +
>> +/* amd-sfh */
>> +enum sfh_message_type {
>> +    MT_HPD,
>> +};
>> +
>> +enum hpd_info {
>> +    SFH_NOT_DETECTED,
>> +    SFH_USER_PRESENT,
>> +    SFH_USER_AWAY
>> +};
>> +
>> +struct amd_sfh_info {
>> +    u8 user_present;
>> +    /* add future caps below */
>> +};
>> +
>> +int amd_get_sfh_info(struct amd_sfh_info *sfh_info, enum 
>> sfh_message_type op);
>> +
>>   #endif
> 


^ permalink raw reply	[flat|nested] 54+ messages in thread

* Re: [PATCH 10/15] platform/x86/amd/pmf: Add capability to sideload of policy binary
  2023-09-22 17:50 ` [PATCH 10/15] platform/x86/amd/pmf: Add capability to sideload of policy binary Shyam Sundar S K
@ 2023-09-25  2:14   ` kernel test robot
  2023-09-27 12:33   ` Ilpo Järvinen
  1 sibling, 0 replies; 54+ messages in thread
From: kernel test robot @ 2023-09-25  2:14 UTC (permalink / raw)
  To: Shyam Sundar S K, hdegoede, markgross, basavaraj.natikar, jikos,
	benjamin.tissoires, alexander.deucher, christian.koenig,
	Xinhui.Pan, airlied, daniel
  Cc: Shyam Sundar S K, linux-input, dri-devel, platform-driver-x86,
	amd-gfx, Patil.Reddy, oe-kbuild-all, mario.limonciello

Hi Shyam,

kernel test robot noticed the following build warnings:

[auto build test WARNING on hid/for-next]
[also build test WARNING on linus/master v6.6-rc3 next-20230921]
[cannot apply to drm-misc/drm-misc-next]
[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/Shyam-Sundar-S-K/platform-x86-amd-pmf-Add-PMF-TEE-interface/20230923-015418
base:   https://git.kernel.org/pub/scm/linux/kernel/git/hid/hid.git for-next
patch link:    https://lore.kernel.org/r/20230922175056.244940-11-Shyam-sundar.S-k%40amd.com
patch subject: [PATCH 10/15] platform/x86/amd/pmf: Add capability to sideload of policy binary
config: x86_64-allyesconfig (https://download.01.org/0day-ci/archive/20230925/202309251031.awDDkRgS-lkp@intel.com/config)
compiler: gcc-12 (Debian 12.2.0-14) 12.2.0
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20230925/202309251031.awDDkRgS-lkp@intel.com/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 <lkp@intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202309251031.awDDkRgS-lkp@intel.com/

All warnings (new ones prefixed by >>):

>> drivers/platform/x86/amd/pmf/tee-if.c:305:5: warning: no previous prototype for 'amd_pmf_open_pb' [-Wmissing-prototypes]
     305 | int amd_pmf_open_pb(struct amd_pmf_dev *dev, struct dentry *debugfs_root)
         |     ^~~~~~~~~~~~~~~


vim +/amd_pmf_open_pb +305 drivers/platform/x86/amd/pmf/tee-if.c

   304	
 > 305	int amd_pmf_open_pb(struct amd_pmf_dev *dev, struct dentry *debugfs_root)
   306	{
   307		struct dentry *file = NULL;
   308	
   309		dev->esbin = debugfs_create_dir("pb", debugfs_root);
   310		if (IS_ERR(dev->esbin))
   311			return -EINVAL;
   312	
   313		file = debugfs_create_file("update_policy", 0644, dev->esbin, dev, &pb_fops);
   314		if (!file)
   315			return -EINVAL;
   316	
   317		return 0;
   318	}
   319	#endif
   320	

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

^ permalink raw reply	[flat|nested] 54+ messages in thread

* RE: [PATCH 13/15] platform/x86/amd/pmf: Add PMF-AMDGPU set interface
  2023-09-22 17:50 ` [PATCH 13/15] platform/x86/amd/pmf: Add PMF-AMDGPU set interface Shyam Sundar S K
@ 2023-09-25 16:27   ` Deucher, Alexander
  2023-09-25 16:30     ` Mario Limonciello
  2023-09-26 11:15     ` Shyam Sundar S K
  2023-09-26 10:35   ` Hans de Goede
  2023-09-27 13:36   ` Ilpo Järvinen
  2 siblings, 2 replies; 54+ messages in thread
From: Deucher, Alexander @ 2023-09-25 16:27 UTC (permalink / raw)
  To: S-k, Shyam-sundar, hdegoede, markgross, Natikar, Basavaraj,
	jikos, benjamin.tissoires, Koenig, Christian, Pan, Xinhui,
	airlied, daniel
  Cc: S-k, Shyam-sundar, dri-devel, platform-driver-x86, amd-gfx,
	Patil Rajesh, linux-input, Limonciello, Mario

[Public]

> -----Original Message-----
> From: amd-gfx <amd-gfx-bounces@lists.freedesktop.org> On Behalf Of
> Shyam Sundar S K
> Sent: Friday, September 22, 2023 1:51 PM
> To: hdegoede@redhat.com; markgross@kernel.org; Natikar, Basavaraj
> <Basavaraj.Natikar@amd.com>; jikos@kernel.org;
> benjamin.tissoires@redhat.com; Deucher, Alexander
> <Alexander.Deucher@amd.com>; Koenig, Christian
> <Christian.Koenig@amd.com>; Pan, Xinhui <Xinhui.Pan@amd.com>;
> airlied@gmail.com; daniel@ffwll.ch
> Cc: S-k, Shyam-sundar <Shyam-sundar.S-k@amd.com>; amd-
> gfx@lists.freedesktop.org; platform-driver-x86@vger.kernel.org; dri-
> devel@lists.freedesktop.org; Patil Rajesh <Patil.Reddy@amd.com>; linux-
> input@vger.kernel.org; Limonciello, Mario <Mario.Limonciello@amd.com>
> Subject: [PATCH 13/15] platform/x86/amd/pmf: Add PMF-AMDGPU set
> interface
>
> For the Smart PC Solution to fully work, it has to enact to the actions coming
> from TA. Add the initial code path for set interface to AMDGPU.

This seems to be limited to backlight at this point.  What does setting or not setting the backlight level mean for the system when this framework is in place?  What if a user manually changes the backlight level?  Additional comments below.

>
> Co-developed-by: Mario Limonciello <mario.limonciello@amd.com>
> Signed-off-by: Mario Limonciello <mario.limonciello@amd.com>
> Signed-off-by: Shyam Sundar S K <Shyam-sundar.S-k@amd.com>
> ---
>  drivers/gpu/drm/amd/amdgpu/amdgpu_pmf.c | 21
> +++++++++++++++++++++
>  drivers/platform/x86/amd/pmf/pmf.h      |  2 ++
>  drivers/platform/x86/amd/pmf/tee-if.c   | 19 +++++++++++++++++--
>  include/linux/amd-pmf-io.h              |  1 +
>  4 files changed, 41 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_pmf.c
> b/drivers/gpu/drm/amd/amdgpu/amdgpu_pmf.c
> index 232d11833ddc..5c567bff0548 100644
> --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_pmf.c
> +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_pmf.c
> @@ -68,3 +68,24 @@ int amd_pmf_get_gfx_data(struct amd_gpu_pmf_data
> *pmf)
>       return 0;
>  }
>  EXPORT_SYMBOL_GPL(amd_pmf_get_gfx_data);
> +
> +int amd_pmf_set_gfx_data(struct amd_gpu_pmf_data *pmf) {
> +     struct drm_device *drm_dev = pci_get_drvdata(pmf->gpu_dev);
> +     struct amdgpu_device *adev = drm_to_adev(drm_dev);
> +     struct backlight_device *bd;
> +
> +     if (!(adev->flags & AMD_IS_APU)) {
> +             DRM_ERROR("PMF-AMDGPU interface not supported\n");
> +             return -ENODEV;
> +     }
> +
> +     bd = backlight_device_get_by_type(BACKLIGHT_RAW);
> +     if (!bd)
> +             return -ENODEV;
> +
> +     backlight_device_set_brightness(bd, pmf->brightness);
> +
> +     return 0;
> +}
> +EXPORT_SYMBOL_GPL(amd_pmf_set_gfx_data);
> diff --git a/drivers/platform/x86/amd/pmf/pmf.h
> b/drivers/platform/x86/amd/pmf/pmf.h
> index 9032df4ba48a..ce89cc0daa5a 100644
> --- a/drivers/platform/x86/amd/pmf/pmf.h
> +++ b/drivers/platform/x86/amd/pmf/pmf.h
> @@ -73,6 +73,7 @@
>  #define PMF_POLICY_STT_SKINTEMP_APU                          7
>  #define PMF_POLICY_STT_SKINTEMP_HS2                          8
>  #define PMF_POLICY_SYSTEM_STATE                                      9
> +#define PMF_POLICY_DISPLAY_BRIGHTNESS                                12
>  #define PMF_POLICY_P3T                                               38
>
>  /* TA macros */
> @@ -480,6 +481,7 @@ enum ta_pmf_error_type {  };
>
>  struct pmf_action_table {
> +     unsigned long display_brightness;
>       enum system_state system_state;
>       unsigned long spl; /* in mW */
>       unsigned long sppt; /* in mW */
> diff --git a/drivers/platform/x86/amd/pmf/tee-if.c
> b/drivers/platform/x86/amd/pmf/tee-if.c
> index 1608996654e8..eefffff83a4c 100644
> --- a/drivers/platform/x86/amd/pmf/tee-if.c
> +++ b/drivers/platform/x86/amd/pmf/tee-if.c
> @@ -79,10 +79,10 @@ static int amd_pmf_update_uevents(struct
> amd_pmf_dev *dev, u16 event)
>       return 0;
>  }
>
> -static void amd_pmf_apply_policies(struct amd_pmf_dev *dev, struct
> ta_pmf_enact_result *out)
> +static int amd_pmf_apply_policies(struct amd_pmf_dev *dev, struct
> +ta_pmf_enact_result *out)
>  {
>       u32 val, event = 0;
> -     int idx;
> +     int idx, ret;
>
>       for (idx = 0; idx < out->actions_count; idx++) {
>               val = out->actions_list[idx].value;
> @@ -160,8 +160,23 @@ static void amd_pmf_apply_policies(struct
> amd_pmf_dev *dev, struct ta_pmf_enact_
>                               dev->prev_data->system_state = 0;
>                       }
>                       break;
> +
> +             case PMF_POLICY_DISPLAY_BRIGHTNESS:
> +                     ret = amd_pmf_get_gfx_data(&dev->gfx_data);
> +                     if (ret)
> +                             return ret;
> +
> +                     dev->prev_data->display_brightness = dev-
> >gfx_data.brightness;

Are we using standardized units for the brightness?  On the GPU side, we align with the standard blacklight interface, but internally, the driver has to convert units depending on the type of backlight controller used on the platform.  Presumably PMF does something similar?

Alex

> +                     if (dev->prev_data->display_brightness != val) {
> +                             dev->gfx_data.brightness = val;
> +                             amd_pmf_set_gfx_data(&dev->gfx_data);
> +                             dev_dbg(dev->dev, "update
> DISPLAY_BRIGHTNESS : %d\n", val);
> +                     }
> +                     break;
>               }
>       }
> +
> +     return 0;
>  }
>
>  static int amd_pmf_invoke_cmd_enact(struct amd_pmf_dev *dev) diff --git
> a/include/linux/amd-pmf-io.h b/include/linux/amd-pmf-io.h index
> a2d4af231362..ecae387ddaa6 100644
> --- a/include/linux/amd-pmf-io.h
> +++ b/include/linux/amd-pmf-io.h
> @@ -25,4 +25,5 @@ struct amd_gpu_pmf_data {  };
>
>  int amd_pmf_get_gfx_data(struct amd_gpu_pmf_data *pmf);
> +int amd_pmf_set_gfx_data(struct amd_gpu_pmf_data *pmf);
>  #endif
> --
> 2.25.1


^ permalink raw reply	[flat|nested] 54+ messages in thread

* Re: [PATCH 13/15] platform/x86/amd/pmf: Add PMF-AMDGPU set interface
  2023-09-25 16:27   ` Deucher, Alexander
@ 2023-09-25 16:30     ` Mario Limonciello
  2023-09-26 11:17       ` Shyam Sundar S K
  2023-09-26 11:15     ` Shyam Sundar S K
  1 sibling, 1 reply; 54+ messages in thread
From: Mario Limonciello @ 2023-09-25 16:30 UTC (permalink / raw)
  To: Deucher, Alexander, S-k, Shyam-sundar, hdegoede, markgross,
	Natikar, Basavaraj, jikos, benjamin.tissoires, Koenig, Christian,
	Pan, Xinhui, airlied, daniel
  Cc: Patil Rajesh, linux-input, dri-devel, amd-gfx, platform-driver-x86

On 9/25/2023 11:27, Deucher, Alexander wrote:
> [Public]
> 
>> -----Original Message-----
>> From: amd-gfx <amd-gfx-bounces@lists.freedesktop.org> On Behalf Of
>> Shyam Sundar S K
>> Sent: Friday, September 22, 2023 1:51 PM
>> To: hdegoede@redhat.com; markgross@kernel.org; Natikar, Basavaraj
>> <Basavaraj.Natikar@amd.com>; jikos@kernel.org;
>> benjamin.tissoires@redhat.com; Deucher, Alexander
>> <Alexander.Deucher@amd.com>; Koenig, Christian
>> <Christian.Koenig@amd.com>; Pan, Xinhui <Xinhui.Pan@amd.com>;
>> airlied@gmail.com; daniel@ffwll.ch
>> Cc: S-k, Shyam-sundar <Shyam-sundar.S-k@amd.com>; amd-
>> gfx@lists.freedesktop.org; platform-driver-x86@vger.kernel.org; dri-
>> devel@lists.freedesktop.org; Patil Rajesh <Patil.Reddy@amd.com>; linux-
>> input@vger.kernel.org; Limonciello, Mario <Mario.Limonciello@amd.com>
>> Subject: [PATCH 13/15] platform/x86/amd/pmf: Add PMF-AMDGPU set
>> interface
>>
>> For the Smart PC Solution to fully work, it has to enact to the actions coming
>> from TA. Add the initial code path for set interface to AMDGPU.
> 
> This seems to be limited to backlight at this point.  What does setting or not setting the backlight level mean for the system when this framework is in place?  What if a user manually changes the backlight level?  Additional comments below.
> 

It's also for the display count.

>>
>> Co-developed-by: Mario Limonciello <mario.limonciello@amd.com>
>> Signed-off-by: Mario Limonciello <mario.limonciello@amd.com>
>> Signed-off-by: Shyam Sundar S K <Shyam-sundar.S-k@amd.com>
>> ---
>>   drivers/gpu/drm/amd/amdgpu/amdgpu_pmf.c | 21
>> +++++++++++++++++++++
>>   drivers/platform/x86/amd/pmf/pmf.h      |  2 ++
>>   drivers/platform/x86/amd/pmf/tee-if.c   | 19 +++++++++++++++++--
>>   include/linux/amd-pmf-io.h              |  1 +
>>   4 files changed, 41 insertions(+), 2 deletions(-)
>>
>> diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_pmf.c
>> b/drivers/gpu/drm/amd/amdgpu/amdgpu_pmf.c
>> index 232d11833ddc..5c567bff0548 100644
>> --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_pmf.c
>> +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_pmf.c
>> @@ -68,3 +68,24 @@ int amd_pmf_get_gfx_data(struct amd_gpu_pmf_data
>> *pmf)
>>        return 0;
>>   }
>>   EXPORT_SYMBOL_GPL(amd_pmf_get_gfx_data);
>> +
>> +int amd_pmf_set_gfx_data(struct amd_gpu_pmf_data *pmf) {
>> +     struct drm_device *drm_dev = pci_get_drvdata(pmf->gpu_dev);
>> +     struct amdgpu_device *adev = drm_to_adev(drm_dev);
>> +     struct backlight_device *bd;
>> +
>> +     if (!(adev->flags & AMD_IS_APU)) {
>> +             DRM_ERROR("PMF-AMDGPU interface not supported\n");
>> +             return -ENODEV;
>> +     }
>> +
>> +     bd = backlight_device_get_by_type(BACKLIGHT_RAW);
>> +     if (!bd)
>> +             return -ENODEV;
>> +
>> +     backlight_device_set_brightness(bd, pmf->brightness);
>> +
>> +     return 0;
>> +}
>> +EXPORT_SYMBOL_GPL(amd_pmf_set_gfx_data);
>> diff --git a/drivers/platform/x86/amd/pmf/pmf.h
>> b/drivers/platform/x86/amd/pmf/pmf.h
>> index 9032df4ba48a..ce89cc0daa5a 100644
>> --- a/drivers/platform/x86/amd/pmf/pmf.h
>> +++ b/drivers/platform/x86/amd/pmf/pmf.h
>> @@ -73,6 +73,7 @@
>>   #define PMF_POLICY_STT_SKINTEMP_APU                          7
>>   #define PMF_POLICY_STT_SKINTEMP_HS2                          8
>>   #define PMF_POLICY_SYSTEM_STATE                                      9
>> +#define PMF_POLICY_DISPLAY_BRIGHTNESS                                12
>>   #define PMF_POLICY_P3T                                               38
>>
>>   /* TA macros */
>> @@ -480,6 +481,7 @@ enum ta_pmf_error_type {  };
>>
>>   struct pmf_action_table {
>> +     unsigned long display_brightness;
>>        enum system_state system_state;
>>        unsigned long spl; /* in mW */
>>        unsigned long sppt; /* in mW */
>> diff --git a/drivers/platform/x86/amd/pmf/tee-if.c
>> b/drivers/platform/x86/amd/pmf/tee-if.c
>> index 1608996654e8..eefffff83a4c 100644
>> --- a/drivers/platform/x86/amd/pmf/tee-if.c
>> +++ b/drivers/platform/x86/amd/pmf/tee-if.c
>> @@ -79,10 +79,10 @@ static int amd_pmf_update_uevents(struct
>> amd_pmf_dev *dev, u16 event)
>>        return 0;
>>   }
>>
>> -static void amd_pmf_apply_policies(struct amd_pmf_dev *dev, struct
>> ta_pmf_enact_result *out)
>> +static int amd_pmf_apply_policies(struct amd_pmf_dev *dev, struct
>> +ta_pmf_enact_result *out)
>>   {
>>        u32 val, event = 0;
>> -     int idx;
>> +     int idx, ret;
>>
>>        for (idx = 0; idx < out->actions_count; idx++) {
>>                val = out->actions_list[idx].value;
>> @@ -160,8 +160,23 @@ static void amd_pmf_apply_policies(struct
>> amd_pmf_dev *dev, struct ta_pmf_enact_
>>                                dev->prev_data->system_state = 0;
>>                        }
>>                        break;
>> +
>> +             case PMF_POLICY_DISPLAY_BRIGHTNESS:
>> +                     ret = amd_pmf_get_gfx_data(&dev->gfx_data);
>> +                     if (ret)
>> +                             return ret;
>> +
>> +                     dev->prev_data->display_brightness = dev-
>>> gfx_data.brightness;
> 
> Are we using standardized units for the brightness?  On the GPU side, we align with the standard blacklight interface, but internally, the driver has to convert units depending on the type of backlight controller used on the platform.  Presumably PMF does something similar?
> 
> Alex
> 
>> +                     if (dev->prev_data->display_brightness != val) {
>> +                             dev->gfx_data.brightness = val;
>> +                             amd_pmf_set_gfx_data(&dev->gfx_data);
>> +                             dev_dbg(dev->dev, "update
>> DISPLAY_BRIGHTNESS : %d\n", val);
>> +                     }
>> +                     break;
>>                }
>>        }
>> +
>> +     return 0;
>>   }
>>
>>   static int amd_pmf_invoke_cmd_enact(struct amd_pmf_dev *dev) diff --git
>> a/include/linux/amd-pmf-io.h b/include/linux/amd-pmf-io.h index
>> a2d4af231362..ecae387ddaa6 100644
>> --- a/include/linux/amd-pmf-io.h
>> +++ b/include/linux/amd-pmf-io.h
>> @@ -25,4 +25,5 @@ struct amd_gpu_pmf_data {  };
>>
>>   int amd_pmf_get_gfx_data(struct amd_gpu_pmf_data *pmf);
>> +int amd_pmf_set_gfx_data(struct amd_gpu_pmf_data *pmf);
>>   #endif
>> --
>> 2.25.1
> 


^ permalink raw reply	[flat|nested] 54+ messages in thread

* Re: [PATCH 08/15] platform/x86/amd/pmf: Add support to update system state
  2023-09-22 17:50 ` [PATCH 08/15] platform/x86/amd/pmf: Add support to update system state Shyam Sundar S K
@ 2023-09-25 21:42   ` kernel test robot
  2023-09-27 12:22   ` Ilpo Järvinen
  1 sibling, 0 replies; 54+ messages in thread
From: kernel test robot @ 2023-09-25 21:42 UTC (permalink / raw)
  To: Shyam Sundar S K, hdegoede, markgross, basavaraj.natikar, jikos,
	benjamin.tissoires, alexander.deucher, christian.koenig,
	Xinhui.Pan, airlied, daniel
  Cc: Shyam Sundar S K, linux-input, dri-devel, platform-driver-x86,
	amd-gfx, Patil.Reddy, oe-kbuild-all, mario.limonciello

Hi Shyam,

kernel test robot noticed the following build warnings:

[auto build test WARNING on hid/for-next]
[also build test WARNING on linus/master v6.6-rc3 next-20230925]
[cannot apply to drm-misc/drm-misc-next]
[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/Shyam-Sundar-S-K/platform-x86-amd-pmf-Add-PMF-TEE-interface/20230923-015418
base:   https://git.kernel.org/pub/scm/linux/kernel/git/hid/hid.git for-next
patch link:    https://lore.kernel.org/r/20230922175056.244940-9-Shyam-sundar.S-k%40amd.com
patch subject: [PATCH 08/15] platform/x86/amd/pmf: Add support to update system state
reproduce: (https://download.01.org/0day-ci/archive/20230926/202309260515.5XbR6N0g-lkp@intel.com/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 <lkp@intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202309260515.5XbR6N0g-lkp@intel.com/

All warnings (new ones prefixed by >>):

>> Documentation/admin-guide/pmf.rst:16: WARNING: Unexpected indentation.
>> Documentation/admin-guide/pmf.rst: WARNING: document isn't included in any toctree

vim +16 Documentation/admin-guide/pmf.rst

    13	
    14	Please add the following line(s) to
    15	``/etc/udev/rules.d/99-local.rules``::
  > 16	        DRIVERS=="amd-pmf", ACTION=="change", ENV{EVENT_ID}=="1", RUN+="/usr/bin/systemctl suspend"
    17	        DRIVERS=="amd-pmf", ACTION=="change", ENV{EVENT_ID}=="2", RUN+="/usr/bin/systemctl hibernate"
    18	        DRIVERS=="amd-pmf", ACTION=="change", ENV{EVENT_ID}=="3", RUN+="/bin/loginctl lock-sessions"
    19	

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

^ permalink raw reply	[flat|nested] 54+ messages in thread

* Re: [PATCH 13/15] platform/x86/amd/pmf: Add PMF-AMDGPU set interface
  2023-09-22 17:50 ` [PATCH 13/15] platform/x86/amd/pmf: Add PMF-AMDGPU set interface Shyam Sundar S K
  2023-09-25 16:27   ` Deucher, Alexander
@ 2023-09-26 10:35   ` Hans de Goede
  2023-09-26 11:24     ` Shyam Sundar S K
  2023-09-27 13:36   ` Ilpo Järvinen
  2 siblings, 1 reply; 54+ messages in thread
From: Hans de Goede @ 2023-09-26 10:35 UTC (permalink / raw)
  To: Shyam Sundar S K, markgross, basavaraj.natikar, jikos,
	benjamin.tissoires, alexander.deucher, christian.koenig,
	Xinhui.Pan, airlied, daniel
  Cc: amd-gfx, platform-driver-x86, dri-devel, Patil.Reddy,
	linux-input, mario.limonciello

Hi,

On 9/22/23 19:50, Shyam Sundar S K wrote:
> For the Smart PC Solution to fully work, it has to enact to the actions
> coming from TA. Add the initial code path for set interface to AMDGPU.
> 
> Co-developed-by: Mario Limonciello <mario.limonciello@amd.com>
> Signed-off-by: Mario Limonciello <mario.limonciello@amd.com>
> Signed-off-by: Shyam Sundar S K <Shyam-sundar.S-k@amd.com>
> ---
>  drivers/gpu/drm/amd/amdgpu/amdgpu_pmf.c | 21 +++++++++++++++++++++
>  drivers/platform/x86/amd/pmf/pmf.h      |  2 ++
>  drivers/platform/x86/amd/pmf/tee-if.c   | 19 +++++++++++++++++--
>  include/linux/amd-pmf-io.h              |  1 +
>  4 files changed, 41 insertions(+), 2 deletions(-)
> 
> diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_pmf.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_pmf.c
> index 232d11833ddc..5c567bff0548 100644
> --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_pmf.c
> +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_pmf.c
> @@ -68,3 +68,24 @@ int amd_pmf_get_gfx_data(struct amd_gpu_pmf_data *pmf)
>  	return 0;
>  }
>  EXPORT_SYMBOL_GPL(amd_pmf_get_gfx_data);
> +
> +int amd_pmf_set_gfx_data(struct amd_gpu_pmf_data *pmf)
> +{
> +	struct drm_device *drm_dev = pci_get_drvdata(pmf->gpu_dev);
> +	struct amdgpu_device *adev = drm_to_adev(drm_dev);
> +	struct backlight_device *bd;
> +
> +	if (!(adev->flags & AMD_IS_APU)) {
> +		DRM_ERROR("PMF-AMDGPU interface not supported\n");
> +		return -ENODEV;
> +	}
> +
> +	bd = backlight_device_get_by_type(BACKLIGHT_RAW);
> +	if (!bd)
> +		return -ENODEV;

This assumes that the backlight is always controller by the amdgpu's
native backlight driver, but it might e.g. also be handled by
eacpi-video or by nvidia_wmi_ec_backlight (when using an AMD APU +
nvidia dgpu).

For now what should be done here is to call acpi_video_get_backlight_type()
and then translate the return value from this into a backlight-type:

        acpi_backlight_video		-> BACKLIGHT_FIRMWARE
        acpi_backlight_vendor,		-> BACKLIGHT_PLATFORM
        acpi_backlight_native,		-> BACKLIGHT_RAW
        acpi_backlight_nvidia_wmi_ec,	-> BACKLIGHT_FIRMWARE
        acpi_backlight_apple_gmux,	-> BACKLIGHT_PLATFORM

Also I'm worried about probe order here, this code currently assumes
that the GPU or other backlight driver has loaded before this runs,
which is not necessarily the case.

I think that if the backlight_device_get_by_type() fails this
should be retried say every 10 seconds from some delayed workqueue
for at least a couple of minutes after boot.

Regards,

Hans




> +
> +	backlight_device_set_brightness(bd, pmf->brightness);
> +
> +	return 0;
> +}
> +EXPORT_SYMBOL_GPL(amd_pmf_set_gfx_data);
> diff --git a/drivers/platform/x86/amd/pmf/pmf.h b/drivers/platform/x86/amd/pmf/pmf.h
> index 9032df4ba48a..ce89cc0daa5a 100644
> --- a/drivers/platform/x86/amd/pmf/pmf.h
> +++ b/drivers/platform/x86/amd/pmf/pmf.h
> @@ -73,6 +73,7 @@
>  #define PMF_POLICY_STT_SKINTEMP_APU				7
>  #define PMF_POLICY_STT_SKINTEMP_HS2				8
>  #define PMF_POLICY_SYSTEM_STATE					9
> +#define PMF_POLICY_DISPLAY_BRIGHTNESS				12
>  #define PMF_POLICY_P3T						38
>  
>  /* TA macros */
> @@ -480,6 +481,7 @@ enum ta_pmf_error_type {
>  };
>  
>  struct pmf_action_table {
> +	unsigned long display_brightness;
>  	enum system_state system_state;
>  	unsigned long spl; /* in mW */
>  	unsigned long sppt; /* in mW */
> diff --git a/drivers/platform/x86/amd/pmf/tee-if.c b/drivers/platform/x86/amd/pmf/tee-if.c
> index 1608996654e8..eefffff83a4c 100644
> --- a/drivers/platform/x86/amd/pmf/tee-if.c
> +++ b/drivers/platform/x86/amd/pmf/tee-if.c
> @@ -79,10 +79,10 @@ static int amd_pmf_update_uevents(struct amd_pmf_dev *dev, u16 event)
>  	return 0;
>  }
>  
> -static void amd_pmf_apply_policies(struct amd_pmf_dev *dev, struct ta_pmf_enact_result *out)
> +static int amd_pmf_apply_policies(struct amd_pmf_dev *dev, struct ta_pmf_enact_result *out)
>  {
>  	u32 val, event = 0;
> -	int idx;
> +	int idx, ret;
>  
>  	for (idx = 0; idx < out->actions_count; idx++) {
>  		val = out->actions_list[idx].value;
> @@ -160,8 +160,23 @@ static void amd_pmf_apply_policies(struct amd_pmf_dev *dev, struct ta_pmf_enact_
>  				dev->prev_data->system_state = 0;
>  			}
>  			break;
> +
> +		case PMF_POLICY_DISPLAY_BRIGHTNESS:
> +			ret = amd_pmf_get_gfx_data(&dev->gfx_data);
> +			if (ret)
> +				return ret;
> +
> +			dev->prev_data->display_brightness = dev->gfx_data.brightness;
> +			if (dev->prev_data->display_brightness != val) {
> +				dev->gfx_data.brightness = val;
> +				amd_pmf_set_gfx_data(&dev->gfx_data);
> +				dev_dbg(dev->dev, "update DISPLAY_BRIGHTNESS : %d\n", val);
> +			}
> +			break;
>  		}
>  	}
> +
> +	return 0;
>  }
>  
>  static int amd_pmf_invoke_cmd_enact(struct amd_pmf_dev *dev)
> diff --git a/include/linux/amd-pmf-io.h b/include/linux/amd-pmf-io.h
> index a2d4af231362..ecae387ddaa6 100644
> --- a/include/linux/amd-pmf-io.h
> +++ b/include/linux/amd-pmf-io.h
> @@ -25,4 +25,5 @@ struct amd_gpu_pmf_data {
>  };
>  
>  int amd_pmf_get_gfx_data(struct amd_gpu_pmf_data *pmf);
> +int amd_pmf_set_gfx_data(struct amd_gpu_pmf_data *pmf);
>  #endif


^ permalink raw reply	[flat|nested] 54+ messages in thread

* Re: [PATCH 13/15] platform/x86/amd/pmf: Add PMF-AMDGPU set interface
  2023-09-25 16:27   ` Deucher, Alexander
  2023-09-25 16:30     ` Mario Limonciello
@ 2023-09-26 11:15     ` Shyam Sundar S K
  1 sibling, 0 replies; 54+ messages in thread
From: Shyam Sundar S K @ 2023-09-26 11:15 UTC (permalink / raw)
  To: Deucher, Alexander, hdegoede, markgross, Natikar, Basavaraj,
	jikos, benjamin.tissoires, Koenig, Christian, Pan, Xinhui,
	airlied, daniel
  Cc: amd-gfx, dri-devel, platform-driver-x86, Limonciello, Mario,
	Patil Rajesh, linux-input



On 9/25/2023 9:57 PM, Deucher, Alexander wrote:
> [Public]
> 
>> -----Original Message-----
>> From: amd-gfx <amd-gfx-bounces@lists.freedesktop.org> On Behalf Of
>> Shyam Sundar S K
>> Sent: Friday, September 22, 2023 1:51 PM
>> To: hdegoede@redhat.com; markgross@kernel.org; Natikar, Basavaraj
>> <Basavaraj.Natikar@amd.com>; jikos@kernel.org;
>> benjamin.tissoires@redhat.com; Deucher, Alexander
>> <Alexander.Deucher@amd.com>; Koenig, Christian
>> <Christian.Koenig@amd.com>; Pan, Xinhui <Xinhui.Pan@amd.com>;
>> airlied@gmail.com; daniel@ffwll.ch
>> Cc: S-k, Shyam-sundar <Shyam-sundar.S-k@amd.com>; amd-
>> gfx@lists.freedesktop.org; platform-driver-x86@vger.kernel.org; dri-
>> devel@lists.freedesktop.org; Patil Rajesh <Patil.Reddy@amd.com>; linux-
>> input@vger.kernel.org; Limonciello, Mario <Mario.Limonciello@amd.com>
>> Subject: [PATCH 13/15] platform/x86/amd/pmf: Add PMF-AMDGPU set
>> interface
>>
>> For the Smart PC Solution to fully work, it has to enact to the actions coming
>> from TA. Add the initial code path for set interface to AMDGPU.
> 
> This seems to be limited to backlight at this point.  What does setting or not setting the backlight level mean for the system when this framework is in place?  What if a user manually changes the backlight level?  Additional comments below.

The unit here is nits that varies from 0 to 255. User can manually
update the backlight but if there is an action from the TA to update
the backlight, PMF driver would send a request to GPU driver to update
the backlight to the updated value (in nits)

At this point, yes. PMF is using to PMF-GPU interface to set
backlight, but there are additional things to be added in future. This
patch builds the initial plumbing for that.

> 
>>
>> Co-developed-by: Mario Limonciello <mario.limonciello@amd.com>
>> Signed-off-by: Mario Limonciello <mario.limonciello@amd.com>
>> Signed-off-by: Shyam Sundar S K <Shyam-sundar.S-k@amd.com>
>> ---
>>  drivers/gpu/drm/amd/amdgpu/amdgpu_pmf.c | 21
>> +++++++++++++++++++++
>>  drivers/platform/x86/amd/pmf/pmf.h      |  2 ++
>>  drivers/platform/x86/amd/pmf/tee-if.c   | 19 +++++++++++++++++--
>>  include/linux/amd-pmf-io.h              |  1 +
>>  4 files changed, 41 insertions(+), 2 deletions(-)
>>
>> diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_pmf.c
>> b/drivers/gpu/drm/amd/amdgpu/amdgpu_pmf.c
>> index 232d11833ddc..5c567bff0548 100644
>> --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_pmf.c
>> +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_pmf.c
>> @@ -68,3 +68,24 @@ int amd_pmf_get_gfx_data(struct amd_gpu_pmf_data
>> *pmf)
>>       return 0;
>>  }
>>  EXPORT_SYMBOL_GPL(amd_pmf_get_gfx_data);
>> +
>> +int amd_pmf_set_gfx_data(struct amd_gpu_pmf_data *pmf) {
>> +     struct drm_device *drm_dev = pci_get_drvdata(pmf->gpu_dev);
>> +     struct amdgpu_device *adev = drm_to_adev(drm_dev);
>> +     struct backlight_device *bd;
>> +
>> +     if (!(adev->flags & AMD_IS_APU)) {
>> +             DRM_ERROR("PMF-AMDGPU interface not supported\n");
>> +             return -ENODEV;
>> +     }
>> +
>> +     bd = backlight_device_get_by_type(BACKLIGHT_RAW);
>> +     if (!bd)
>> +             return -ENODEV;
>> +
>> +     backlight_device_set_brightness(bd, pmf->brightness);
>> +
>> +     return 0;
>> +}
>> +EXPORT_SYMBOL_GPL(amd_pmf_set_gfx_data);
>> diff --git a/drivers/platform/x86/amd/pmf/pmf.h
>> b/drivers/platform/x86/amd/pmf/pmf.h
>> index 9032df4ba48a..ce89cc0daa5a 100644
>> --- a/drivers/platform/x86/amd/pmf/pmf.h
>> +++ b/drivers/platform/x86/amd/pmf/pmf.h
>> @@ -73,6 +73,7 @@
>>  #define PMF_POLICY_STT_SKINTEMP_APU                          7
>>  #define PMF_POLICY_STT_SKINTEMP_HS2                          8
>>  #define PMF_POLICY_SYSTEM_STATE                                      9
>> +#define PMF_POLICY_DISPLAY_BRIGHTNESS                                12
>>  #define PMF_POLICY_P3T                                               38
>>
>>  /* TA macros */
>> @@ -480,6 +481,7 @@ enum ta_pmf_error_type {  };
>>
>>  struct pmf_action_table {
>> +     unsigned long display_brightness;
>>       enum system_state system_state;
>>       unsigned long spl; /* in mW */
>>       unsigned long sppt; /* in mW */
>> diff --git a/drivers/platform/x86/amd/pmf/tee-if.c
>> b/drivers/platform/x86/amd/pmf/tee-if.c
>> index 1608996654e8..eefffff83a4c 100644
>> --- a/drivers/platform/x86/amd/pmf/tee-if.c
>> +++ b/drivers/platform/x86/amd/pmf/tee-if.c
>> @@ -79,10 +79,10 @@ static int amd_pmf_update_uevents(struct
>> amd_pmf_dev *dev, u16 event)
>>       return 0;
>>  }
>>
>> -static void amd_pmf_apply_policies(struct amd_pmf_dev *dev, struct
>> ta_pmf_enact_result *out)
>> +static int amd_pmf_apply_policies(struct amd_pmf_dev *dev, struct
>> +ta_pmf_enact_result *out)
>>  {
>>       u32 val, event = 0;
>> -     int idx;
>> +     int idx, ret;
>>
>>       for (idx = 0; idx < out->actions_count; idx++) {
>>               val = out->actions_list[idx].value;
>> @@ -160,8 +160,23 @@ static void amd_pmf_apply_policies(struct
>> amd_pmf_dev *dev, struct ta_pmf_enact_
>>                               dev->prev_data->system_state = 0;
>>                       }
>>                       break;
>> +
>> +             case PMF_POLICY_DISPLAY_BRIGHTNESS:
>> +                     ret = amd_pmf_get_gfx_data(&dev->gfx_data);
>> +                     if (ret)
>> +                             return ret;
>> +
>> +                     dev->prev_data->display_brightness = dev-
>>> gfx_data.brightness;
> 
> Are we using standardized units for the brightness?  On the GPU side, we align with the standard blacklight interface, but internally, the driver has to convert units depending on the type of backlight controller used on the platform.  Presumably PMF does something similar?

Yes its the standard nits. There is no conversion needed.

> 
> Alex
> 
>> +                     if (dev->prev_data->display_brightness != val) {
>> +                             dev->gfx_data.brightness = val;
>> +                             amd_pmf_set_gfx_data(&dev->gfx_data);
>> +                             dev_dbg(dev->dev, "update
>> DISPLAY_BRIGHTNESS : %d\n", val);
>> +                     }
>> +                     break;
>>               }
>>       }
>> +
>> +     return 0;
>>  }
>>
>>  static int amd_pmf_invoke_cmd_enact(struct amd_pmf_dev *dev) diff --git
>> a/include/linux/amd-pmf-io.h b/include/linux/amd-pmf-io.h index
>> a2d4af231362..ecae387ddaa6 100644
>> --- a/include/linux/amd-pmf-io.h
>> +++ b/include/linux/amd-pmf-io.h
>> @@ -25,4 +25,5 @@ struct amd_gpu_pmf_data {  };
>>
>>  int amd_pmf_get_gfx_data(struct amd_gpu_pmf_data *pmf);
>> +int amd_pmf_set_gfx_data(struct amd_gpu_pmf_data *pmf);
>>  #endif
>> --
>> 2.25.1
> 

^ permalink raw reply	[flat|nested] 54+ messages in thread

* Re: [PATCH 13/15] platform/x86/amd/pmf: Add PMF-AMDGPU set interface
  2023-09-25 16:30     ` Mario Limonciello
@ 2023-09-26 11:17       ` Shyam Sundar S K
  0 siblings, 0 replies; 54+ messages in thread
From: Shyam Sundar S K @ 2023-09-26 11:17 UTC (permalink / raw)
  To: Mario Limonciello, Deucher, Alexander, hdegoede, markgross,
	Natikar, Basavaraj, jikos, benjamin.tissoires, Koenig, Christian,
	Pan, Xinhui, airlied, daniel
  Cc: Patil Rajesh, linux-input, dri-devel, amd-gfx, platform-driver-x86



On 9/25/2023 10:00 PM, Mario Limonciello wrote:
> On 9/25/2023 11:27, Deucher, Alexander wrote:
>> [Public]
>>
>>> -----Original Message-----
>>> From: amd-gfx <amd-gfx-bounces@lists.freedesktop.org> On Behalf Of
>>> Shyam Sundar S K
>>> Sent: Friday, September 22, 2023 1:51 PM
>>> To: hdegoede@redhat.com; markgross@kernel.org; Natikar, Basavaraj
>>> <Basavaraj.Natikar@amd.com>; jikos@kernel.org;
>>> benjamin.tissoires@redhat.com; Deucher, Alexander
>>> <Alexander.Deucher@amd.com>; Koenig, Christian
>>> <Christian.Koenig@amd.com>; Pan, Xinhui <Xinhui.Pan@amd.com>;
>>> airlied@gmail.com; daniel@ffwll.ch
>>> Cc: S-k, Shyam-sundar <Shyam-sundar.S-k@amd.com>; amd-
>>> gfx@lists.freedesktop.org; platform-driver-x86@vger.kernel.org; dri-
>>> devel@lists.freedesktop.org; Patil Rajesh <Patil.Reddy@amd.com>;
>>> linux-
>>> input@vger.kernel.org; Limonciello, Mario <Mario.Limonciello@amd.com>
>>> Subject: [PATCH 13/15] platform/x86/amd/pmf: Add PMF-AMDGPU set
>>> interface
>>>
>>> For the Smart PC Solution to fully work, it has to enact to the
>>> actions coming
>>> from TA. Add the initial code path for set interface to AMDGPU.
>>
>> This seems to be limited to backlight at this point.  What does
>> setting or not setting the backlight level mean for the system when
>> this framework is in place?  What if a user manually changes the
>> backlight level?  Additional comments below.
>>
> 
> It's also for the display count.

display count is on the PMF-GPU GET interface. On the SET interface
its only backlight for today.

Thanks,
Shyam

> 
>>>
>>> Co-developed-by: Mario Limonciello <mario.limonciello@amd.com>
>>> Signed-off-by: Mario Limonciello <mario.limonciello@amd.com>
>>> Signed-off-by: Shyam Sundar S K <Shyam-sundar.S-k@amd.com>
>>> ---
>>>   drivers/gpu/drm/amd/amdgpu/amdgpu_pmf.c | 21
>>> +++++++++++++++++++++
>>>   drivers/platform/x86/amd/pmf/pmf.h      |  2 ++
>>>   drivers/platform/x86/amd/pmf/tee-if.c   | 19 +++++++++++++++++--
>>>   include/linux/amd-pmf-io.h              |  1 +
>>>   4 files changed, 41 insertions(+), 2 deletions(-)
>>>
>>> diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_pmf.c
>>> b/drivers/gpu/drm/amd/amdgpu/amdgpu_pmf.c
>>> index 232d11833ddc..5c567bff0548 100644
>>> --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_pmf.c
>>> +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_pmf.c
>>> @@ -68,3 +68,24 @@ int amd_pmf_get_gfx_data(struct amd_gpu_pmf_data
>>> *pmf)
>>>        return 0;
>>>   }
>>>   EXPORT_SYMBOL_GPL(amd_pmf_get_gfx_data);
>>> +
>>> +int amd_pmf_set_gfx_data(struct amd_gpu_pmf_data *pmf) {
>>> +     struct drm_device *drm_dev = pci_get_drvdata(pmf->gpu_dev);
>>> +     struct amdgpu_device *adev = drm_to_adev(drm_dev);
>>> +     struct backlight_device *bd;
>>> +
>>> +     if (!(adev->flags & AMD_IS_APU)) {
>>> +             DRM_ERROR("PMF-AMDGPU interface not supported\n");
>>> +             return -ENODEV;
>>> +     }
>>> +
>>> +     bd = backlight_device_get_by_type(BACKLIGHT_RAW);
>>> +     if (!bd)
>>> +             return -ENODEV;
>>> +
>>> +     backlight_device_set_brightness(bd, pmf->brightness);
>>> +
>>> +     return 0;
>>> +}
>>> +EXPORT_SYMBOL_GPL(amd_pmf_set_gfx_data);
>>> diff --git a/drivers/platform/x86/amd/pmf/pmf.h
>>> b/drivers/platform/x86/amd/pmf/pmf.h
>>> index 9032df4ba48a..ce89cc0daa5a 100644
>>> --- a/drivers/platform/x86/amd/pmf/pmf.h
>>> +++ b/drivers/platform/x86/amd/pmf/pmf.h
>>> @@ -73,6 +73,7 @@
>>>   #define PMF_POLICY_STT_SKINTEMP_APU                          7
>>>   #define PMF_POLICY_STT_SKINTEMP_HS2                          8
>>>   #define
>>> PMF_POLICY_SYSTEM_STATE                                      9
>>> +#define
>>> PMF_POLICY_DISPLAY_BRIGHTNESS                                12
>>>   #define
>>> PMF_POLICY_P3T                                               38
>>>
>>>   /* TA macros */
>>> @@ -480,6 +481,7 @@ enum ta_pmf_error_type {  };
>>>
>>>   struct pmf_action_table {
>>> +     unsigned long display_brightness;
>>>        enum system_state system_state;
>>>        unsigned long spl; /* in mW */
>>>        unsigned long sppt; /* in mW */
>>> diff --git a/drivers/platform/x86/amd/pmf/tee-if.c
>>> b/drivers/platform/x86/amd/pmf/tee-if.c
>>> index 1608996654e8..eefffff83a4c 100644
>>> --- a/drivers/platform/x86/amd/pmf/tee-if.c
>>> +++ b/drivers/platform/x86/amd/pmf/tee-if.c
>>> @@ -79,10 +79,10 @@ static int amd_pmf_update_uevents(struct
>>> amd_pmf_dev *dev, u16 event)
>>>        return 0;
>>>   }
>>>
>>> -static void amd_pmf_apply_policies(struct amd_pmf_dev *dev, struct
>>> ta_pmf_enact_result *out)
>>> +static int amd_pmf_apply_policies(struct amd_pmf_dev *dev, struct
>>> +ta_pmf_enact_result *out)
>>>   {
>>>        u32 val, event = 0;
>>> -     int idx;
>>> +     int idx, ret;
>>>
>>>        for (idx = 0; idx < out->actions_count; idx++) {
>>>                val = out->actions_list[idx].value;
>>> @@ -160,8 +160,23 @@ static void amd_pmf_apply_policies(struct
>>> amd_pmf_dev *dev, struct ta_pmf_enact_
>>>                                dev->prev_data->system_state = 0;
>>>                        }
>>>                        break;
>>> +
>>> +             case PMF_POLICY_DISPLAY_BRIGHTNESS:
>>> +                     ret = amd_pmf_get_gfx_data(&dev->gfx_data);
>>> +                     if (ret)
>>> +                             return ret;
>>> +
>>> +                     dev->prev_data->display_brightness = dev-
>>>> gfx_data.brightness;
>>
>> Are we using standardized units for the brightness?  On the GPU
>> side, we align with the standard blacklight interface, but
>> internally, the driver has to convert units depending on the type of
>> backlight controller used on the platform.  Presumably PMF does
>> something similar?
>>
>> Alex
>>
>>> +                     if (dev->prev_data->display_brightness != val) {
>>> +                             dev->gfx_data.brightness = val;
>>> +                             amd_pmf_set_gfx_data(&dev->gfx_data);
>>> +                             dev_dbg(dev->dev, "update
>>> DISPLAY_BRIGHTNESS : %d\n", val);
>>> +                     }
>>> +                     break;
>>>                }
>>>        }
>>> +
>>> +     return 0;
>>>   }
>>>
>>>   static int amd_pmf_invoke_cmd_enact(struct amd_pmf_dev *dev) diff
>>> --git
>>> a/include/linux/amd-pmf-io.h b/include/linux/amd-pmf-io.h index
>>> a2d4af231362..ecae387ddaa6 100644
>>> --- a/include/linux/amd-pmf-io.h
>>> +++ b/include/linux/amd-pmf-io.h
>>> @@ -25,4 +25,5 @@ struct amd_gpu_pmf_data {  };
>>>
>>>   int amd_pmf_get_gfx_data(struct amd_gpu_pmf_data *pmf);
>>> +int amd_pmf_set_gfx_data(struct amd_gpu_pmf_data *pmf);
>>>   #endif
>>> -- 
>>> 2.25.1
>>
> 

^ permalink raw reply	[flat|nested] 54+ messages in thread

* Re: [PATCH 13/15] platform/x86/amd/pmf: Add PMF-AMDGPU set interface
  2023-09-26 10:35   ` Hans de Goede
@ 2023-09-26 11:24     ` Shyam Sundar S K
  2023-09-26 12:56       ` Hans de Goede
  0 siblings, 1 reply; 54+ messages in thread
From: Shyam Sundar S K @ 2023-09-26 11:24 UTC (permalink / raw)
  To: Hans de Goede, markgross, basavaraj.natikar, jikos,
	benjamin.tissoires, alexander.deucher, christian.koenig,
	Xinhui.Pan, airlied, daniel
  Cc: amd-gfx, platform-driver-x86, dri-devel, Patil.Reddy,
	linux-input, mario.limonciello

Hi Hans,

On 9/26/2023 4:05 PM, Hans de Goede wrote:
> Hi,
> 
> On 9/22/23 19:50, Shyam Sundar S K wrote:
>> For the Smart PC Solution to fully work, it has to enact to the actions
>> coming from TA. Add the initial code path for set interface to AMDGPU.
>>
>> Co-developed-by: Mario Limonciello <mario.limonciello@amd.com>
>> Signed-off-by: Mario Limonciello <mario.limonciello@amd.com>
>> Signed-off-by: Shyam Sundar S K <Shyam-sundar.S-k@amd.com>
>> ---
>>  drivers/gpu/drm/amd/amdgpu/amdgpu_pmf.c | 21 +++++++++++++++++++++
>>  drivers/platform/x86/amd/pmf/pmf.h      |  2 ++
>>  drivers/platform/x86/amd/pmf/tee-if.c   | 19 +++++++++++++++++--
>>  include/linux/amd-pmf-io.h              |  1 +
>>  4 files changed, 41 insertions(+), 2 deletions(-)
>>
>> diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_pmf.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_pmf.c
>> index 232d11833ddc..5c567bff0548 100644
>> --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_pmf.c
>> +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_pmf.c
>> @@ -68,3 +68,24 @@ int amd_pmf_get_gfx_data(struct amd_gpu_pmf_data *pmf)
>>  	return 0;
>>  }
>>  EXPORT_SYMBOL_GPL(amd_pmf_get_gfx_data);
>> +
>> +int amd_pmf_set_gfx_data(struct amd_gpu_pmf_data *pmf)
>> +{
>> +	struct drm_device *drm_dev = pci_get_drvdata(pmf->gpu_dev);
>> +	struct amdgpu_device *adev = drm_to_adev(drm_dev);
>> +	struct backlight_device *bd;
>> +
>> +	if (!(adev->flags & AMD_IS_APU)) {
>> +		DRM_ERROR("PMF-AMDGPU interface not supported\n");
>> +		return -ENODEV;
>> +	}
>> +
>> +	bd = backlight_device_get_by_type(BACKLIGHT_RAW);
>> +	if (!bd)
>> +		return -ENODEV;
> 
> This assumes that the backlight is always controller by the amdgpu's
> native backlight driver, but it might e.g. also be handled by
> eacpi-video or by nvidia_wmi_ec_backlight (when using an AMD APU +
> nvidia dgpu).

PMF is meant for AMD APUs(atleast for now) and the _HID will only be
made visible if its AMD laptop. So using amdgpu's native BACKLIGHT_RAW
should be safe, right?

> 
> For now what should be done here is to call acpi_video_get_backlight_type()
> and then translate the return value from this into a backlight-type:
> 
>         acpi_backlight_video		-> BACKLIGHT_FIRMWARE
>         acpi_backlight_vendor,		-> BACKLIGHT_PLATFORM
>         acpi_backlight_native,		-> BACKLIGHT_RAW
>         acpi_backlight_nvidia_wmi_ec,	-> BACKLIGHT_FIRMWARE
>         acpi_backlight_apple_gmux,	-> BACKLIGHT_PLATFORM
> 

I can add this change in the v2, do you insist on this?

Thanks,
Shyam

> Also I'm worried about probe order here, this code currently assumes
> that the GPU or other backlight driver has loaded before this runs,
> which is not necessarily the case.
> 
> I think that if the backlight_device_get_by_type() fails this
> should be retried say every 10 seconds from some delayed workqueue
> for at least a couple of minutes after boot.
> 
> Regards,
> 
> Hans
> 
> 
> 
> 
>> +
>> +	backlight_device_set_brightness(bd, pmf->brightness);
>> +
>> +	return 0;
>> +}
>> +EXPORT_SYMBOL_GPL(amd_pmf_set_gfx_data);
>> diff --git a/drivers/platform/x86/amd/pmf/pmf.h b/drivers/platform/x86/amd/pmf/pmf.h
>> index 9032df4ba48a..ce89cc0daa5a 100644
>> --- a/drivers/platform/x86/amd/pmf/pmf.h
>> +++ b/drivers/platform/x86/amd/pmf/pmf.h
>> @@ -73,6 +73,7 @@
>>  #define PMF_POLICY_STT_SKINTEMP_APU				7
>>  #define PMF_POLICY_STT_SKINTEMP_HS2				8
>>  #define PMF_POLICY_SYSTEM_STATE					9
>> +#define PMF_POLICY_DISPLAY_BRIGHTNESS				12
>>  #define PMF_POLICY_P3T						38
>>  
>>  /* TA macros */
>> @@ -480,6 +481,7 @@ enum ta_pmf_error_type {
>>  };
>>  
>>  struct pmf_action_table {
>> +	unsigned long display_brightness;
>>  	enum system_state system_state;
>>  	unsigned long spl; /* in mW */
>>  	unsigned long sppt; /* in mW */
>> diff --git a/drivers/platform/x86/amd/pmf/tee-if.c b/drivers/platform/x86/amd/pmf/tee-if.c
>> index 1608996654e8..eefffff83a4c 100644
>> --- a/drivers/platform/x86/amd/pmf/tee-if.c
>> +++ b/drivers/platform/x86/amd/pmf/tee-if.c
>> @@ -79,10 +79,10 @@ static int amd_pmf_update_uevents(struct amd_pmf_dev *dev, u16 event)
>>  	return 0;
>>  }
>>  
>> -static void amd_pmf_apply_policies(struct amd_pmf_dev *dev, struct ta_pmf_enact_result *out)
>> +static int amd_pmf_apply_policies(struct amd_pmf_dev *dev, struct ta_pmf_enact_result *out)
>>  {
>>  	u32 val, event = 0;
>> -	int idx;
>> +	int idx, ret;
>>  
>>  	for (idx = 0; idx < out->actions_count; idx++) {
>>  		val = out->actions_list[idx].value;
>> @@ -160,8 +160,23 @@ static void amd_pmf_apply_policies(struct amd_pmf_dev *dev, struct ta_pmf_enact_
>>  				dev->prev_data->system_state = 0;
>>  			}
>>  			break;
>> +
>> +		case PMF_POLICY_DISPLAY_BRIGHTNESS:
>> +			ret = amd_pmf_get_gfx_data(&dev->gfx_data);
>> +			if (ret)
>> +				return ret;
>> +
>> +			dev->prev_data->display_brightness = dev->gfx_data.brightness;
>> +			if (dev->prev_data->display_brightness != val) {
>> +				dev->gfx_data.brightness = val;
>> +				amd_pmf_set_gfx_data(&dev->gfx_data);
>> +				dev_dbg(dev->dev, "update DISPLAY_BRIGHTNESS : %d\n", val);
>> +			}
>> +			break;
>>  		}
>>  	}
>> +
>> +	return 0;
>>  }
>>  
>>  static int amd_pmf_invoke_cmd_enact(struct amd_pmf_dev *dev)
>> diff --git a/include/linux/amd-pmf-io.h b/include/linux/amd-pmf-io.h
>> index a2d4af231362..ecae387ddaa6 100644
>> --- a/include/linux/amd-pmf-io.h
>> +++ b/include/linux/amd-pmf-io.h
>> @@ -25,4 +25,5 @@ struct amd_gpu_pmf_data {
>>  };
>>  
>>  int amd_pmf_get_gfx_data(struct amd_gpu_pmf_data *pmf);
>> +int amd_pmf_set_gfx_data(struct amd_gpu_pmf_data *pmf);
>>  #endif
> 

^ permalink raw reply	[flat|nested] 54+ messages in thread

* Re: [PATCH 13/15] platform/x86/amd/pmf: Add PMF-AMDGPU set interface
  2023-09-26 11:24     ` Shyam Sundar S K
@ 2023-09-26 12:56       ` Hans de Goede
  2023-09-26 13:17         ` Christian König
  0 siblings, 1 reply; 54+ messages in thread
From: Hans de Goede @ 2023-09-26 12:56 UTC (permalink / raw)
  To: Shyam Sundar S K, markgross, basavaraj.natikar, jikos,
	benjamin.tissoires, alexander.deucher, christian.koenig,
	Xinhui.Pan, airlied, daniel
  Cc: amd-gfx, platform-driver-x86, dri-devel, Patil.Reddy,
	linux-input, mario.limonciello

Hi,

On 9/26/23 13:24, Shyam Sundar S K wrote:
> Hi Hans,
> 
> On 9/26/2023 4:05 PM, Hans de Goede wrote:
>> Hi,
>>
>> On 9/22/23 19:50, Shyam Sundar S K wrote:
>>> For the Smart PC Solution to fully work, it has to enact to the actions
>>> coming from TA. Add the initial code path for set interface to AMDGPU.
>>>
>>> Co-developed-by: Mario Limonciello <mario.limonciello@amd.com>
>>> Signed-off-by: Mario Limonciello <mario.limonciello@amd.com>
>>> Signed-off-by: Shyam Sundar S K <Shyam-sundar.S-k@amd.com>
>>> ---
>>>  drivers/gpu/drm/amd/amdgpu/amdgpu_pmf.c | 21 +++++++++++++++++++++
>>>  drivers/platform/x86/amd/pmf/pmf.h      |  2 ++
>>>  drivers/platform/x86/amd/pmf/tee-if.c   | 19 +++++++++++++++++--
>>>  include/linux/amd-pmf-io.h              |  1 +
>>>  4 files changed, 41 insertions(+), 2 deletions(-)
>>>
>>> diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_pmf.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_pmf.c
>>> index 232d11833ddc..5c567bff0548 100644
>>> --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_pmf.c
>>> +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_pmf.c
>>> @@ -68,3 +68,24 @@ int amd_pmf_get_gfx_data(struct amd_gpu_pmf_data *pmf)
>>>  	return 0;
>>>  }
>>>  EXPORT_SYMBOL_GPL(amd_pmf_get_gfx_data);
>>> +
>>> +int amd_pmf_set_gfx_data(struct amd_gpu_pmf_data *pmf)
>>> +{
>>> +	struct drm_device *drm_dev = pci_get_drvdata(pmf->gpu_dev);
>>> +	struct amdgpu_device *adev = drm_to_adev(drm_dev);
>>> +	struct backlight_device *bd;
>>> +
>>> +	if (!(adev->flags & AMD_IS_APU)) {
>>> +		DRM_ERROR("PMF-AMDGPU interface not supported\n");
>>> +		return -ENODEV;
>>> +	}
>>> +
>>> +	bd = backlight_device_get_by_type(BACKLIGHT_RAW);
>>> +	if (!bd)
>>> +		return -ENODEV;
>>
>> This assumes that the backlight is always controller by the amdgpu's
>> native backlight driver, but it might e.g. also be handled by
>> eacpi-video or by nvidia_wmi_ec_backlight (when using an AMD APU +
>> nvidia dgpu).
> 
> PMF is meant for AMD APUs(atleast for now) and the _HID will only be
> made visible if its AMD laptop. So using amdgpu's native BACKLIGHT_RAW
> should be safe, right?

Users can pass say acpi_backlight=video and use the acpi_video
driver for backlight control instead of the native GPU backlight
control.

> 
>>
>> For now what should be done here is to call acpi_video_get_backlight_type()
>> and then translate the return value from this into a backlight-type:
>>
>>         acpi_backlight_video		-> BACKLIGHT_FIRMWARE
>>         acpi_backlight_vendor,		-> BACKLIGHT_PLATFORM
>>         acpi_backlight_native,		-> BACKLIGHT_RAW
>>         acpi_backlight_nvidia_wmi_ec,	-> BACKLIGHT_FIRMWARE
>>         acpi_backlight_apple_gmux,	-> BACKLIGHT_PLATFORM
>>
> 
> I can add this change in the v2, do you insist on this?

Insist is a strong word, but I think that it is a good idea to have
this. Evenutally it looks like this code will need to either integrate with
the drm drivers lot more; or the drm core needs to export some special
hooks for this which the PMF code can then call.

Actually thinking more about this, I think that the right thing to do
here is make some code register brightness control as a cooling device
(which I think is already done in some cases) and then have the PMF
code use the cooling-device APIs for this.

IMHO that would be a much cleaner solution then this hack.

Regards,

Hans



> 
> Thanks,
> Shyam
> 
>> Also I'm worried about probe order here, this code currently assumes
>> that the GPU or other backlight driver has loaded before this runs,
>> which is not necessarily the case.
>>
>> I think that if the backlight_device_get_by_type() fails this
>> should be retried say every 10 seconds from some delayed workqueue
>> for at least a couple of minutes after boot.
>>
>> Regards,
>>
>> Hans
>>
>>
>>
>>
>>> +
>>> +	backlight_device_set_brightness(bd, pmf->brightness);
>>> +
>>> +	return 0;
>>> +}
>>> +EXPORT_SYMBOL_GPL(amd_pmf_set_gfx_data);
>>> diff --git a/drivers/platform/x86/amd/pmf/pmf.h b/drivers/platform/x86/amd/pmf/pmf.h
>>> index 9032df4ba48a..ce89cc0daa5a 100644
>>> --- a/drivers/platform/x86/amd/pmf/pmf.h
>>> +++ b/drivers/platform/x86/amd/pmf/pmf.h
>>> @@ -73,6 +73,7 @@
>>>  #define PMF_POLICY_STT_SKINTEMP_APU				7
>>>  #define PMF_POLICY_STT_SKINTEMP_HS2				8
>>>  #define PMF_POLICY_SYSTEM_STATE					9
>>> +#define PMF_POLICY_DISPLAY_BRIGHTNESS				12
>>>  #define PMF_POLICY_P3T						38
>>>  
>>>  /* TA macros */
>>> @@ -480,6 +481,7 @@ enum ta_pmf_error_type {
>>>  };
>>>  
>>>  struct pmf_action_table {
>>> +	unsigned long display_brightness;
>>>  	enum system_state system_state;
>>>  	unsigned long spl; /* in mW */
>>>  	unsigned long sppt; /* in mW */
>>> diff --git a/drivers/platform/x86/amd/pmf/tee-if.c b/drivers/platform/x86/amd/pmf/tee-if.c
>>> index 1608996654e8..eefffff83a4c 100644
>>> --- a/drivers/platform/x86/amd/pmf/tee-if.c
>>> +++ b/drivers/platform/x86/amd/pmf/tee-if.c
>>> @@ -79,10 +79,10 @@ static int amd_pmf_update_uevents(struct amd_pmf_dev *dev, u16 event)
>>>  	return 0;
>>>  }
>>>  
>>> -static void amd_pmf_apply_policies(struct amd_pmf_dev *dev, struct ta_pmf_enact_result *out)
>>> +static int amd_pmf_apply_policies(struct amd_pmf_dev *dev, struct ta_pmf_enact_result *out)
>>>  {
>>>  	u32 val, event = 0;
>>> -	int idx;
>>> +	int idx, ret;
>>>  
>>>  	for (idx = 0; idx < out->actions_count; idx++) {
>>>  		val = out->actions_list[idx].value;
>>> @@ -160,8 +160,23 @@ static void amd_pmf_apply_policies(struct amd_pmf_dev *dev, struct ta_pmf_enact_
>>>  				dev->prev_data->system_state = 0;
>>>  			}
>>>  			break;
>>> +
>>> +		case PMF_POLICY_DISPLAY_BRIGHTNESS:
>>> +			ret = amd_pmf_get_gfx_data(&dev->gfx_data);
>>> +			if (ret)
>>> +				return ret;
>>> +
>>> +			dev->prev_data->display_brightness = dev->gfx_data.brightness;
>>> +			if (dev->prev_data->display_brightness != val) {
>>> +				dev->gfx_data.brightness = val;
>>> +				amd_pmf_set_gfx_data(&dev->gfx_data);
>>> +				dev_dbg(dev->dev, "update DISPLAY_BRIGHTNESS : %d\n", val);
>>> +			}
>>> +			break;
>>>  		}
>>>  	}
>>> +
>>> +	return 0;
>>>  }
>>>  
>>>  static int amd_pmf_invoke_cmd_enact(struct amd_pmf_dev *dev)
>>> diff --git a/include/linux/amd-pmf-io.h b/include/linux/amd-pmf-io.h
>>> index a2d4af231362..ecae387ddaa6 100644
>>> --- a/include/linux/amd-pmf-io.h
>>> +++ b/include/linux/amd-pmf-io.h
>>> @@ -25,4 +25,5 @@ struct amd_gpu_pmf_data {
>>>  };
>>>  
>>>  int amd_pmf_get_gfx_data(struct amd_gpu_pmf_data *pmf);
>>> +int amd_pmf_set_gfx_data(struct amd_gpu_pmf_data *pmf);
>>>  #endif
>>
> 


^ permalink raw reply	[flat|nested] 54+ messages in thread

* Re: [PATCH 13/15] platform/x86/amd/pmf: Add PMF-AMDGPU set interface
  2023-09-26 12:56       ` Hans de Goede
@ 2023-09-26 13:17         ` Christian König
  2023-09-26 13:48           ` Shyam Sundar S K
  2023-09-27 13:04           ` Hans de Goede
  0 siblings, 2 replies; 54+ messages in thread
From: Christian König @ 2023-09-26 13:17 UTC (permalink / raw)
  To: Hans de Goede, Shyam Sundar S K, markgross, basavaraj.natikar,
	jikos, benjamin.tissoires, alexander.deucher, christian.koenig,
	Xinhui.Pan, airlied, daniel
  Cc: amd-gfx, dri-devel, platform-driver-x86, mario.limonciello,
	Patil.Reddy, linux-input

Am 26.09.23 um 14:56 schrieb Hans de Goede:
> Hi,
>
> On 9/26/23 13:24, Shyam Sundar S K wrote:
>> Hi Hans,
>>
>> On 9/26/2023 4:05 PM, Hans de Goede wrote:
>>> Hi,
>>>
>>> On 9/22/23 19:50, Shyam Sundar S K wrote:
>>>> For the Smart PC Solution to fully work, it has to enact to the actions
>>>> coming from TA. Add the initial code path for set interface to AMDGPU.
>>>>
>>>> Co-developed-by: Mario Limonciello <mario.limonciello@amd.com>
>>>> Signed-off-by: Mario Limonciello <mario.limonciello@amd.com>
>>>> Signed-off-by: Shyam Sundar S K <Shyam-sundar.S-k@amd.com>
>>>> ---
>>>>   drivers/gpu/drm/amd/amdgpu/amdgpu_pmf.c | 21 +++++++++++++++++++++
>>>>   drivers/platform/x86/amd/pmf/pmf.h      |  2 ++
>>>>   drivers/platform/x86/amd/pmf/tee-if.c   | 19 +++++++++++++++++--
>>>>   include/linux/amd-pmf-io.h              |  1 +
>>>>   4 files changed, 41 insertions(+), 2 deletions(-)
>>>>
>>>> diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_pmf.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_pmf.c
>>>> index 232d11833ddc..5c567bff0548 100644
>>>> --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_pmf.c
>>>> +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_pmf.c
>>>> @@ -68,3 +68,24 @@ int amd_pmf_get_gfx_data(struct amd_gpu_pmf_data *pmf)
>>>>   	return 0;
>>>>   }
>>>>   EXPORT_SYMBOL_GPL(amd_pmf_get_gfx_data);
>>>> +
>>>> +int amd_pmf_set_gfx_data(struct amd_gpu_pmf_data *pmf)
>>>> +{
>>>> +	struct drm_device *drm_dev = pci_get_drvdata(pmf->gpu_dev);
>>>> +	struct amdgpu_device *adev = drm_to_adev(drm_dev);
>>>> +	struct backlight_device *bd;
>>>> +
>>>> +	if (!(adev->flags & AMD_IS_APU)) {
>>>> +		DRM_ERROR("PMF-AMDGPU interface not supported\n");
>>>> +		return -ENODEV;
>>>> +	}
>>>> +
>>>> +	bd = backlight_device_get_by_type(BACKLIGHT_RAW);
>>>> +	if (!bd)
>>>> +		return -ENODEV;
>>> This assumes that the backlight is always controller by the amdgpu's
>>> native backlight driver, but it might e.g. also be handled by
>>> eacpi-video or by nvidia_wmi_ec_backlight (when using an AMD APU +
>>> nvidia dgpu).
>> PMF is meant for AMD APUs(atleast for now) and the _HID will only be
>> made visible if its AMD laptop. So using amdgpu's native BACKLIGHT_RAW
>> should be safe, right?
> Users can pass say acpi_backlight=video and use the acpi_video
> driver for backlight control instead of the native GPU backlight
> control.
>
>>> For now what should be done here is to call acpi_video_get_backlight_type()
>>> and then translate the return value from this into a backlight-type:
>>>
>>>          acpi_backlight_video		-> BACKLIGHT_FIRMWARE
>>>          acpi_backlight_vendor,		-> BACKLIGHT_PLATFORM
>>>          acpi_backlight_native,		-> BACKLIGHT_RAW
>>>          acpi_backlight_nvidia_wmi_ec,	-> BACKLIGHT_FIRMWARE
>>>          acpi_backlight_apple_gmux,	-> BACKLIGHT_PLATFORM
>>>
>> I can add this change in the v2, do you insist on this?
> Insist is a strong word, but I think that it is a good idea to have
> this. Evenutally it looks like this code will need to either integrate with
> the drm drivers lot more; or the drm core needs to export some special
> hooks for this which the PMF code can then call.
>
> Actually thinking more about this, I think that the right thing to do
> here is make some code register brightness control as a cooling device
> (which I think is already done in some cases) and then have the PMF
> code use the cooling-device APIs for this.
>
> IMHO that would be a much cleaner solution then this hack.

Yeah, fully agree with Hans. This looks like a rather extreme hack to me.

Apart from that what exactly is this thing supposed to do? Prevent 
overheating by reducing the brightness?

Regards,
Christian.

>
> Regards,
>
> Hans
>
>
>
>> Thanks,
>> Shyam
>>
>>> Also I'm worried about probe order here, this code currently assumes
>>> that the GPU or other backlight driver has loaded before this runs,
>>> which is not necessarily the case.
>>>
>>> I think that if the backlight_device_get_by_type() fails this
>>> should be retried say every 10 seconds from some delayed workqueue
>>> for at least a couple of minutes after boot.
>>>
>>> Regards,
>>>
>>> Hans
>>>
>>>
>>>
>>>
>>>> +
>>>> +	backlight_device_set_brightness(bd, pmf->brightness);
>>>> +
>>>> +	return 0;
>>>> +}
>>>> +EXPORT_SYMBOL_GPL(amd_pmf_set_gfx_data);
>>>> diff --git a/drivers/platform/x86/amd/pmf/pmf.h b/drivers/platform/x86/amd/pmf/pmf.h
>>>> index 9032df4ba48a..ce89cc0daa5a 100644
>>>> --- a/drivers/platform/x86/amd/pmf/pmf.h
>>>> +++ b/drivers/platform/x86/amd/pmf/pmf.h
>>>> @@ -73,6 +73,7 @@
>>>>   #define PMF_POLICY_STT_SKINTEMP_APU				7
>>>>   #define PMF_POLICY_STT_SKINTEMP_HS2				8
>>>>   #define PMF_POLICY_SYSTEM_STATE					9
>>>> +#define PMF_POLICY_DISPLAY_BRIGHTNESS				12
>>>>   #define PMF_POLICY_P3T						38
>>>>   
>>>>   /* TA macros */
>>>> @@ -480,6 +481,7 @@ enum ta_pmf_error_type {
>>>>   };
>>>>   
>>>>   struct pmf_action_table {
>>>> +	unsigned long display_brightness;
>>>>   	enum system_state system_state;
>>>>   	unsigned long spl; /* in mW */
>>>>   	unsigned long sppt; /* in mW */
>>>> diff --git a/drivers/platform/x86/amd/pmf/tee-if.c b/drivers/platform/x86/amd/pmf/tee-if.c
>>>> index 1608996654e8..eefffff83a4c 100644
>>>> --- a/drivers/platform/x86/amd/pmf/tee-if.c
>>>> +++ b/drivers/platform/x86/amd/pmf/tee-if.c
>>>> @@ -79,10 +79,10 @@ static int amd_pmf_update_uevents(struct amd_pmf_dev *dev, u16 event)
>>>>   	return 0;
>>>>   }
>>>>   
>>>> -static void amd_pmf_apply_policies(struct amd_pmf_dev *dev, struct ta_pmf_enact_result *out)
>>>> +static int amd_pmf_apply_policies(struct amd_pmf_dev *dev, struct ta_pmf_enact_result *out)
>>>>   {
>>>>   	u32 val, event = 0;
>>>> -	int idx;
>>>> +	int idx, ret;
>>>>   
>>>>   	for (idx = 0; idx < out->actions_count; idx++) {
>>>>   		val = out->actions_list[idx].value;
>>>> @@ -160,8 +160,23 @@ static void amd_pmf_apply_policies(struct amd_pmf_dev *dev, struct ta_pmf_enact_
>>>>   				dev->prev_data->system_state = 0;
>>>>   			}
>>>>   			break;
>>>> +
>>>> +		case PMF_POLICY_DISPLAY_BRIGHTNESS:
>>>> +			ret = amd_pmf_get_gfx_data(&dev->gfx_data);
>>>> +			if (ret)
>>>> +				return ret;
>>>> +
>>>> +			dev->prev_data->display_brightness = dev->gfx_data.brightness;
>>>> +			if (dev->prev_data->display_brightness != val) {
>>>> +				dev->gfx_data.brightness = val;
>>>> +				amd_pmf_set_gfx_data(&dev->gfx_data);
>>>> +				dev_dbg(dev->dev, "update DISPLAY_BRIGHTNESS : %d\n", val);
>>>> +			}
>>>> +			break;
>>>>   		}
>>>>   	}
>>>> +
>>>> +	return 0;
>>>>   }
>>>>   
>>>>   static int amd_pmf_invoke_cmd_enact(struct amd_pmf_dev *dev)
>>>> diff --git a/include/linux/amd-pmf-io.h b/include/linux/amd-pmf-io.h
>>>> index a2d4af231362..ecae387ddaa6 100644
>>>> --- a/include/linux/amd-pmf-io.h
>>>> +++ b/include/linux/amd-pmf-io.h
>>>> @@ -25,4 +25,5 @@ struct amd_gpu_pmf_data {
>>>>   };
>>>>   
>>>>   int amd_pmf_get_gfx_data(struct amd_gpu_pmf_data *pmf);
>>>> +int amd_pmf_set_gfx_data(struct amd_gpu_pmf_data *pmf);
>>>>   #endif


^ permalink raw reply	[flat|nested] 54+ messages in thread

* Re: [PATCH 13/15] platform/x86/amd/pmf: Add PMF-AMDGPU set interface
  2023-09-26 13:17         ` Christian König
@ 2023-09-26 13:48           ` Shyam Sundar S K
  2023-09-27 13:04           ` Hans de Goede
  1 sibling, 0 replies; 54+ messages in thread
From: Shyam Sundar S K @ 2023-09-26 13:48 UTC (permalink / raw)
  To: Christian König, Hans de Goede, markgross,
	basavaraj.natikar, jikos, benjamin.tissoires, alexander.deucher,
	Xinhui.Pan, airlied, daniel
  Cc: amd-gfx, dri-devel, platform-driver-x86, mario.limonciello,
	Patil.Reddy, linux-input

Hi Christian,

On 9/26/2023 6:47 PM, Christian König wrote:
> Am 26.09.23 um 14:56 schrieb Hans de Goede:
>> Hi,
>>
>> On 9/26/23 13:24, Shyam Sundar S K wrote:
>>> Hi Hans,
>>>
>>> On 9/26/2023 4:05 PM, Hans de Goede wrote:
>>>> Hi,
>>>>
>>>> On 9/22/23 19:50, Shyam Sundar S K wrote:
>>>>> For the Smart PC Solution to fully work, it has to enact to the
>>>>> actions
>>>>> coming from TA. Add the initial code path for set interface to
>>>>> AMDGPU.
>>>>>
>>>>> Co-developed-by: Mario Limonciello <mario.limonciello@amd.com>
>>>>> Signed-off-by: Mario Limonciello <mario.limonciello@amd.com>
>>>>> Signed-off-by: Shyam Sundar S K <Shyam-sundar.S-k@amd.com>
>>>>> ---
>>>>>   drivers/gpu/drm/amd/amdgpu/amdgpu_pmf.c | 21 +++++++++++++++++++++
>>>>>   drivers/platform/x86/amd/pmf/pmf.h      |  2 ++
>>>>>   drivers/platform/x86/amd/pmf/tee-if.c   | 19 +++++++++++++++++--
>>>>>   include/linux/amd-pmf-io.h              |  1 +
>>>>>   4 files changed, 41 insertions(+), 2 deletions(-)
>>>>>
>>>>> diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_pmf.c
>>>>> b/drivers/gpu/drm/amd/amdgpu/amdgpu_pmf.c
>>>>> index 232d11833ddc..5c567bff0548 100644
>>>>> --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_pmf.c
>>>>> +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_pmf.c
>>>>> @@ -68,3 +68,24 @@ int amd_pmf_get_gfx_data(struct
>>>>> amd_gpu_pmf_data *pmf)
>>>>>       return 0;
>>>>>   }
>>>>>   EXPORT_SYMBOL_GPL(amd_pmf_get_gfx_data);
>>>>> +
>>>>> +int amd_pmf_set_gfx_data(struct amd_gpu_pmf_data *pmf)
>>>>> +{
>>>>> +    struct drm_device *drm_dev = pci_get_drvdata(pmf->gpu_dev);
>>>>> +    struct amdgpu_device *adev = drm_to_adev(drm_dev);
>>>>> +    struct backlight_device *bd;
>>>>> +
>>>>> +    if (!(adev->flags & AMD_IS_APU)) {
>>>>> +        DRM_ERROR("PMF-AMDGPU interface not supported\n");
>>>>> +        return -ENODEV;
>>>>> +    }
>>>>> +
>>>>> +    bd = backlight_device_get_by_type(BACKLIGHT_RAW);
>>>>> +    if (!bd)
>>>>> +        return -ENODEV;
>>>> This assumes that the backlight is always controller by the amdgpu's
>>>> native backlight driver, but it might e.g. also be handled by
>>>> eacpi-video or by nvidia_wmi_ec_backlight (when using an AMD APU +
>>>> nvidia dgpu).
>>> PMF is meant for AMD APUs(atleast for now) and the _HID will only be
>>> made visible if its AMD laptop. So using amdgpu's native BACKLIGHT_RAW
>>> should be safe, right?
>> Users can pass say acpi_backlight=video and use the acpi_video
>> driver for backlight control instead of the native GPU backlight
>> control.
>>
>>>> For now what should be done here is to call
>>>> acpi_video_get_backlight_type()
>>>> and then translate the return value from this into a backlight-type:
>>>>
>>>>          acpi_backlight_video        -> BACKLIGHT_FIRMWARE
>>>>          acpi_backlight_vendor,        -> BACKLIGHT_PLATFORM
>>>>          acpi_backlight_native,        -> BACKLIGHT_RAW
>>>>          acpi_backlight_nvidia_wmi_ec,    -> BACKLIGHT_FIRMWARE
>>>>          acpi_backlight_apple_gmux,    -> BACKLIGHT_PLATFORM
>>>>
>>> I can add this change in the v2, do you insist on this?
>> Insist is a strong word, but I think that it is a good idea to have
>> this. Evenutally it looks like this code will need to either
>> integrate with
>> the drm drivers lot more; or the drm core needs to export some special
>> hooks for this which the PMF code can then call.
>>
>> Actually thinking more about this, I think that the right thing to do
>> here is make some code register brightness control as a cooling device
>> (which I think is already done in some cases) and then have the PMF
>> code use the cooling-device APIs for this.
>>
>> IMHO that would be a much cleaner solution then this hack.
> 
> Yeah, fully agree with Hans. This looks like a rather extreme hack to me.

Sure. Let me think in this direction.

> 
> Apart from that what exactly is this thing supposed to do? Prevent
> overheating by reducing the brightness?

Yes that can be one of the cases. But the thought process here is to
help OEMs build their own policies.

A policy is combination of inputs and outputs. Inputs are the
conditions that has to be met and outputs are the actions to be set/done.

The output actions come from PMF TA. One example policy apart from the
case you mentioned is:

if ambient light (received from amd_sfh) is low ; reduce the screen
brightness (received from amdgpu) or vice versa.

Thanks,
Shyam

> 
> Regards,
> Christian.
> 
>>
>> Regards,
>>
>> Hans
>>
>>
>>
>>> Thanks,
>>> Shyam
>>>
>>>> Also I'm worried about probe order here, this code currently assumes
>>>> that the GPU or other backlight driver has loaded before this runs,
>>>> which is not necessarily the case.
>>>>
>>>> I think that if the backlight_device_get_by_type() fails this
>>>> should be retried say every 10 seconds from some delayed workqueue
>>>> for at least a couple of minutes after boot.
>>>>
>>>> Regards,
>>>>
>>>> Hans
>>>>
>>>>
>>>>
>>>>
>>>>> +
>>>>> +    backlight_device_set_brightness(bd, pmf->brightness);
>>>>> +
>>>>> +    return 0;
>>>>> +}
>>>>> +EXPORT_SYMBOL_GPL(amd_pmf_set_gfx_data);
>>>>> diff --git a/drivers/platform/x86/amd/pmf/pmf.h
>>>>> b/drivers/platform/x86/amd/pmf/pmf.h
>>>>> index 9032df4ba48a..ce89cc0daa5a 100644
>>>>> --- a/drivers/platform/x86/amd/pmf/pmf.h
>>>>> +++ b/drivers/platform/x86/amd/pmf/pmf.h
>>>>> @@ -73,6 +73,7 @@
>>>>>   #define PMF_POLICY_STT_SKINTEMP_APU                7
>>>>>   #define PMF_POLICY_STT_SKINTEMP_HS2                8
>>>>>   #define PMF_POLICY_SYSTEM_STATE                    9
>>>>> +#define PMF_POLICY_DISPLAY_BRIGHTNESS                12
>>>>>   #define PMF_POLICY_P3T                        38
>>>>>     /* TA macros */
>>>>> @@ -480,6 +481,7 @@ enum ta_pmf_error_type {
>>>>>   };
>>>>>     struct pmf_action_table {
>>>>> +    unsigned long display_brightness;
>>>>>       enum system_state system_state;
>>>>>       unsigned long spl; /* in mW */
>>>>>       unsigned long sppt; /* in mW */
>>>>> diff --git a/drivers/platform/x86/amd/pmf/tee-if.c
>>>>> b/drivers/platform/x86/amd/pmf/tee-if.c
>>>>> index 1608996654e8..eefffff83a4c 100644
>>>>> --- a/drivers/platform/x86/amd/pmf/tee-if.c
>>>>> +++ b/drivers/platform/x86/amd/pmf/tee-if.c
>>>>> @@ -79,10 +79,10 @@ static int amd_pmf_update_uevents(struct
>>>>> amd_pmf_dev *dev, u16 event)
>>>>>       return 0;
>>>>>   }
>>>>>   -static void amd_pmf_apply_policies(struct amd_pmf_dev *dev,
>>>>> struct ta_pmf_enact_result *out)
>>>>> +static int amd_pmf_apply_policies(struct amd_pmf_dev *dev,
>>>>> struct ta_pmf_enact_result *out)
>>>>>   {
>>>>>       u32 val, event = 0;
>>>>> -    int idx;
>>>>> +    int idx, ret;
>>>>>         for (idx = 0; idx < out->actions_count; idx++) {
>>>>>           val = out->actions_list[idx].value;
>>>>> @@ -160,8 +160,23 @@ static void amd_pmf_apply_policies(struct
>>>>> amd_pmf_dev *dev, struct ta_pmf_enact_
>>>>>                   dev->prev_data->system_state = 0;
>>>>>               }
>>>>>               break;
>>>>> +
>>>>> +        case PMF_POLICY_DISPLAY_BRIGHTNESS:
>>>>> +            ret = amd_pmf_get_gfx_data(&dev->gfx_data);
>>>>> +            if (ret)
>>>>> +                return ret;
>>>>> +
>>>>> +            dev->prev_data->display_brightness =
>>>>> dev->gfx_data.brightness;
>>>>> +            if (dev->prev_data->display_brightness != val) {
>>>>> +                dev->gfx_data.brightness = val;
>>>>> +                amd_pmf_set_gfx_data(&dev->gfx_data);
>>>>> +                dev_dbg(dev->dev, "update DISPLAY_BRIGHTNESS :
>>>>> %d\n", val);
>>>>> +            }
>>>>> +            break;
>>>>>           }
>>>>>       }
>>>>> +
>>>>> +    return 0;
>>>>>   }
>>>>>     static int amd_pmf_invoke_cmd_enact(struct amd_pmf_dev *dev)
>>>>> diff --git a/include/linux/amd-pmf-io.h b/include/linux/amd-pmf-io.h
>>>>> index a2d4af231362..ecae387ddaa6 100644
>>>>> --- a/include/linux/amd-pmf-io.h
>>>>> +++ b/include/linux/amd-pmf-io.h
>>>>> @@ -25,4 +25,5 @@ struct amd_gpu_pmf_data {
>>>>>   };
>>>>>     int amd_pmf_get_gfx_data(struct amd_gpu_pmf_data *pmf);
>>>>> +int amd_pmf_set_gfx_data(struct amd_gpu_pmf_data *pmf);
>>>>>   #endif
> 

^ permalink raw reply	[flat|nested] 54+ messages in thread

* Re: [PATCH 01/15] platform/x86/amd/pmf: Add PMF TEE interface
  2023-09-22 17:50 ` [PATCH 01/15] platform/x86/amd/pmf: Add PMF TEE interface Shyam Sundar S K
@ 2023-09-26 16:42   ` Ilpo Järvinen
  0 siblings, 0 replies; 54+ messages in thread
From: Ilpo Järvinen @ 2023-09-26 16:42 UTC (permalink / raw)
  To: Shyam Sundar S K
  Cc: Xinhui.Pan, Patil.Reddy, basavaraj.natikar, dri-devel, jikos,
	amd-gfx, platform-driver-x86, markgross, Hans de Goede,
	benjamin.tissoires, mario.limonciello, linux-input,
	alexander.deucher, christian.koenig

On Fri, 22 Sep 2023, Shyam Sundar S K wrote:

> AMD PMF driver loads the PMF TA (Trusted Application) into the AMD
> ASP's (AMD Security Processor) TEE (Trusted Execution Environment).
> 
> PMF Trusted Application is a secured firmware placed under
> /lib/firmware/amdtee gets loaded only when the TEE environment is
> initialized. Add the initial code path to build these pipes.
> 
> Reviewed-by: Mario Limonciello <mario.limonciello@amd.com>
> Signed-off-by: Shyam Sundar S K <Shyam-sundar.S-k@amd.com>
> ---
>  drivers/platform/x86/amd/pmf/Makefile |   3 +-
>  drivers/platform/x86/amd/pmf/core.c   |  11 ++-
>  drivers/platform/x86/amd/pmf/pmf.h    |  16 ++++
>  drivers/platform/x86/amd/pmf/tee-if.c | 106 ++++++++++++++++++++++++++
>  4 files changed, 132 insertions(+), 4 deletions(-)
>  create mode 100644 drivers/platform/x86/amd/pmf/tee-if.c
> 
> diff --git a/drivers/platform/x86/amd/pmf/Makefile b/drivers/platform/x86/amd/pmf/Makefile
> index fdededf54392..d2746ee7369f 100644
> --- a/drivers/platform/x86/amd/pmf/Makefile
> +++ b/drivers/platform/x86/amd/pmf/Makefile
> @@ -6,4 +6,5 @@
>  
>  obj-$(CONFIG_AMD_PMF) += amd-pmf.o
>  amd-pmf-objs := core.o acpi.o sps.o \
> -		auto-mode.o cnqf.o
> +		auto-mode.o cnqf.o \
> +		tee-if.o
> diff --git a/drivers/platform/x86/amd/pmf/core.c b/drivers/platform/x86/amd/pmf/core.c
> index 78ed3ee22555..68f1389dda3e 100644
> --- a/drivers/platform/x86/amd/pmf/core.c
> +++ b/drivers/platform/x86/amd/pmf/core.c
> @@ -309,8 +309,11 @@ static void amd_pmf_init_features(struct amd_pmf_dev *dev)
>  		dev_dbg(dev->dev, "SPS enabled and Platform Profiles registered\n");
>  	}
>  
> -	/* Enable Auto Mode */
> -	if (is_apmf_func_supported(dev, APMF_FUNC_AUTO_MODE)) {
> +	if (amd_pmf_init_smart_pc(dev)) {
> +		/* Enable Smart PC Solution builder */
> +		dev_dbg(dev->dev, "Smart PC Solution Enabled\n");
> +	} else if (is_apmf_func_supported(dev, APMF_FUNC_AUTO_MODE)) {
> +		/* Enable Auto Mode */
>  		amd_pmf_init_auto_mode(dev);
>  		dev_dbg(dev->dev, "Auto Mode Init done\n");
>  	} else if (is_apmf_func_supported(dev, APMF_FUNC_DYN_SLIDER_AC) ||
> @@ -330,7 +333,9 @@ static void amd_pmf_deinit_features(struct amd_pmf_dev *dev)
>  		amd_pmf_deinit_sps(dev);
>  	}
>  
> -	if (is_apmf_func_supported(dev, APMF_FUNC_AUTO_MODE)) {
> +	if (dev->smart_pc_enabled) {
> +		amd_pmf_deinit_smart_pc(dev);
> +	} else if (is_apmf_func_supported(dev, APMF_FUNC_AUTO_MODE)) {
>  		amd_pmf_deinit_auto_mode(dev);
>  	} else if (is_apmf_func_supported(dev, APMF_FUNC_DYN_SLIDER_AC) ||
>  			  is_apmf_func_supported(dev, APMF_FUNC_DYN_SLIDER_DC)) {
> diff --git a/drivers/platform/x86/amd/pmf/pmf.h b/drivers/platform/x86/amd/pmf/pmf.h
> index deba88e6e4c8..02460c2a31ea 100644
> --- a/drivers/platform/x86/amd/pmf/pmf.h
> +++ b/drivers/platform/x86/amd/pmf/pmf.h
> @@ -179,6 +179,12 @@ struct amd_pmf_dev {
>  	bool cnqf_enabled;
>  	bool cnqf_supported;
>  	struct notifier_block pwr_src_notifier;
> +	/* Smart PC solution builder */
> +	struct tee_context *tee_ctx;
> +	struct tee_shm *fw_shm_pool;
> +	u32 session_id;
> +	void *shbuf;
> +	bool smart_pc_enabled;
>  };
>  
>  struct apmf_sps_prop_granular {
> @@ -389,6 +395,13 @@ struct apmf_dyn_slider_output {
>  	struct apmf_cnqf_power_set ps[APMF_CNQF_MAX];
>  } __packed;
>  
> +struct ta_pmf_shared_memory {
> +	int command_id;
> +	int resp_id;
> +	u32 pmf_result;
> +	u32 if_version;
> +};
> +
>  /* Core Layer */
>  int apmf_acpi_init(struct amd_pmf_dev *pmf_dev);
>  void apmf_acpi_deinit(struct amd_pmf_dev *pmf_dev);
> @@ -433,4 +446,7 @@ void amd_pmf_deinit_cnqf(struct amd_pmf_dev *dev);
>  int amd_pmf_trans_cnqf(struct amd_pmf_dev *dev, int socket_power, ktime_t time_lapsed_ms);
>  extern const struct attribute_group cnqf_feature_attribute_group;
>  
> +/* Smart PC builder Layer*/
> +int amd_pmf_init_smart_pc(struct amd_pmf_dev *dev);
> +void amd_pmf_deinit_smart_pc(struct amd_pmf_dev *dev);
>  #endif /* PMF_H */
> diff --git a/drivers/platform/x86/amd/pmf/tee-if.c b/drivers/platform/x86/amd/pmf/tee-if.c
> new file mode 100644
> index 000000000000..b48340edbf44
> --- /dev/null
> +++ b/drivers/platform/x86/amd/pmf/tee-if.c
> @@ -0,0 +1,106 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * AMD Platform Management Framework Driver - TEE Interface
> + *
> + * Copyright (c) 2023, Advanced Micro Devices, Inc.
> + * All Rights Reserved.
> + *
> + * Author: Shyam Sundar S K <Shyam-sundar.S-k@amd.com>
> + */
> +
> +#include <linux/tee_drv.h>
> +#include <linux/uuid.h>
> +#include "pmf.h"
> +
> +#define MAX_TEE_PARAM	4
> +static const uuid_t amd_pmf_ta_uuid = UUID_INIT(0x6fd93b77, 0x3fb8, 0x524d,
> +						0xb1, 0x2d, 0xc5, 0x29, 0xb1, 0x3d, 0x85, 0x43);
> +
> +static int amd_pmf_amdtee_ta_match(struct tee_ioctl_version_data *ver, const void *data)
> +{
> +	return ver->impl_id == TEE_IMPL_ID_AMDTEE;
> +}
> +
> +static int amd_pmf_ta_open_session(struct tee_context *ctx, u32 *id)
> +{
> +	struct tee_ioctl_open_session_arg sess_arg = {};
> +	int rc;
> +
> +	export_uuid(sess_arg.uuid, &amd_pmf_ta_uuid);
> +	sess_arg.clnt_login = TEE_IOCTL_LOGIN_PUBLIC;
> +	sess_arg.num_params = 0;
> +
> +	rc = tee_client_open_session(ctx, &sess_arg, NULL);
> +	if (rc < 0 || sess_arg.ret != 0) {
> +		pr_err("%s: tee_client_open_session failed err:%#x, ret:%#x\n",
> +		       __func__, sess_arg.ret, rc);

Don't print function names but meaningful messages (no __func__ nor 
manually added function names). I didn't make the others, please take care 
of them all, thank you.

-- 
 i.


> +		rc = -EINVAL;
> +	} else {
> +		*id = sess_arg.session;
> +	}
> +
> +	return rc;
> +}
> +
> +static int amd_pmf_tee_init(struct amd_pmf_dev *dev)
> +{
> +	int ret;
> +	u32 size;
> +
> +	/* Open context with TEE driver */
> +	dev->tee_ctx = tee_client_open_context(NULL, amd_pmf_amdtee_ta_match, NULL, NULL);
> +	if (IS_ERR(dev->tee_ctx)) {
> +		dev_err(dev->dev, "%s: tee_client_open_context failed\n", __func__);
> +		return PTR_ERR(dev->tee_ctx);
> +	}
> +
> +	/* Open session with PMF Trusted App */
> +	ret = amd_pmf_ta_open_session(dev->tee_ctx, &dev->session_id);
> +	if (ret) {
> +		dev_err(dev->dev, "%s: amd_pmf_ta_open_session failed(%d)\n", __func__, ret);
> +		ret = -EINVAL;
> +		goto out_ctx;
> +	}
> +
> +	size = sizeof(struct ta_pmf_shared_memory);
> +	dev->fw_shm_pool = tee_shm_alloc_kernel_buf(dev->tee_ctx, size);
> +	if (IS_ERR(dev->fw_shm_pool)) {
> +		dev_err(dev->dev, "%s: tee_shm_alloc_kernel_buf failed\n", __func__);
> +		ret = PTR_ERR(dev->fw_shm_pool);
> +		goto out_sess;
> +	}
> +
> +	dev->shbuf = tee_shm_get_va(dev->fw_shm_pool, 0);
> +	dev_dbg(dev->dev, "TEE init done\n");
> +
> +	return 0;
> +
> +out_sess:
> +	tee_client_close_session(dev->tee_ctx, dev->session_id);
> +out_ctx:
> +	tee_client_close_context(dev->tee_ctx);
> +
> +	return ret;
> +}
> +
> +static void amd_pmf_tee_deinit(struct amd_pmf_dev *dev)
> +{
> +	/* Free the shared memory pool */
> +	tee_shm_free(dev->fw_shm_pool);
> +
> +	/* close the existing session with PMF TA*/
> +	tee_client_close_session(dev->tee_ctx, dev->session_id);
> +
> +	/* close the context with TEE driver */
> +	tee_client_close_context(dev->tee_ctx);
> +}
> +
> +int amd_pmf_init_smart_pc(struct amd_pmf_dev *dev)
> +{
> +	return amd_pmf_tee_init(dev);
> +}
> +
> +void amd_pmf_deinit_smart_pc(struct amd_pmf_dev *dev)
> +{
> +	amd_pmf_tee_deinit(dev);
> +}
> 

^ permalink raw reply	[flat|nested] 54+ messages in thread

* Re: [PATCH 02/15] platform/x86/amd/pmf: Add support PMF-TA interaction
  2023-09-22 17:50 ` [PATCH 02/15] platform/x86/amd/pmf: Add support PMF-TA interaction Shyam Sundar S K
@ 2023-09-26 16:48   ` Ilpo Järvinen
  0 siblings, 0 replies; 54+ messages in thread
From: Ilpo Järvinen @ 2023-09-26 16:48 UTC (permalink / raw)
  To: Shyam Sundar S K
  Cc: Xinhui.Pan, Patil.Reddy, basavaraj.natikar, dri-devel, jikos,
	amd-gfx, platform-driver-x86, markgross, hdegoede,
	benjamin.tissoires, mario.limonciello, linux-input,
	alexander.deucher, christian.koenig

On Fri, 22 Sep 2023, Shyam Sundar S K wrote:

> PMF TA (Trusted Application) loads via the TEE environment into the
> AMD ASP.
> 
> PMF-TA supports two commands:
> 1) Init: Initialize the TA with the PMF Smart PC policy binary and
> start the policy engine. A policy is a combination of inputs and
> outputs, where;
>  - the inputs are the changing dynamics of the system like the user
>    behaviour, system heuristics etc.
>  - the outputs, which are the actions to be set on the system which
>    lead to better power management and enhanced user experience.
> 
> PMF driver acts as a central manager in this case to supply the
> inputs required to the TA (either by getting the information from
> the other kernel subsystems or from userland)
> 
> 2) Enact: Enact the output actions from the TA. The action could be
> applying a new thermal limit to boost/throttle the power limits or
> change system behavior.
> 
> Reviewed-by: Mario Limonciello <mario.limonciello@amd.com>
> Signed-off-by: Shyam Sundar S K <Shyam-sundar.S-k@amd.com>
> ---
>  drivers/platform/x86/amd/pmf/pmf.h    | 10 +++
>  drivers/platform/x86/amd/pmf/tee-if.c | 97 ++++++++++++++++++++++++++-
>  2 files changed, 106 insertions(+), 1 deletion(-)
> 
> diff --git a/drivers/platform/x86/amd/pmf/pmf.h b/drivers/platform/x86/amd/pmf/pmf.h
> index 02460c2a31ea..a9333ff6c0a7 100644
> --- a/drivers/platform/x86/amd/pmf/pmf.h
> +++ b/drivers/platform/x86/amd/pmf/pmf.h
> @@ -59,6 +59,9 @@
>  #define ARG_NONE 0
>  #define AVG_SAMPLE_SIZE 3
>  
> +/* TA macros */
> +#define PMF_TA_IF_VERSION__MAJOR				1

I suppose double _ is not intentional?

> +
>  /* AMD PMF BIOS interfaces */
>  struct apmf_verify_interface {
>  	u16 size;
> @@ -184,6 +187,7 @@ struct amd_pmf_dev {
>  	struct tee_shm *fw_shm_pool;
>  	u32 session_id;
>  	void *shbuf;
> +	struct delayed_work pb_work;
>  	bool smart_pc_enabled;
>  };
>  
> @@ -395,6 +399,12 @@ struct apmf_dyn_slider_output {
>  	struct apmf_cnqf_power_set ps[APMF_CNQF_MAX];
>  } __packed;
>  
> +/* cmd ids for TA communication */
> +enum ta_pmf_command {
> +	TA_PMF_COMMAND_POLICY_BUILDER__INITIALIZE,
> +	TA_PMF_COMMAND_POLICY_BUILDER__ENACT_POLICIES

Add comma to the second line too.

Did you mean to have double _?

> +};
> +
>  struct ta_pmf_shared_memory {
>  	int command_id;
>  	int resp_id;
> diff --git a/drivers/platform/x86/amd/pmf/tee-if.c b/drivers/platform/x86/amd/pmf/tee-if.c
> index b48340edbf44..1fce04beacb3 100644
> --- a/drivers/platform/x86/amd/pmf/tee-if.c
> +++ b/drivers/platform/x86/amd/pmf/tee-if.c
> @@ -13,9 +13,96 @@
>  #include "pmf.h"
>  
>  #define MAX_TEE_PARAM	4
> +
> +/* Policy binary actions sampling frequency (in ms) */
> +static int pb_actions_ms = 1000;
> +#ifdef CONFIG_AMD_PMF_DEBUG
> +module_param(pb_actions_ms, int, 0644);
> +MODULE_PARM_DESC(pb_actions_ms, "Policy binary actions sampling frequency (default = 1000ms)");
> +#endif
> +
>  static const uuid_t amd_pmf_ta_uuid = UUID_INIT(0x6fd93b77, 0x3fb8, 0x524d,
>  						0xb1, 0x2d, 0xc5, 0x29, 0xb1, 0x3d, 0x85, 0x43);
>  
> +static void amd_pmf_prepare_args(struct amd_pmf_dev *dev, int cmd,
> +				 struct tee_ioctl_invoke_arg *arg,
> +				 struct tee_param *param)
> +{
> +	memset(arg, 0, sizeof(*arg));
> +	memset(param, 0, MAX_TEE_PARAM * sizeof(*param));
> +
> +	arg->func = cmd;
> +	arg->session = dev->session_id;
> +	arg->num_params = MAX_TEE_PARAM;
> +
> +	/* Fill invoke cmd params */
> +	param[0].u.memref.size = sizeof(struct ta_pmf_shared_memory);
> +	param[0].attr = TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INOUT;
> +	param[0].u.memref.shm = dev->fw_shm_pool;
> +	param[0].u.memref.shm_offs = 0;
> +}
> +
> +static int amd_pmf_invoke_cmd_enact(struct amd_pmf_dev *dev)
> +{
> +	struct ta_pmf_shared_memory *ta_sm = NULL;
> +	struct tee_param param[MAX_TEE_PARAM];
> +	struct tee_ioctl_invoke_arg arg;
> +	int ret = 0;
> +
> +	if (!dev->tee_ctx)
> +		return -ENODEV;
> +
> +	ta_sm = (struct ta_pmf_shared_memory *)dev->shbuf;
> +	memset(ta_sm, 0, sizeof(struct ta_pmf_shared_memory));
> +	ta_sm->command_id = TA_PMF_COMMAND_POLICY_BUILDER__ENACT_POLICIES;
> +	ta_sm->if_version = PMF_TA_IF_VERSION__MAJOR;
> +
> +	amd_pmf_prepare_args(dev, TA_PMF_COMMAND_POLICY_BUILDER__ENACT_POLICIES, &arg, param);
> +
> +	ret = tee_client_invoke_func(dev->tee_ctx, &arg, param);
> +	if (ret < 0 || arg.ret != 0) {
> +		dev_err(dev->dev, "%s failed TEE err: %x, ret:%x\n", __func__, arg.ret, ret);

No __func__s please.

> +		return -EINVAL;
> +	}
> +
> +	return 0;
> +}
> +
> +static int amd_pmf_invoke_cmd_init(struct amd_pmf_dev *dev)
> +{
> +	struct ta_pmf_shared_memory *ta_sm = NULL;
> +	struct tee_param param[MAX_TEE_PARAM];
> +	struct tee_ioctl_invoke_arg arg;
> +	int ret = 0;
> +
> +	if (!dev->tee_ctx) {
> +		dev_err(dev->dev, "%s tee_ctx no context\n", __func__);
> +		return -ENODEV;
> +	}
> +
> +	ta_sm = (struct ta_pmf_shared_memory *)dev->shbuf;
> +	ta_sm->command_id = TA_PMF_COMMAND_POLICY_BUILDER__INITIALIZE;
> +	ta_sm->if_version = PMF_TA_IF_VERSION__MAJOR;
> +
> +	amd_pmf_prepare_args(dev, TA_PMF_COMMAND_POLICY_BUILDER__INITIALIZE, &arg, param);
> +
> +	ret = tee_client_invoke_func(dev->tee_ctx, &arg, param);
> +	if (ret < 0 || arg.ret != 0) {
> +		dev_err(dev->dev, "%s failed TEE err: %x, ret:%x\n", __func__, arg.ret, ret);
> +		return -EINVAL;
> +	}
> +
> +	return ta_sm->pmf_result;
> +}
> +
> +static void amd_pmf_invoke_cmd(struct work_struct *work)
> +{
> +	struct amd_pmf_dev *dev = container_of(work, struct amd_pmf_dev, pb_work.work);
> +
> +	amd_pmf_invoke_cmd_enact(dev);
> +	schedule_delayed_work(&dev->pb_work, msecs_to_jiffies(pb_actions_ms));
> +}
> +
>  static int amd_pmf_amdtee_ta_match(struct tee_ioctl_version_data *ver, const void *data)
>  {
>  	return ver->impl_id == TEE_IMPL_ID_AMDTEE;
> @@ -97,10 +184,18 @@ static void amd_pmf_tee_deinit(struct amd_pmf_dev *dev)
>  
>  int amd_pmf_init_smart_pc(struct amd_pmf_dev *dev)
>  {
> -	return amd_pmf_tee_init(dev);
> +	int ret;
> +
> +	ret = amd_pmf_tee_init(dev);
> +	if (ret)
> +		return ret;
> +
> +	INIT_DELAYED_WORK(&dev->pb_work, amd_pmf_invoke_cmd);
> +	return 0;
>  }
>  
>  void amd_pmf_deinit_smart_pc(struct amd_pmf_dev *dev)
>  {
> +	cancel_delayed_work_sync(&dev->pb_work);
>  	amd_pmf_tee_deinit(dev);
>  }
> 

-- 
 i.


^ permalink raw reply	[flat|nested] 54+ messages in thread

* Re: [PATCH 03/15] platform/x86/amd/pmf: Change signature of amd_pmf_set_dram_addr
  2023-09-22 17:50 ` [PATCH 03/15] platform/x86/amd/pmf: Change signature of amd_pmf_set_dram_addr Shyam Sundar S K
@ 2023-09-26 16:52   ` Ilpo Järvinen
  0 siblings, 0 replies; 54+ messages in thread
From: Ilpo Järvinen @ 2023-09-26 16:52 UTC (permalink / raw)
  To: Shyam Sundar S K
  Cc: Xinhui.Pan, Patil.Reddy, basavaraj.natikar, dri-devel, jikos,
	amd-gfx, platform-driver-x86, markgross, hdegoede,
	benjamin.tissoires, mario.limonciello, linux-input,
	alexander.deucher, christian.koenig

On Fri, 22 Sep 2023, Shyam Sundar S K wrote:

Add () to the function name in the shortlog. "Change signature" is quite 
vague, perhaps you could come up something more descriptive.

> Make amd_pmf_set_dram_addr() as non-static so that same function
> can be used across files.

This says nothing about the move of allocation.

> Reviewed-by: Mario Limonciello <mario.limonciello@amd.com>
> Signed-off-by: Shyam Sundar S K <Shyam-sundar.S-k@amd.com>
> ---
>  drivers/platform/x86/amd/pmf/core.c | 14 ++++++++------
>  drivers/platform/x86/amd/pmf/pmf.h  |  1 +
>  2 files changed, 9 insertions(+), 6 deletions(-)
> 
> diff --git a/drivers/platform/x86/amd/pmf/core.c b/drivers/platform/x86/amd/pmf/core.c
> index 68f1389dda3e..5fb03ed614ff 100644
> --- a/drivers/platform/x86/amd/pmf/core.c
> +++ b/drivers/platform/x86/amd/pmf/core.c
> @@ -251,26 +251,28 @@ static const struct pci_device_id pmf_pci_ids[] = {
>  	{ }
>  };
>  
> -static void amd_pmf_set_dram_addr(struct amd_pmf_dev *dev)
> +int amd_pmf_set_dram_addr(struct amd_pmf_dev *dev)
>  {
>  	u64 phys_addr;
>  	u32 hi, low;
>  
> +	/* Get Metrics Table Address */
> +	dev->buf = kzalloc(sizeof(dev->m_table), GFP_KERNEL);
> +	if (!dev->buf)
> +		return -ENOMEM;
> +
>  	phys_addr = virt_to_phys(dev->buf);
>  	hi = phys_addr >> 32;
>  	low = phys_addr & GENMASK(31, 0);
>  
>  	amd_pmf_send_cmd(dev, SET_DRAM_ADDR_HIGH, 0, hi, NULL);
>  	amd_pmf_send_cmd(dev, SET_DRAM_ADDR_LOW, 0, low, NULL);
> +
> +	return 0;
>  }
>  
>  int amd_pmf_init_metrics_table(struct amd_pmf_dev *dev)
>  {
> -	/* Get Metrics Table Address */
> -	dev->buf = kzalloc(sizeof(dev->m_table), GFP_KERNEL);
> -	if (!dev->buf)
> -		return -ENOMEM;
> -
>  	INIT_DELAYED_WORK(&dev->work_buffer, amd_pmf_get_metrics);
>  
>  	amd_pmf_set_dram_addr(dev);
> diff --git a/drivers/platform/x86/amd/pmf/pmf.h b/drivers/platform/x86/amd/pmf/pmf.h
> index a9333ff6c0a7..ea15ce547d24 100644
> --- a/drivers/platform/x86/amd/pmf/pmf.h
> +++ b/drivers/platform/x86/amd/pmf/pmf.h
> @@ -421,6 +421,7 @@ int amd_pmf_init_metrics_table(struct amd_pmf_dev *dev);
>  int amd_pmf_get_power_source(void);
>  int apmf_install_handler(struct amd_pmf_dev *pmf_dev);
>  int apmf_os_power_slider_update(struct amd_pmf_dev *dev, u8 flag);
> +int amd_pmf_set_dram_addr(struct amd_pmf_dev *dev);
>  
>  /* SPS Layer */
>  int amd_pmf_get_pprof_modes(struct amd_pmf_dev *pmf);
> 

Why are not amd_pmf_set_dram_addr() callers made to handle/pass on 
errors???

-- 
 i.


^ permalink raw reply	[flat|nested] 54+ messages in thread

* Re: [PATCH 05/15] platform/x86/amd/pmf: change debugfs init sequence
  2023-09-22 17:50 ` [PATCH 05/15] platform/x86/amd/pmf: change debugfs init sequence Shyam Sundar S K
@ 2023-09-26 16:53   ` Ilpo Järvinen
  0 siblings, 0 replies; 54+ messages in thread
From: Ilpo Järvinen @ 2023-09-26 16:53 UTC (permalink / raw)
  To: Shyam Sundar S K
  Cc: Xinhui.Pan, Patil.Reddy, basavaraj.natikar, dri-devel, jikos,
	amd-gfx, platform-driver-x86, markgross, hdegoede,
	benjamin.tissoires, mario.limonciello, linux-input,
	alexander.deucher, christian.koenig

On Fri, 22 Sep 2023, Shyam Sundar S K wrote:

> amd_pmf_dbgfs_register() needs to be called before amd_pmf_init_features().

Please answer to why? question too here.

> Hence change the sequence.
>
> Reviewed-by: Mario Limonciello <mario.limonciello@amd.com>
> Signed-off-by: Shyam Sundar S K <Shyam-sundar.S-k@amd.com>
> ---
>  drivers/platform/x86/amd/pmf/core.c | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
> 
> diff --git a/drivers/platform/x86/amd/pmf/core.c b/drivers/platform/x86/amd/pmf/core.c
> index 6f36c43e081e..dbfe7c1d6fc4 100644
> --- a/drivers/platform/x86/amd/pmf/core.c
> +++ b/drivers/platform/x86/amd/pmf/core.c
> @@ -427,9 +427,9 @@ static int amd_pmf_probe(struct platform_device *pdev)
>  
>  	apmf_acpi_init(dev);
>  	platform_set_drvdata(pdev, dev);
> +	amd_pmf_dbgfs_register(dev);
>  	amd_pmf_init_features(dev);
>  	apmf_install_handler(dev);
> -	amd_pmf_dbgfs_register(dev);
>  
>  	dev_info(dev->dev, "registered PMF device successfully\n");
>  
> 

-- 
 i.


^ permalink raw reply	[flat|nested] 54+ messages in thread

* Re: [PATCH 04/15] platform/x86/amd/pmf: Add support for PMF Policy Binary
  2023-09-22 17:50 ` [PATCH 04/15] platform/x86/amd/pmf: Add support for PMF Policy Binary Shyam Sundar S K
  2023-09-22 18:51   ` Mario Limonciello
@ 2023-09-26 17:05   ` Ilpo Järvinen
  2023-09-27 12:19   ` Ilpo Järvinen
  2 siblings, 0 replies; 54+ messages in thread
From: Ilpo Järvinen @ 2023-09-26 17:05 UTC (permalink / raw)
  To: Shyam Sundar S K
  Cc: Xinhui.Pan, Patil.Reddy, basavaraj.natikar, dri-devel, jikos,
	amd-gfx, platform-driver-x86, markgross, hdegoede,
	benjamin.tissoires, mario.limonciello, linux-input,
	alexander.deucher, christian.koenig

On Fri, 22 Sep 2023, Shyam Sundar S K wrote:

> PMF Policy binary is a encrypted and signed binary that will be part
> of the BIOS. PMF driver via the ACPI interface checks the existence
> of Smart PC bit. If the advertised bit is found, PMF driver walks
> the acpi namespace to find out the policy binary size and the address
> which has to be passed to the TA during the TA init sequence.
> 
> The policy binary is comprised of inputs (or the events) and outputs
> (or the actions). With the PMF ecosystem, OEMs generate the policy
> binary (or could be multiple binaries) that contains a supported set
> of inputs and outputs which could be specifically carved out for each
> usage segment (or for each user also) that could influence the system
> behavior either by enriching the user experience or/and boost/throttle
> power limits.
> 
> Once the TA init command succeeds, the PMF driver sends the changing
> events in the current environment to the TA for a constant sampling
> frequency time (the event here could be a lid close or open) and
> if the policy binary has corresponding action built within it, the
> TA sends the action for it in the subsequent enact command.
> 
> If the inputs sent to the TA has no output defined in the policy
> binary generated by OEMs, there will be no action to be performed
> by the PMF driver.
> 
> Example policies:
> 
> 1) if slider is performance ; set the SPL to 40W
> Here PMF driver registers with the platform profile interface and
> when the slider position is changed, PMF driver lets the TA know
> about this. TA sends back an action to update the Sustained
> Power Limit (SPL). PMF driver updates this limit via the PMFW mailbox.
> 
> 2) if user_away ; then lock the system
> Here PMF driver hooks to the AMD SFH driver to know the user presence
> and send the inputs to TA and if the condition is met, the TA sends
> the action of locking the system. PMF driver generates a uevent and
> based on the udev rule in the userland the system gets locked with
> systemctl.
> 
> The intent here is to provide the OEM's to make a policy to lock the
> system when the user is away ; but the userland can make a choice to
> ignore it.
> 
> and so on.
> 
> The OEMs will have an utility to create numerous such policies and
> the policies shall be reviewed by AMD before signing and encrypting
> them. Policies are shared between operating systems to have seemless user
> experience.
> 
> Since all this action has to happen via the "amdtee" driver, currently
> there is no caller for it in the kernel which can load the amdtee driver.
> Without amdtee driver loading onto the system the "tee" calls shall fail
> from the PMF driver. Hence an explicit "request_module" has been added
> to address this.
> 
> Signed-off-by: Shyam Sundar S K <Shyam-sundar.S-k@amd.com>
> ---
>  drivers/platform/x86/amd/pmf/Kconfig  |   1 +
>  drivers/platform/x86/amd/pmf/acpi.c   |  37 +++++++
>  drivers/platform/x86/amd/pmf/core.c   |  12 +++
>  drivers/platform/x86/amd/pmf/pmf.h    | 132 ++++++++++++++++++++++++
>  drivers/platform/x86/amd/pmf/tee-if.c | 141 +++++++++++++++++++++++++-
>  5 files changed, 321 insertions(+), 2 deletions(-)
> 
> diff --git a/drivers/platform/x86/amd/pmf/Kconfig b/drivers/platform/x86/amd/pmf/Kconfig
> index 3064bc8ea167..437b78c6d1c5 100644
> --- a/drivers/platform/x86/amd/pmf/Kconfig
> +++ b/drivers/platform/x86/amd/pmf/Kconfig
> @@ -9,6 +9,7 @@ config AMD_PMF
>  	depends on POWER_SUPPLY
>  	depends on AMD_NB
>  	select ACPI_PLATFORM_PROFILE
> +	depends on AMDTEE
>  	help
>  	  This driver provides support for the AMD Platform Management Framework.
>  	  The goal is to enhance end user experience by making AMD PCs smarter,
> diff --git a/drivers/platform/x86/amd/pmf/acpi.c b/drivers/platform/x86/amd/pmf/acpi.c
> index 3fc5e4547d9f..d0512af2cd42 100644
> --- a/drivers/platform/x86/amd/pmf/acpi.c
> +++ b/drivers/platform/x86/amd/pmf/acpi.c
> @@ -286,6 +286,43 @@ int apmf_install_handler(struct amd_pmf_dev *pmf_dev)
>  	return 0;
>  }
>  
> +static acpi_status apmf_walk_resources(struct acpi_resource *res, void *data)
> +{
> +	struct amd_pmf_dev *dev = data;
> +
> +	switch (res->type) {
> +	case ACPI_RESOURCE_TYPE_ADDRESS64:
> +		dev->policy_addr = res->data.address64.address.minimum;
> +		dev->policy_sz = res->data.address64.address.address_length;
> +		break;
> +	case ACPI_RESOURCE_TYPE_FIXED_MEMORY32:
> +		dev->policy_addr = res->data.fixed_memory32.address;
> +		dev->policy_sz = res->data.fixed_memory32.address_length;
> +		break;
> +	}
> +
> +	if (!dev->policy_addr || dev->policy_sz > POLICY_BUF_MAX_SZ || dev->policy_sz == 0) {
> +		pr_err("Incorrect Policy params, possibly a SBIOS bug\n");
> +		return AE_ERROR;
> +	}
> +
> +	return AE_OK;
> +}
> +
> +int apmf_check_smart_pc(struct amd_pmf_dev *pmf_dev)
> +{
> +	acpi_handle ahandle = ACPI_HANDLE(pmf_dev->dev);
> +	acpi_status status;
> +
> +	status = acpi_walk_resources(ahandle, METHOD_NAME__CRS, apmf_walk_resources, pmf_dev);
> +	if (ACPI_FAILURE(status)) {
> +		dev_err(pmf_dev->dev, "acpi_walk_resources failed\n");
> +		return status;
> +	}
> +
> +	return 0;
> +}
> +
>  void apmf_acpi_deinit(struct amd_pmf_dev *pmf_dev)
>  {
>  	acpi_handle ahandle = ACPI_HANDLE(pmf_dev->dev);
> diff --git a/drivers/platform/x86/amd/pmf/core.c b/drivers/platform/x86/amd/pmf/core.c
> index 5fb03ed614ff..6f36c43e081e 100644
> --- a/drivers/platform/x86/amd/pmf/core.c
> +++ b/drivers/platform/x86/amd/pmf/core.c
> @@ -376,6 +376,18 @@ static int amd_pmf_probe(struct platform_device *pdev)
>  		return -ENOMEM;
>  
>  	dev->dev = &pdev->dev;
> +	err = apmf_check_smart_pc(dev);
> +	if (!err) {
> +		/* in order for Smart PC solution to work it has a hard dependency
> +		 * on the amdtee driver to be loaded first even before the PMF driver
> +		 * loads. PMF ASL has a _CRS method that advertises the existence
> +		 * of Smart PC bit. If this information is present, use this to
> +		 * explicitly probe the amdtee driver, so that "tee" plumbing is done
> +		 * before the PMF Smart PC init happens.
> +		 */
> +		if (request_module("amdtee"))
> +			pr_err("Failed to load amdtee. PMF Smart PC not enabled!\n");
> +	}
>  
>  	rdev = pci_get_domain_bus_and_slot(0, 0, PCI_DEVFN(0, 0));
>  	if (!rdev || !pci_match_id(pmf_pci_ids, rdev)) {
> diff --git a/drivers/platform/x86/amd/pmf/pmf.h b/drivers/platform/x86/amd/pmf/pmf.h
> index ea15ce547d24..81acf2a37366 100644
> --- a/drivers/platform/x86/amd/pmf/pmf.h
> +++ b/drivers/platform/x86/amd/pmf/pmf.h
> @@ -13,6 +13,8 @@
>  
>  #include <linux/acpi.h>
>  #include <linux/platform_profile.h>
> +#define POLICY_BUF_MAX_SZ		0x4b000
> +#define POLICY_SIGN_COOKIE		0x31535024
>  
>  /* APMF Functions */
>  #define APMF_FUNC_VERIFY_INTERFACE			0
> @@ -59,8 +61,20 @@
>  #define ARG_NONE 0
>  #define AVG_SAMPLE_SIZE 3
>  
> +/* Policy Actions */
> +#define PMF_POLICY_SPL						2
> +#define PMF_POLICY_SPPT						3
> +#define PMF_POLICY_FPPT						4
> +#define PMF_POLICY_SPPT_APU_ONLY				5
> +#define PMF_POLICY_STT_MIN					6
> +#define PMF_POLICY_STT_SKINTEMP_APU				7
> +#define PMF_POLICY_STT_SKINTEMP_HS2				8
> +
>  /* TA macros */
>  #define PMF_TA_IF_VERSION__MAJOR				1
> +#define TA_PMF_ACTION_MAX					32
> +#define TA_PMF_UNDO_MAX						8
> +#define MAX_OPERATION_PARAMS					4
>  
>  /* AMD PMF BIOS interfaces */
>  struct apmf_verify_interface {
> @@ -183,11 +197,16 @@ struct amd_pmf_dev {
>  	bool cnqf_supported;
>  	struct notifier_block pwr_src_notifier;
>  	/* Smart PC solution builder */
> +	unsigned char *policy_buf;
> +	u32 policy_sz;
>  	struct tee_context *tee_ctx;
>  	struct tee_shm *fw_shm_pool;
>  	u32 session_id;
>  	void *shbuf;
>  	struct delayed_work pb_work;
> +	struct pmf_action_table *prev_data;
> +	u64 policy_addr;
> +	void *policy_base;
>  	bool smart_pc_enabled;
>  };
>  
> @@ -399,17 +418,129 @@ struct apmf_dyn_slider_output {
>  	struct apmf_cnqf_power_set ps[APMF_CNQF_MAX];
>  } __packed;
>  
> +/* Smart PC - TA internals */
> +enum ta_slider {
> +	TA_BEST_BATTERY, /* Best Battery */
> +	TA_BETTER_BATTERY, /* Better Battery */
> +	TA_BETTER_PERFORMANCE, /* Better Performance */
> +	TA_BEST_PERFORMANCE, /* Best Performance */
> +	TA_MAX,
> +};
> +
>  /* cmd ids for TA communication */
>  enum ta_pmf_command {
>  	TA_PMF_COMMAND_POLICY_BUILDER__INITIALIZE,
>  	TA_PMF_COMMAND_POLICY_BUILDER__ENACT_POLICIES
>  };
>  
> +enum ta_pmf_error_type {
> +	TA_PMF_TYPE__SUCCESS,
> +	TA_PMF_ERROR_TYPE__GENERIC,
> +	TA_PMF_ERROR_TYPE__CRYPTO,
> +	TA_PMF_ERROR_TYPE__CRYPTO_VALIDATE,
> +	TA_PMF_ERROR_TYPE__CRYPTO_VERIFY_OEM,
> +	TA_PMF_ERROR_TYPE__POLICY_BUILDER,
> +	TA_PMF_ERROR_TYPE__PB_CONVERT,
> +	TA_PMF_ERROR_TYPE__PB_SETUP,
> +	TA_PMF_ERROR_TYPE__PB_ENACT,
> +	TA_PMF_ERROR_TYPE__ASD_GET_DEVICE_INFO,
> +	TA_PMF_ERROR_TYPE__ASD_GET_DEVICE_PCIE_INFO,
> +	TA_PMF_ERROR_TYPE__SYS_DRV_FW_VALIDATION,
> +	TA_PMF_ERROR_TYPE__MAX,
> +};
> +
> +struct pmf_action_table {
> +	unsigned long spl; /* in mW */
> +	unsigned long sppt; /* in mW */
> +	unsigned long sppt_apuonly; /* in mW */
> +	unsigned long fppt; /* in mW */
> +	unsigned long stt_minlimit; /* in mW */
> +	unsigned long stt_skintemp_apu; /* in C */
> +	unsigned long stt_skintemp_hs2; /* in C */
> +};
> +
> +/* Input conditions */
> +struct ta_pmf_condition_info {
> +	u32 power_source;
> +	u32 bat_percentage;
> +	u32 power_slider;
> +	u32 lid_state;
> +	bool user_present;
> +	u32 rsvd1[2];
> +	u32 monitor_count;
> +	u32 rsvd2[2];
> +	u32 bat_design;
> +	u32 full_charge_capacity;
> +	int drain_rate;
> +	bool user_engaged;
> +	u32 device_state;
> +	u32 socket_power;
> +	u32 skin_temperature;
> +	u32 rsvd3[5];
> +	u32 ambient_light;
> +	u32 length;
> +	u32 avg_c0residency;
> +	u32 max_c0residency;
> +	u32 s0i3_entry;
> +	u32 gfx_busy;
> +	u32 rsvd4[7];
> +	bool camera_state;
> +	u32 workload_type;
> +	u32 display_type;
> +	u32 display_state;
> +	u32 rsvd5[150];
> +};
> +
> +struct ta_pmf_load_policy_table {
> +	u32 table_size;
> +	u8 table[POLICY_BUF_MAX_SZ];
> +};
> +
> +/* TA initialization params */
> +struct ta_pmf_init_table {
> +	u32 frequency; /* SMU sampling frequency */
> +	bool validate;
> +	bool sku_check;
> +	bool metadata_macrocheck;
> +	struct ta_pmf_load_policy_table policies_table;
> +};
> +
> +/* Everything the TA needs to Enact Policies */
> +struct ta_pmf_enact_table {
> +	struct ta_pmf_condition_info ev_info;
> +	u32 name;
> +};
> +
> +struct ta_pmf_action {
> +	u32 action_index;
> +	u32 value;
> +};
> +
> +/* output actions from TA */
> +struct ta_pmf_enact_result {
> +	u32 actions_count;
> +	struct ta_pmf_action actions_list[TA_PMF_ACTION_MAX];
> +	u32 undo_count;
> +	struct ta_pmf_action undo_list[TA_PMF_UNDO_MAX];
> +};
> +
> +union ta_pmf_input {
> +	struct ta_pmf_enact_table enact_table;
> +	struct ta_pmf_init_table init_table;
> +};
> +
> +union ta_pmf_output {
> +	struct ta_pmf_enact_result policy_apply_table;
> +	u32 rsvd[906];
> +};
> +
>  struct ta_pmf_shared_memory {
>  	int command_id;
>  	int resp_id;
>  	u32 pmf_result;
>  	u32 if_version;
> +	union ta_pmf_output pmf_output;
> +	union ta_pmf_input pmf_input;
>  };
>  
>  /* Core Layer */
> @@ -460,4 +591,5 @@ extern const struct attribute_group cnqf_feature_attribute_group;
>  /* Smart PC builder Layer*/
>  int amd_pmf_init_smart_pc(struct amd_pmf_dev *dev);
>  void amd_pmf_deinit_smart_pc(struct amd_pmf_dev *dev);
> +int apmf_check_smart_pc(struct amd_pmf_dev *pmf_dev);
>  #endif /* PMF_H */
> diff --git a/drivers/platform/x86/amd/pmf/tee-if.c b/drivers/platform/x86/amd/pmf/tee-if.c
> index 1fce04beacb3..a8b05e746efd 100644
> --- a/drivers/platform/x86/amd/pmf/tee-if.c
> +++ b/drivers/platform/x86/amd/pmf/tee-if.c
> @@ -42,9 +42,77 @@ static void amd_pmf_prepare_args(struct amd_pmf_dev *dev, int cmd,
>  	param[0].u.memref.shm_offs = 0;
>  }
>  
> +static void amd_pmf_apply_policies(struct amd_pmf_dev *dev, struct ta_pmf_enact_result *out)
> +{
> +	u32 val;
> +	int idx;
> +
> +	for (idx = 0; idx < out->actions_count; idx++) {
> +		val = out->actions_list[idx].value;
> +		switch (out->actions_list[idx].action_index) {
> +		case PMF_POLICY_SPL:
> +			if (dev->prev_data->spl != val) {
> +				amd_pmf_send_cmd(dev, SET_SPL, false, val, NULL);
> +				dev_dbg(dev->dev, "update SPL : %d\n", val);
> +				dev->prev_data->spl = val;
> +			}
> +			break;
> +
> +		case PMF_POLICY_SPPT:
> +			if (dev->prev_data->sppt != val) {
> +				amd_pmf_send_cmd(dev, SET_SPPT, false, val, NULL);
> +				dev_dbg(dev->dev, "update SPPT : %d\n", val);
> +				dev->prev_data->sppt = val;
> +			}
> +			break;
> +
> +		case PMF_POLICY_FPPT:
> +			if (dev->prev_data->fppt != val) {
> +				amd_pmf_send_cmd(dev, SET_FPPT, false, val, NULL);
> +				dev_dbg(dev->dev, "update FPPT : %d\n", val);
> +				dev->prev_data->fppt = val;
> +			}
> +			break;
> +
> +		case PMF_POLICY_SPPT_APU_ONLY:
> +			if (dev->prev_data->sppt_apuonly != val) {
> +				amd_pmf_send_cmd(dev, SET_SPPT_APU_ONLY, false, val, NULL);
> +				dev_dbg(dev->dev, "update SPPT_APU_ONLY : %d\n", val);
> +				dev->prev_data->sppt_apuonly = val;
> +			}
> +			break;
> +
> +		case PMF_POLICY_STT_MIN:
> +			if (dev->prev_data->stt_minlimit != val) {
> +				amd_pmf_send_cmd(dev, SET_STT_MIN_LIMIT, false, val, NULL);
> +				dev_dbg(dev->dev, "update STT_MIN : %d\n", val);
> +				dev->prev_data->stt_minlimit = val;
> +			}
> +			break;
> +
> +		case PMF_POLICY_STT_SKINTEMP_APU:
> +			if (dev->prev_data->stt_skintemp_apu != val) {
> +				amd_pmf_send_cmd(dev, SET_STT_LIMIT_APU, false, val, NULL);
> +				dev_dbg(dev->dev, "update STT_SKINTEMP_APU : %d\n", val);
> +				dev->prev_data->stt_skintemp_apu = val;
> +			}
> +			break;
> +
> +		case PMF_POLICY_STT_SKINTEMP_HS2:
> +			if (dev->prev_data->stt_skintemp_hs2 != val) {
> +				amd_pmf_send_cmd(dev, SET_STT_LIMIT_HS2, false, val, NULL);
> +				dev_dbg(dev->dev, "update STT_SKINTEMP_HS2 : %d\n", val);
> +				dev->prev_data->stt_skintemp_hs2 = val;
> +			}
> +			break;
> +		}
> +	}
> +}
> +
>  static int amd_pmf_invoke_cmd_enact(struct amd_pmf_dev *dev)
>  {
>  	struct ta_pmf_shared_memory *ta_sm = NULL;
> +	struct ta_pmf_enact_result *out = NULL;
>  	struct tee_param param[MAX_TEE_PARAM];
>  	struct tee_ioctl_invoke_arg arg;
>  	int ret = 0;
> @@ -52,7 +120,10 @@ static int amd_pmf_invoke_cmd_enact(struct amd_pmf_dev *dev)
>  	if (!dev->tee_ctx)
>  		return -ENODEV;
>  
> +	memset(dev->shbuf, 0, dev->policy_sz);
>  	ta_sm = (struct ta_pmf_shared_memory *)dev->shbuf;
> +	out = &ta_sm->pmf_output.policy_apply_table;
> +
>  	memset(ta_sm, 0, sizeof(struct ta_pmf_shared_memory));
>  	ta_sm->command_id = TA_PMF_COMMAND_POLICY_BUILDER__ENACT_POLICIES;
>  	ta_sm->if_version = PMF_TA_IF_VERSION__MAJOR;
> @@ -65,6 +136,12 @@ static int amd_pmf_invoke_cmd_enact(struct amd_pmf_dev *dev)
>  		return -EINVAL;
>  	}
>  
> +	if (ta_sm->pmf_result == TA_PMF_TYPE__SUCCESS && out->actions_count) {
> +		dev_dbg(dev->dev, "action count:%d result:%x\n", out->actions_count,
> +			ta_sm->pmf_result);
> +		amd_pmf_apply_policies(dev, out);
> +	}
> +
>  	return 0;
>  }
>  
> @@ -72,6 +149,7 @@ static int amd_pmf_invoke_cmd_init(struct amd_pmf_dev *dev)
>  {
>  	struct ta_pmf_shared_memory *ta_sm = NULL;
>  	struct tee_param param[MAX_TEE_PARAM];
> +	struct ta_pmf_init_table *in = NULL;
>  	struct tee_ioctl_invoke_arg arg;
>  	int ret = 0;
>  
> @@ -80,10 +158,20 @@ static int amd_pmf_invoke_cmd_init(struct amd_pmf_dev *dev)
>  		return -ENODEV;
>  	}
>  
> +	dev_dbg(dev->dev, "Policy Binary size: %d bytes\n", dev->policy_sz);
> +	memset(dev->shbuf, 0, dev->policy_sz);
>  	ta_sm = (struct ta_pmf_shared_memory *)dev->shbuf;
> +	in = &ta_sm->pmf_input.init_table;
> +
>  	ta_sm->command_id = TA_PMF_COMMAND_POLICY_BUILDER__INITIALIZE;
>  	ta_sm->if_version = PMF_TA_IF_VERSION__MAJOR;
> +	in->metadata_macrocheck = false;
> +	in->sku_check = false;
> +	in->validate = true;
> +	in->frequency = pb_actions_ms;
> +	in->policies_table.table_size = dev->policy_sz;
>  
> +	memcpy(in->policies_table.table, dev->policy_buf, dev->policy_sz);
>  	amd_pmf_prepare_args(dev, TA_PMF_COMMAND_POLICY_BUILDER__INITIALIZE, &arg, param);
>  
>  	ret = tee_client_invoke_func(dev->tee_ctx, &arg, param);
> @@ -103,6 +191,47 @@ static void amd_pmf_invoke_cmd(struct work_struct *work)
>  	schedule_delayed_work(&dev->pb_work, msecs_to_jiffies(pb_actions_ms));
>  }
>  
> +static int amd_pmf_start_policy_engine(struct amd_pmf_dev *dev)
> +{
> +	u32 cookie, length;
> +	int res;
> +
> +	cookie = readl(dev->policy_buf + 0x10);
> +	length = readl(dev->policy_buf + 0x14);

Name the offsets with defines please.

> +
> +	if (cookie != POLICY_SIGN_COOKIE || !length)
> +		return -EINVAL;
> +
> +	/* update the actual length */
> +	dev->policy_sz = length + 512;
> +	res = amd_pmf_invoke_cmd_init(dev);
> +	if (res == TA_PMF_TYPE__SUCCESS) {
> +		/* now its safe to announce that smart pc is enabled */
> +		dev->smart_pc_enabled = 1;
> +		schedule_delayed_work(&dev->pb_work, msecs_to_jiffies(pb_actions_ms * 3));
> +	} else {
> +		dev_err(dev->dev, "%s ta invoke_cmd_init failed err: %x\n", __func__, res);
> +		return res;
> +	}
> +
> +	return 0;
> +}
> +
> +static int amd_pmf_get_bios_buffer(struct amd_pmf_dev *dev)
> +{
> +	dev->policy_buf = kzalloc(dev->policy_sz, GFP_KERNEL);
> +	if (!dev->policy_buf)
> +		return -ENOMEM;
> +
> +	dev->policy_base = ioremap(dev->policy_addr, dev->policy_sz);
> +	if (!dev->policy_base)
> +		return -ENOMEM;

Memleak?

> +	memcpy(dev->policy_buf, dev->policy_base, dev->policy_sz);
> +
> +	return amd_pmf_start_policy_engine(dev);
> +}
> +
>  static int amd_pmf_amdtee_ta_match(struct tee_ioctl_version_data *ver, const void *data)
>  {
>  	return ver->impl_id == TEE_IMPL_ID_AMDTEE;
> @@ -149,7 +278,7 @@ static int amd_pmf_tee_init(struct amd_pmf_dev *dev)
>  		goto out_ctx;
>  	}
>  
> -	size = sizeof(struct ta_pmf_shared_memory);
> +	size = sizeof(struct ta_pmf_shared_memory) + dev->policy_sz;
>  	dev->fw_shm_pool = tee_shm_alloc_kernel_buf(dev->tee_ctx, size);
>  	if (IS_ERR(dev->fw_shm_pool)) {
>  		dev_err(dev->dev, "%s: tee_shm_alloc_kernel_buf failed\n", __func__);
> @@ -191,11 +320,19 @@ int amd_pmf_init_smart_pc(struct amd_pmf_dev *dev)
>  		return ret;
>  
>  	INIT_DELAYED_WORK(&dev->pb_work, amd_pmf_invoke_cmd);
> -	return 0;
> +	amd_pmf_set_dram_addr(dev);
> +	amd_pmf_get_bios_buffer(dev);
> +	dev->prev_data = kzalloc(sizeof(*dev->prev_data), GFP_KERNEL);
> +	if (!dev->prev_data)
> +		return -ENOMEM;
> +
> +	return dev->smart_pc_enabled;
>  }
>  
>  void amd_pmf_deinit_smart_pc(struct amd_pmf_dev *dev)
>  {
> +	kfree(dev->prev_data);
> +	kfree(dev->policy_buf);
>  	cancel_delayed_work_sync(&dev->pb_work);
>  	amd_pmf_tee_deinit(dev);
>  }
> 

-- 
 i.


^ permalink raw reply	[flat|nested] 54+ messages in thread

* Re: [PATCH 06/15] platform/x86/amd/pmf: Add support to get inputs from other subsystems
  2023-09-22 17:50 ` [PATCH 06/15] platform/x86/amd/pmf: Add support to get inputs from other subsystems Shyam Sundar S K
@ 2023-09-26 17:08   ` Ilpo Järvinen
  2023-09-30  8:40     ` Shyam Sundar S K
  0 siblings, 1 reply; 54+ messages in thread
From: Ilpo Järvinen @ 2023-09-26 17:08 UTC (permalink / raw)
  To: Shyam Sundar S K
  Cc: Xinhui.Pan, Patil.Reddy, basavaraj.natikar, dri-devel, jikos,
	amd-gfx, platform-driver-x86, markgross, hdegoede,
	benjamin.tissoires, mario.limonciello, linux-input,
	alexander.deucher, christian.koenig

On Fri, 22 Sep 2023, Shyam Sundar S K wrote:

> PMF driver sends changing inputs from each subystem to TA for evaluating
> the conditions in the policy binary.
> 
> Add initial support of plumbing in the PMF driver for Smart PC to get
> information from other subsystems in the kernel.
> 
> Signed-off-by: Shyam Sundar S K <Shyam-sundar.S-k@amd.com>
> ---
>  drivers/platform/x86/amd/pmf/Makefile |   2 +-
>  drivers/platform/x86/amd/pmf/pmf.h    |  18 ++++
>  drivers/platform/x86/amd/pmf/spc.c    | 118 ++++++++++++++++++++++++++
>  drivers/platform/x86/amd/pmf/tee-if.c |   3 +
>  4 files changed, 140 insertions(+), 1 deletion(-)
>  create mode 100644 drivers/platform/x86/amd/pmf/spc.c
> 
> diff --git a/drivers/platform/x86/amd/pmf/Makefile b/drivers/platform/x86/amd/pmf/Makefile
> index d2746ee7369f..6b26e48ce8ad 100644
> --- a/drivers/platform/x86/amd/pmf/Makefile
> +++ b/drivers/platform/x86/amd/pmf/Makefile
> @@ -7,4 +7,4 @@
>  obj-$(CONFIG_AMD_PMF) += amd-pmf.o
>  amd-pmf-objs := core.o acpi.o sps.o \
>  		auto-mode.o cnqf.o \
> -		tee-if.o
> +		tee-if.o spc.o
> diff --git a/drivers/platform/x86/amd/pmf/pmf.h b/drivers/platform/x86/amd/pmf/pmf.h
> index 81acf2a37366..e64b4d285624 100644
> --- a/drivers/platform/x86/amd/pmf/pmf.h
> +++ b/drivers/platform/x86/amd/pmf/pmf.h
> @@ -146,6 +146,21 @@ struct smu_pmf_metrics {
>  	u16 infra_gfx_maxfreq; /* in MHz */
>  	u16 skin_temp; /* in centi-Celsius */
>  	u16 device_state;
> +	u16 curtemp; /* in centi-Celsius */
> +	u16 filter_alpha_value;
> +	u16 avg_gfx_clkfrequency;
> +	u16 avg_fclk_frequency;
> +	u16 avg_gfx_activity;
> +	u16 avg_socclk_frequency;
> +	u16 avg_vclk_frequency;
> +	u16 avg_vcn_activity;
> +	u16 avg_dram_reads;
> +	u16 avg_dram_writes;
> +	u16 avg_socket_power;
> +	u16 avg_core_power[2];
> +	u16 avg_core_c0residency[16];
> +	u16 spare1;
> +	u32 metrics_counter;
>  } __packed;
>  
>  enum amd_stt_skin_temp {
> @@ -592,4 +607,7 @@ extern const struct attribute_group cnqf_feature_attribute_group;
>  int amd_pmf_init_smart_pc(struct amd_pmf_dev *dev);
>  void amd_pmf_deinit_smart_pc(struct amd_pmf_dev *dev);
>  int apmf_check_smart_pc(struct amd_pmf_dev *pmf_dev);
> +
> +/* Smart PC - TA interfaces */
> +void amd_pmf_populate_ta_inputs(struct amd_pmf_dev *dev, struct ta_pmf_enact_table *in);
>  #endif /* PMF_H */
> diff --git a/drivers/platform/x86/amd/pmf/spc.c b/drivers/platform/x86/amd/pmf/spc.c
> new file mode 100644
> index 000000000000..08159cd5f853
> --- /dev/null
> +++ b/drivers/platform/x86/amd/pmf/spc.c
> @@ -0,0 +1,118 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * AMD Platform Management Framework Driver - Smart PC Capabilities
> + *
> + * Copyright (c) 2023, Advanced Micro Devices, Inc.
> + * All Rights Reserved.
> + *
> + * Authors: Shyam Sundar S K <Shyam-sundar.S-k@amd.com>
> + *          Patil Rajesh Reddy <Patil.Reddy@amd.com>
> + */
> +
> +#include <acpi/button.h>
> +#include <linux/power_supply.h>
> +#include "pmf.h"
> +
> +static void amd_pmf_get_smu_info(struct amd_pmf_dev *dev, struct ta_pmf_enact_table *in)
> +{
> +	u16 max, avg = 0;
> +	int i;
> +
> +	memset(dev->buf, 0, sizeof(dev->m_table));
> +	amd_pmf_send_cmd(dev, SET_TRANSFER_TABLE, 0, 7, NULL);
> +	memcpy(&dev->m_table, dev->buf, sizeof(dev->m_table));
> +
> +	in->ev_info.socket_power = dev->m_table.apu_power + dev->m_table.dgpu_power;
> +	in->ev_info.skin_temperature = dev->m_table.skin_temp;
> +
> +	/* get the avg C0 residency of all the cores */
> +	for (i = 0; i < ARRAY_SIZE(dev->m_table.avg_core_c0residency); i++)
> +		avg += dev->m_table.avg_core_c0residency[i];

Is this safe from overflow?

> +
> +	/* get the max C0 residency of all the cores */
> +	max = dev->m_table.avg_core_c0residency[0];
> +	for (i = 1; i < ARRAY_SIZE(dev->m_table.avg_core_c0residency); i++) {
> +		if (dev->m_table.avg_core_c0residency[i] > max)
> +			max = dev->m_table.avg_core_c0residency[i];
> +	}
> +
> +	in->ev_info.avg_c0residency = avg / ARRAY_SIZE(dev->m_table.avg_core_c0residency);
> +	in->ev_info.max_c0residency = max;
> +	in->ev_info.gfx_busy = dev->m_table.avg_gfx_activity;
> +}
> +
> +static const char * const pmf_battery_supply_name[] = {
> +	"BATT",
> +	"BAT0",
> +};
> +
> +static int get_battery_prop(enum power_supply_property prop)
> +{
> +	union power_supply_propval value;
> +	struct power_supply *psy;
> +	int i, ret = -EINVAL;
> +
> +	for (i = 0; i < ARRAY_SIZE(pmf_battery_supply_name); i++) {
> +		psy = power_supply_get_by_name(pmf_battery_supply_name[i]);
> +		if (!psy)
> +			continue;
> +
> +		ret = power_supply_get_property(psy, prop, &value);
> +		if (ret) {
> +			power_supply_put(psy);
> +			return ret;
> +		}
> +	}
> +
> +	return value.intval;
> +}
> +
> +static int amd_pmf_get_battery_info(struct amd_pmf_dev *dev, struct ta_pmf_enact_table *in)
> +{
> +	int val;
> +
> +	val = get_battery_prop(POWER_SUPPLY_PROP_PRESENT);
> +	if (val != 1)
> +		return -EINVAL;
> +
> +	in->ev_info.bat_percentage = get_battery_prop(POWER_SUPPLY_PROP_CAPACITY);
> +	/* all values in mWh metrics */
> +	in->ev_info.bat_design = get_battery_prop(POWER_SUPPLY_PROP_ENERGY_FULL_DESIGN) / 1000;
> +	in->ev_info.full_charge_capacity = get_battery_prop(POWER_SUPPLY_PROP_ENERGY_FULL) / 1000;
> +	in->ev_info.drain_rate = get_battery_prop(POWER_SUPPLY_PROP_POWER_NOW) / 1000;

You don't need literal, use the defines provided in linux/units.h.

> +
> +	return 0;
> +}
> +
> +static int amd_pmf_get_slider_info(struct amd_pmf_dev *dev, struct ta_pmf_enact_table *in)
> +{
> +	int val;
> +
> +	switch (dev->current_profile) {
> +	case PLATFORM_PROFILE_PERFORMANCE:
> +		val = TA_BEST_PERFORMANCE;
> +		break;
> +	case PLATFORM_PROFILE_BALANCED:
> +		val = TA_BETTER_PERFORMANCE;
> +		break;
> +	case PLATFORM_PROFILE_LOW_POWER:
> +		val = TA_BEST_BATTERY;
> +		break;
> +	default:
> +		dev_err(dev->dev, "Unknown Platform Profile.\n");
> +		return -EOPNOTSUPP;
> +	}
> +	in->ev_info.power_slider = val;
> +
> +	return 0;
> +}
> +
> +void amd_pmf_populate_ta_inputs(struct amd_pmf_dev *dev, struct ta_pmf_enact_table *in)
> +{
> +	/* TA side lid open is 1 and close is 0, hence the ! here */
> +	in->ev_info.lid_state = !acpi_lid_open();
> +	in->ev_info.power_source = amd_pmf_get_power_source();
> +	amd_pmf_get_smu_info(dev, in);
> +	amd_pmf_get_battery_info(dev, in);
> +	amd_pmf_get_slider_info(dev, in);
> +}
> diff --git a/drivers/platform/x86/amd/pmf/tee-if.c b/drivers/platform/x86/amd/pmf/tee-if.c
> index a8b05e746efd..eb25d5ce3a9a 100644
> --- a/drivers/platform/x86/amd/pmf/tee-if.c
> +++ b/drivers/platform/x86/amd/pmf/tee-if.c
> @@ -113,6 +113,7 @@ static int amd_pmf_invoke_cmd_enact(struct amd_pmf_dev *dev)
>  {
>  	struct ta_pmf_shared_memory *ta_sm = NULL;
>  	struct ta_pmf_enact_result *out = NULL;
> +	struct ta_pmf_enact_table *in = NULL;
>  	struct tee_param param[MAX_TEE_PARAM];
>  	struct tee_ioctl_invoke_arg arg;
>  	int ret = 0;
> @@ -123,11 +124,13 @@ static int amd_pmf_invoke_cmd_enact(struct amd_pmf_dev *dev)
>  	memset(dev->shbuf, 0, dev->policy_sz);
>  	ta_sm = (struct ta_pmf_shared_memory *)dev->shbuf;
>  	out = &ta_sm->pmf_output.policy_apply_table;
> +	in = &ta_sm->pmf_input.enact_table;
>  
>  	memset(ta_sm, 0, sizeof(struct ta_pmf_shared_memory));
>  	ta_sm->command_id = TA_PMF_COMMAND_POLICY_BUILDER__ENACT_POLICIES;
>  	ta_sm->if_version = PMF_TA_IF_VERSION__MAJOR;
>  
> +	amd_pmf_populate_ta_inputs(dev, in);
>  	amd_pmf_prepare_args(dev, TA_PMF_COMMAND_POLICY_BUILDER__ENACT_POLICIES, &arg, param);
>  
>  	ret = tee_client_invoke_func(dev->tee_ctx, &arg, param);
> 

-- 
 i.


^ permalink raw reply	[flat|nested] 54+ messages in thread

* Re: [PATCH 04/15] platform/x86/amd/pmf: Add support for PMF Policy Binary
  2023-09-22 17:50 ` [PATCH 04/15] platform/x86/amd/pmf: Add support for PMF Policy Binary Shyam Sundar S K
  2023-09-22 18:51   ` Mario Limonciello
  2023-09-26 17:05   ` Ilpo Järvinen
@ 2023-09-27 12:19   ` Ilpo Järvinen
  2 siblings, 0 replies; 54+ messages in thread
From: Ilpo Järvinen @ 2023-09-27 12:19 UTC (permalink / raw)
  To: Shyam Sundar S K
  Cc: Xinhui.Pan, Patil.Reddy, basavaraj.natikar, dri-devel, jikos,
	amd-gfx, platform-driver-x86, markgross, Hans de Goede,
	benjamin.tissoires, mario.limonciello, linux-input,
	alexander.deucher, christian.koenig

On Fri, 22 Sep 2023, Shyam Sundar S K wrote:

> PMF Policy binary is a encrypted and signed binary that will be part
> of the BIOS. PMF driver via the ACPI interface checks the existence
> of Smart PC bit. If the advertised bit is found, PMF driver walks
> the acpi namespace to find out the policy binary size and the address
> which has to be passed to the TA during the TA init sequence.
> 
> The policy binary is comprised of inputs (or the events) and outputs
> (or the actions). With the PMF ecosystem, OEMs generate the policy
> binary (or could be multiple binaries) that contains a supported set
> of inputs and outputs which could be specifically carved out for each
> usage segment (or for each user also) that could influence the system
> behavior either by enriching the user experience or/and boost/throttle
> power limits.
> 
> Once the TA init command succeeds, the PMF driver sends the changing
> events in the current environment to the TA for a constant sampling
> frequency time (the event here could be a lid close or open) and
> if the policy binary has corresponding action built within it, the
> TA sends the action for it in the subsequent enact command.
> 
> If the inputs sent to the TA has no output defined in the policy
> binary generated by OEMs, there will be no action to be performed
> by the PMF driver.
> 
> Example policies:
> 
> 1) if slider is performance ; set the SPL to 40W
> Here PMF driver registers with the platform profile interface and
> when the slider position is changed, PMF driver lets the TA know
> about this. TA sends back an action to update the Sustained
> Power Limit (SPL). PMF driver updates this limit via the PMFW mailbox.
> 
> 2) if user_away ; then lock the system
> Here PMF driver hooks to the AMD SFH driver to know the user presence
> and send the inputs to TA and if the condition is met, the TA sends
> the action of locking the system. PMF driver generates a uevent and
> based on the udev rule in the userland the system gets locked with
> systemctl.
> 
> The intent here is to provide the OEM's to make a policy to lock the
> system when the user is away ; but the userland can make a choice to
> ignore it.
> 
> and so on.
> 
> The OEMs will have an utility to create numerous such policies and
> the policies shall be reviewed by AMD before signing and encrypting
> them. Policies are shared between operating systems to have seemless user
> experience.
> 
> Since all this action has to happen via the "amdtee" driver, currently
> there is no caller for it in the kernel which can load the amdtee driver.
> Without amdtee driver loading onto the system the "tee" calls shall fail
> from the PMF driver. Hence an explicit "request_module" has been added
> to address this.
> 
> Signed-off-by: Shyam Sundar S K <Shyam-sundar.S-k@amd.com>
> ---

> +struct pmf_action_table {
> +	unsigned long spl; /* in mW */
> +	unsigned long sppt; /* in mW */
> +	unsigned long sppt_apuonly; /* in mW */
> +	unsigned long fppt; /* in mW */
> +	unsigned long stt_minlimit; /* in mW */
> +	unsigned long stt_skintemp_apu; /* in C */
> +	unsigned long stt_skintemp_hs2; /* in C */
> +};

> +static void amd_pmf_apply_policies(struct amd_pmf_dev *dev, struct ta_pmf_enact_result *out)
> +{
> +	u32 val;
> +	int idx;
> +
> +	for (idx = 0; idx < out->actions_count; idx++) {
> +		val = out->actions_list[idx].value;
> +		switch (out->actions_list[idx].action_index) {
> +		case PMF_POLICY_SPL:
> +			if (dev->prev_data->spl != val) {
> +				amd_pmf_send_cmd(dev, SET_SPL, false, val, NULL);
> +				dev_dbg(dev->dev, "update SPL : %d\n", val);

The %d does not match u32.

> +				dev->prev_data->spl = val;

Why is ->spl (and the others too) unsigned long if it's only assigned u32?

> +			}
> +			break;
> +
> +		case PMF_POLICY_SPPT:
> +			if (dev->prev_data->sppt != val) {
> +				amd_pmf_send_cmd(dev, SET_SPPT, false, val, NULL);
> +				dev_dbg(dev->dev, "update SPPT : %d\n", val);
> +				dev->prev_data->sppt = val;
> +			}
> +			break;
> +
> +		case PMF_POLICY_FPPT:
> +			if (dev->prev_data->fppt != val) {
> +				amd_pmf_send_cmd(dev, SET_FPPT, false, val, NULL);
> +				dev_dbg(dev->dev, "update FPPT : %d\n", val);
> +				dev->prev_data->fppt = val;
> +			}
> +			break;
> +
> +		case PMF_POLICY_SPPT_APU_ONLY:
> +			if (dev->prev_data->sppt_apuonly != val) {
> +				amd_pmf_send_cmd(dev, SET_SPPT_APU_ONLY, false, val, NULL);
> +				dev_dbg(dev->dev, "update SPPT_APU_ONLY : %d\n", val);
> +				dev->prev_data->sppt_apuonly = val;
> +			}
> +			break;
> +
> +		case PMF_POLICY_STT_MIN:
> +			if (dev->prev_data->stt_minlimit != val) {
> +				amd_pmf_send_cmd(dev, SET_STT_MIN_LIMIT, false, val, NULL);
> +				dev_dbg(dev->dev, "update STT_MIN : %d\n", val);
> +				dev->prev_data->stt_minlimit = val;
> +			}
> +			break;
> +
> +		case PMF_POLICY_STT_SKINTEMP_APU:
> +			if (dev->prev_data->stt_skintemp_apu != val) {
> +				amd_pmf_send_cmd(dev, SET_STT_LIMIT_APU, false, val, NULL);
> +				dev_dbg(dev->dev, "update STT_SKINTEMP_APU : %d\n", val);
> +				dev->prev_data->stt_skintemp_apu = val;
> +			}
> +			break;
> +
> +		case PMF_POLICY_STT_SKINTEMP_HS2:
> +			if (dev->prev_data->stt_skintemp_hs2 != val) {
> +				amd_pmf_send_cmd(dev, SET_STT_LIMIT_HS2, false, val, NULL);
> +				dev_dbg(dev->dev, "update STT_SKINTEMP_HS2 : %d\n", val);
> +				dev->prev_data->stt_skintemp_hs2 = val;
> +			}
> +			break;
> +		}
> +	}
> +}
> +


-- 
 i.


^ permalink raw reply	[flat|nested] 54+ messages in thread

* Re: [PATCH 07/15] platform/x86/amd/pmf: Add support update p3t limit
  2023-09-22 17:50 ` [PATCH 07/15] platform/x86/amd/pmf: Add support update p3t limit Shyam Sundar S K
@ 2023-09-27 12:19   ` Ilpo Järvinen
  0 siblings, 0 replies; 54+ messages in thread
From: Ilpo Järvinen @ 2023-09-27 12:19 UTC (permalink / raw)
  To: Shyam Sundar S K
  Cc: Xinhui.Pan, Patil.Reddy, basavaraj.natikar, dri-devel, jikos,
	amd-gfx, platform-driver-x86, markgross, hdegoede,
	benjamin.tissoires, mario.limonciello, linux-input,
	alexander.deucher, christian.koenig

On Fri, 22 Sep 2023, Shyam Sundar S K wrote:

> P3T (Peak Package Power Limit) is a metric within the SMU controller
> that can influence the power limits. Add support from the driver
> to update P3T limits accordingly.
> 
> Reviewed-by: Mario Limonciello <mario.limonciello@amd.com>
> Signed-off-by: Shyam Sundar S K <Shyam-sundar.S-k@amd.com>
> ---
>  drivers/platform/x86/amd/pmf/pmf.h    | 3 +++
>  drivers/platform/x86/amd/pmf/tee-if.c | 8 ++++++++
>  2 files changed, 11 insertions(+)
> 
> diff --git a/drivers/platform/x86/amd/pmf/pmf.h b/drivers/platform/x86/amd/pmf/pmf.h
> index e64b4d285624..897f61b75e2f 100644
> --- a/drivers/platform/x86/amd/pmf/pmf.h
> +++ b/drivers/platform/x86/amd/pmf/pmf.h
> @@ -46,6 +46,7 @@
>  #define GET_STT_MIN_LIMIT	0x1F
>  #define GET_STT_LIMIT_APU	0x20
>  #define GET_STT_LIMIT_HS2	0x21
> +#define SET_P3T				0x23 /* P3T: Peak Package Power Limit */
>  
>  /* OS slider update notification */
>  #define DC_BEST_PERF		0
> @@ -69,6 +70,7 @@
>  #define PMF_POLICY_STT_MIN					6
>  #define PMF_POLICY_STT_SKINTEMP_APU				7
>  #define PMF_POLICY_STT_SKINTEMP_HS2				8
> +#define PMF_POLICY_P3T						38
>  
>  /* TA macros */
>  #define PMF_TA_IF_VERSION__MAJOR				1
> @@ -472,6 +474,7 @@ struct pmf_action_table {
>  	unsigned long stt_minlimit; /* in mW */
>  	unsigned long stt_skintemp_apu; /* in C */
>  	unsigned long stt_skintemp_hs2; /* in C */
> +	unsigned long p3t_limit; /* in mW */
>  };
>  
>  /* Input conditions */
> diff --git a/drivers/platform/x86/amd/pmf/tee-if.c b/drivers/platform/x86/amd/pmf/tee-if.c
> index eb25d5ce3a9a..883dd143375a 100644
> --- a/drivers/platform/x86/amd/pmf/tee-if.c
> +++ b/drivers/platform/x86/amd/pmf/tee-if.c
> @@ -105,6 +105,14 @@ static void amd_pmf_apply_policies(struct amd_pmf_dev *dev, struct ta_pmf_enact_
>  				dev->prev_data->stt_skintemp_hs2 = val;
>  			}
>  			break;
> +
> +		case PMF_POLICY_P3T:
> +			if (dev->prev_data->p3t_limit != val) {
> +				amd_pmf_send_cmd(dev, SET_P3T, false, val, NULL);
> +				dev_dbg(dev->dev, "update P3T : %d\n", val);

%d vs u32

> +				dev->prev_data->p3t_limit = val;

unsigned long vs u32 ? (as in the other patch)


-- 
 i.


^ permalink raw reply	[flat|nested] 54+ messages in thread

* Re: [PATCH 08/15] platform/x86/amd/pmf: Add support to update system state
  2023-09-22 17:50 ` [PATCH 08/15] platform/x86/amd/pmf: Add support to update system state Shyam Sundar S K
  2023-09-25 21:42   ` kernel test robot
@ 2023-09-27 12:22   ` Ilpo Järvinen
  1 sibling, 0 replies; 54+ messages in thread
From: Ilpo Järvinen @ 2023-09-27 12:22 UTC (permalink / raw)
  To: Shyam Sundar S K
  Cc: Xinhui.Pan, Patil.Reddy, basavaraj.natikar, dri-devel, jikos,
	amd-gfx, platform-driver-x86, markgross, Hans de Goede,
	benjamin.tissoires, mario.limonciello, linux-input,
	alexander.deucher, christian.koenig

On Fri, 22 Sep 2023, Shyam Sundar S K wrote:

> PMF driver based on the output actions from the TA can request to update
> the system states like entering s0i3, lock screen etc. by generating
> an uevent. Based on the udev rules set in the userspace the event id
> matching the uevent shall get updated accordingly using the systemctl.
> 
> Sample udev rules under Documentation/admin-guide/pmf.rst.
> 
> Signed-off-by: Shyam Sundar S K <Shyam-sundar.S-k@amd.com>
> ---
>  Documentation/admin-guide/pmf.rst     | 24 ++++++++++++++++
>  drivers/platform/x86/amd/pmf/pmf.h    |  9 ++++++
>  drivers/platform/x86/amd/pmf/tee-if.c | 40 ++++++++++++++++++++++++++-
>  3 files changed, 72 insertions(+), 1 deletion(-)
>  create mode 100644 Documentation/admin-guide/pmf.rst
> 
> diff --git a/Documentation/admin-guide/pmf.rst b/Documentation/admin-guide/pmf.rst
> new file mode 100644
> index 000000000000..b60f381410c3
> --- /dev/null
> +++ b/Documentation/admin-guide/pmf.rst
> @@ -0,0 +1,24 @@
> +.. SPDX-License-Identifier: GPL-2.0
> +
> +Set udev rules for PMF Smart PC Builder
> +---------------------------------------
> +
> +AMD PMF(Platform Management Framework) Smart PC Solution builder has to set the system states
> +like S0i3, Screen lock, hibernate etc, based on the output actions provided by the PMF
> +TA (Trusted Application).
> +
> +In order for this to work the PMF driver generates a uevent for userspace to react to. Below are
> +sample udev rules that can facilitate this experience when a machine has PMF Smart PC solution builder
> +enabled.
> +
> +Please add the following line(s) to
> +``/etc/udev/rules.d/99-local.rules``::
> +        DRIVERS=="amd-pmf", ACTION=="change", ENV{EVENT_ID}=="1", RUN+="/usr/bin/systemctl suspend"
> +        DRIVERS=="amd-pmf", ACTION=="change", ENV{EVENT_ID}=="2", RUN+="/usr/bin/systemctl hibernate"
> +        DRIVERS=="amd-pmf", ACTION=="change", ENV{EVENT_ID}=="3", RUN+="/bin/loginctl lock-sessions"
> +
> +EVENT_ID values:
> +1= Put the system to S0i3/S2Idle
> +2= Put the system to hibernate
> +3= Lock the screen
> +
> diff --git a/drivers/platform/x86/amd/pmf/pmf.h b/drivers/platform/x86/amd/pmf/pmf.h
> index 897f61b75e2f..c5334f1177a4 100644
> --- a/drivers/platform/x86/amd/pmf/pmf.h
> +++ b/drivers/platform/x86/amd/pmf/pmf.h
> @@ -70,6 +70,7 @@
>  #define PMF_POLICY_STT_MIN					6
>  #define PMF_POLICY_STT_SKINTEMP_APU				7
>  #define PMF_POLICY_STT_SKINTEMP_HS2				8
> +#define PMF_POLICY_SYSTEM_STATE					9
>  #define PMF_POLICY_P3T						38
>  
>  /* TA macros */
> @@ -436,6 +437,13 @@ struct apmf_dyn_slider_output {
>  } __packed;
>  
>  /* Smart PC - TA internals */
> +enum system_state {
> +	SYSTEM_STATE__S0i3 = 1,
> +	SYSTEM_STATE__S4,
> +	SYSTEM_STATE__SCREEN_LOCK,
> +	SYSTEM_STATE__MAX
> +};
> +
>  enum ta_slider {
>  	TA_BEST_BATTERY, /* Best Battery */
>  	TA_BETTER_BATTERY, /* Better Battery */
> @@ -467,6 +475,7 @@ enum ta_pmf_error_type {
>  };
>  
>  struct pmf_action_table {
> +	enum system_state system_state;
>  	unsigned long spl; /* in mW */
>  	unsigned long sppt; /* in mW */
>  	unsigned long sppt_apuonly; /* in mW */
> diff --git a/drivers/platform/x86/amd/pmf/tee-if.c b/drivers/platform/x86/amd/pmf/tee-if.c
> index 883dd143375a..1629856c20b4 100644
> --- a/drivers/platform/x86/amd/pmf/tee-if.c
> +++ b/drivers/platform/x86/amd/pmf/tee-if.c
> @@ -24,6 +24,20 @@ MODULE_PARM_DESC(pb_actions_ms, "Policy binary actions sampling frequency (defau
>  static const uuid_t amd_pmf_ta_uuid = UUID_INIT(0x6fd93b77, 0x3fb8, 0x524d,
>  						0xb1, 0x2d, 0xc5, 0x29, 0xb1, 0x3d, 0x85, 0x43);
>  
> +static const char *amd_pmf_uevent_as_str(unsigned int state)
> +{
> +	switch (state) {
> +	case SYSTEM_STATE__S0i3:
> +		return "S0i3";
> +	case SYSTEM_STATE__S4:
> +		return "S4";
> +	case SYSTEM_STATE__SCREEN_LOCK:
> +		return "SCREEN_LOCK";
> +	default:
> +		return "Unknown Smart PC event";
> +	}
> +}
> +
>  static void amd_pmf_prepare_args(struct amd_pmf_dev *dev, int cmd,
>  				 struct tee_ioctl_invoke_arg *arg,
>  				 struct tee_param *param)
> @@ -42,9 +56,23 @@ static void amd_pmf_prepare_args(struct amd_pmf_dev *dev, int cmd,
>  	param[0].u.memref.shm_offs = 0;
>  }
>  
> +static int amd_pmf_update_uevents(struct amd_pmf_dev *dev, u16 event)
> +{
> +	char *envp[2] = {};
> +
> +	envp[0] = kasprintf(GFP_KERNEL, "EVENT_ID=%d", event);
> +	if (!envp[0])
> +		return -EINVAL;
> +
> +	kobject_uevent_env(&dev->dev->kobj, KOBJ_CHANGE, envp);
> +
> +	kfree(envp[0]);
> +	return 0;
> +}
> +
>  static void amd_pmf_apply_policies(struct amd_pmf_dev *dev, struct ta_pmf_enact_result *out)
>  {
> -	u32 val;
> +	u32 val, event = 0;
>  	int idx;
>  
>  	for (idx = 0; idx < out->actions_count; idx++) {
> @@ -113,6 +141,16 @@ static void amd_pmf_apply_policies(struct amd_pmf_dev *dev, struct ta_pmf_enact_
>  				dev->prev_data->p3t_limit = val;
>  			}
>  			break;
> +
> +		case PMF_POLICY_SYSTEM_STATE:
> +			event = val + 1;
> +			if (dev->prev_data->system_state != event) {
> +				amd_pmf_update_uevents(dev, event);
> +				dev_dbg(dev->dev, "update SYSTEM_STATE : %s\n",
> +					amd_pmf_uevent_as_str(event));
> +				dev->prev_data->system_state = 0;

Is it intentional to assign 0 here? If it is, it makes 
prev_data->system_state pretty useless?

> +			}
> +			break;
>  		}
>  	}
>  }
> 

-- 
 i.


^ permalink raw reply	[flat|nested] 54+ messages in thread

* Re: [PATCH 09/15] platform/x86/amd/pmf: Add facility to dump TA inputs
  2023-09-22 17:50 ` [PATCH 09/15] platform/x86/amd/pmf: Add facility to dump TA inputs Shyam Sundar S K
@ 2023-09-27 12:25   ` Ilpo Järvinen
  0 siblings, 0 replies; 54+ messages in thread
From: Ilpo Järvinen @ 2023-09-27 12:25 UTC (permalink / raw)
  To: Shyam Sundar S K
  Cc: Xinhui.Pan, Patil.Reddy, basavaraj.natikar, dri-devel, jikos,
	amd-gfx, platform-driver-x86, markgross, hdegoede,
	benjamin.tissoires, mario.limonciello, linux-input,
	alexander.deucher, christian.koenig

On Fri, 22 Sep 2023, Shyam Sundar S K wrote:

> PMF driver sends constant inputs to TA which its gets via the other
> subsystems in the kernel. To debug certain TA issues knowing what inputs
> being sent to TA becomes critical. Add debug facility to the driver which
> can isolate Smart PC and TA related issues.
> 
> Reviewed-by: Mario Limonciello <mario.limonciello@amd.com>
> Signed-off-by: Shyam Sundar S K <Shyam-sundar.S-k@amd.com>
> ---
>  drivers/platform/x86/amd/pmf/pmf.h    |  3 +++
>  drivers/platform/x86/amd/pmf/spc.c    | 37 +++++++++++++++++++++++++++
>  drivers/platform/x86/amd/pmf/sps.c    |  2 +-
>  drivers/platform/x86/amd/pmf/tee-if.c |  1 +
>  4 files changed, 42 insertions(+), 1 deletion(-)
> 
> diff --git a/drivers/platform/x86/amd/pmf/pmf.h b/drivers/platform/x86/amd/pmf/pmf.h
> index c5334f1177a4..61a0f3225b62 100644
> --- a/drivers/platform/x86/amd/pmf/pmf.h
> +++ b/drivers/platform/x86/amd/pmf/pmf.h
> @@ -592,6 +592,7 @@ int apmf_get_static_slider_granular(struct amd_pmf_dev *pdev,
>  bool is_pprof_balanced(struct amd_pmf_dev *pmf);
>  int amd_pmf_power_slider_update_event(struct amd_pmf_dev *dev);
>  
> +const char *source_as_str(unsigned int state);
>  
>  int apmf_update_fan_idx(struct amd_pmf_dev *pdev, bool manual, u32 idx);
>  int amd_pmf_set_sps_power_limits(struct amd_pmf_dev *pmf);
> @@ -622,4 +623,6 @@ int apmf_check_smart_pc(struct amd_pmf_dev *pmf_dev);
>  
>  /* Smart PC - TA interfaces */
>  void amd_pmf_populate_ta_inputs(struct amd_pmf_dev *dev, struct ta_pmf_enact_table *in);
> +void amd_pmf_dump_ta_inputs(struct amd_pmf_dev *dev, struct ta_pmf_enact_table *in);
> +
>  #endif /* PMF_H */
> diff --git a/drivers/platform/x86/amd/pmf/spc.c b/drivers/platform/x86/amd/pmf/spc.c
> index 08159cd5f853..5c6745f56ed1 100644
> --- a/drivers/platform/x86/amd/pmf/spc.c
> +++ b/drivers/platform/x86/amd/pmf/spc.c
> @@ -13,6 +13,43 @@
>  #include <linux/power_supply.h>
>  #include "pmf.h"
>  
> +#ifdef CONFIG_AMD_PMF_DEBUG
> +static const char *ta_slider_as_str(unsigned int state)
> +{
> +	switch (state) {
> +	case TA_BEST_PERFORMANCE:
> +		return "PERFORMANCE";
> +	case TA_BETTER_PERFORMANCE:
> +		return "BALANCED";
> +	case TA_BEST_BATTERY:
> +		return "POWER_SAVER";
> +	default:
> +		return "Unknown TA Slider State";
> +	}
> +}
> +
> +void amd_pmf_dump_ta_inputs(struct amd_pmf_dev *dev, struct ta_pmf_enact_table *in)
> +{
> +	dev_dbg(dev->dev, "==== TA inputs START ====\n");
> +	dev_dbg(dev->dev, "Slider State : %s\n", ta_slider_as_str(in->ev_info.power_slider));
> +	dev_dbg(dev->dev, "Power Source : %s\n", source_as_str(in->ev_info.power_source));
> +	dev_dbg(dev->dev, "Battery Percentage : %d\n", in->ev_info.bat_percentage);
> +	dev_dbg(dev->dev, "Designed Battery Capacity : %d\n", in->ev_info.bat_design);
> +	dev_dbg(dev->dev, "Fully Charged Capacity : %d\n", in->ev_info.full_charge_capacity);
> +	dev_dbg(dev->dev, "Drain Rate : %d\n", in->ev_info.drain_rate);
> +	dev_dbg(dev->dev, "Socket Power : %d\n", in->ev_info.socket_power);
> +	dev_dbg(dev->dev, "Skin Temperature : %d\n", in->ev_info.skin_temperature);
> +	dev_dbg(dev->dev, "Avg C0 Residency : %d\n", in->ev_info.avg_c0residency);
> +	dev_dbg(dev->dev, "Max C0 Residency : %d\n", in->ev_info.max_c0residency);
> +	dev_dbg(dev->dev, "GFX Busy : %d\n", in->ev_info.gfx_busy);
> +	dev_dbg(dev->dev, "Connected Display Count : %d\n", in->ev_info.monitor_count);
> +	dev_dbg(dev->dev, "LID State : %s\n", in->ev_info.lid_state ? "Close" : "Open");
> +	dev_dbg(dev->dev, "==== TA inputs END ====\n");

Again, the printf format specifiers are wrong, shouldn't the compiler warn 
about them?

> +}
> +#else
> +void amd_pmf_dump_ta_inputs(struct amd_pmf_dev *dev, struct ta_pmf_enact_table *in) {}
> +#endif
> +
>  static void amd_pmf_get_smu_info(struct amd_pmf_dev *dev, struct ta_pmf_enact_table *in)
>  {
>  	u16 max, avg = 0;
> diff --git a/drivers/platform/x86/amd/pmf/sps.c b/drivers/platform/x86/amd/pmf/sps.c
> index a70e67749be3..13e36b52dfe8 100644
> --- a/drivers/platform/x86/amd/pmf/sps.c
> +++ b/drivers/platform/x86/amd/pmf/sps.c
> @@ -27,7 +27,7 @@ static const char *slider_as_str(unsigned int state)
>  	}
>  }
>  
> -static const char *source_as_str(unsigned int state)
> +const char *source_as_str(unsigned int state)
>  {
>  	switch (state) {
>  	case POWER_SOURCE_AC:
> diff --git a/drivers/platform/x86/amd/pmf/tee-if.c b/drivers/platform/x86/amd/pmf/tee-if.c
> index 1629856c20b4..4844782d93c7 100644
> --- a/drivers/platform/x86/amd/pmf/tee-if.c
> +++ b/drivers/platform/x86/amd/pmf/tee-if.c
> @@ -186,6 +186,7 @@ static int amd_pmf_invoke_cmd_enact(struct amd_pmf_dev *dev)
>  	}
>  
>  	if (ta_sm->pmf_result == TA_PMF_TYPE__SUCCESS && out->actions_count) {
> +		amd_pmf_dump_ta_inputs(dev, in);
>  		dev_dbg(dev->dev, "action count:%d result:%x\n", out->actions_count,
>  			ta_sm->pmf_result);
>  		amd_pmf_apply_policies(dev, out);
> 

-- 
 i.


^ permalink raw reply	[flat|nested] 54+ messages in thread

* Re: [PATCH 10/15] platform/x86/amd/pmf: Add capability to sideload of policy binary
  2023-09-22 17:50 ` [PATCH 10/15] platform/x86/amd/pmf: Add capability to sideload of policy binary Shyam Sundar S K
  2023-09-25  2:14   ` kernel test robot
@ 2023-09-27 12:33   ` Ilpo Järvinen
  1 sibling, 0 replies; 54+ messages in thread
From: Ilpo Järvinen @ 2023-09-27 12:33 UTC (permalink / raw)
  To: Shyam Sundar S K
  Cc: Xinhui.Pan, Patil.Reddy, basavaraj.natikar, dri-devel, jikos,
	amd-gfx, platform-driver-x86, markgross, hdegoede,
	benjamin.tissoires, mario.limonciello, linux-input,
	alexander.deucher, christian.koenig

On Fri, 22 Sep 2023, Shyam Sundar S K wrote:

> A policy binary is OS agnostic, and the same policies are expected to work
> across the OSes.  At times it becomes difficult to debug when the policies
> inside the policy binaries starts to misbehave. Add a way to sideload such
> policies independently to debug them via a debugfs entry.
> 
> Reviewed-by: Mario Limonciello <mario.limonciello@amd.com>
> Signed-off-by: Shyam Sundar S K <Shyam-sundar.S-k@amd.com>
> ---
>  drivers/platform/x86/amd/pmf/pmf.h    |  1 +
>  drivers/platform/x86/amd/pmf/tee-if.c | 60 +++++++++++++++++++++++++++
>  2 files changed, 61 insertions(+)
> 
> diff --git a/drivers/platform/x86/amd/pmf/pmf.h b/drivers/platform/x86/amd/pmf/pmf.h
> index 61a0f3225b62..780c442239e3 100644
> --- a/drivers/platform/x86/amd/pmf/pmf.h
> +++ b/drivers/platform/x86/amd/pmf/pmf.h
> @@ -215,6 +215,7 @@ struct amd_pmf_dev {
>  	bool cnqf_supported;
>  	struct notifier_block pwr_src_notifier;
>  	/* Smart PC solution builder */
> +	struct dentry *esbin;
>  	unsigned char *policy_buf;
>  	u32 policy_sz;
>  	struct tee_context *tee_ctx;
> diff --git a/drivers/platform/x86/amd/pmf/tee-if.c b/drivers/platform/x86/amd/pmf/tee-if.c
> index 4844782d93c7..fa37cfab2dc7 100644
> --- a/drivers/platform/x86/amd/pmf/tee-if.c
> +++ b/drivers/platform/x86/amd/pmf/tee-if.c
> @@ -8,6 +8,7 @@
>   * Author: Shyam Sundar S K <Shyam-sundar.S-k@amd.com>
>   */
>  
> +#include <linux/debugfs.h>
>  #include <linux/tee_drv.h>
>  #include <linux/uuid.h>
>  #include "pmf.h"
> @@ -21,6 +22,13 @@ module_param(pb_actions_ms, int, 0644);
>  MODULE_PARM_DESC(pb_actions_ms, "Policy binary actions sampling frequency (default = 1000ms)");
>  #endif
>  
> +#ifdef CONFIG_AMD_PMF_DEBUG
> +/* Sideload policy binaries to debug policy failures */
> +static bool pb_side_load;
> +module_param(pb_side_load, bool, 0444);
> +MODULE_PARM_DESC(pb_side_load, "Sideload policy binaries debug policy failures");
> +#endif
> +
>  static const uuid_t amd_pmf_ta_uuid = UUID_INIT(0x6fd93b77, 0x3fb8, 0x524d,
>  						0xb1, 0x2d, 0xc5, 0x29, 0xb1, 0x3d, 0x85, 0x43);
>  
> @@ -267,6 +275,49 @@ static int amd_pmf_start_policy_engine(struct amd_pmf_dev *dev)
>  	return 0;
>  }
>  
> +#ifdef CONFIG_AMD_PMF_DEBUG
> +static ssize_t amd_pmf_get_pb_data(struct file *filp, const char __user *buf,
> +				   size_t length, loff_t *pos)
> +{
> +	struct amd_pmf_dev *dev = filp->private_data;
> +	int ret;
> +
> +	/* policy binary size cannot exceed POLICY_BUF_MAX_SZ */
> +	if (length > POLICY_BUF_MAX_SZ || length == 0)
> +		return -EINVAL;
> +
> +	dev->policy_sz = length;
> +	if (copy_from_user(dev->policy_buf, buf, dev->policy_sz))
> +		return -EFAULT;
> +
> +	ret = amd_pmf_start_policy_engine(dev);
> +	if (ret)
> +		return -EINVAL;
> +
> +	return length;
> +}
> +
> +static const struct file_operations pb_fops = {
> +	.write = amd_pmf_get_pb_data,
> +	.open = simple_open,
> +};
> +
> +int amd_pmf_open_pb(struct amd_pmf_dev *dev, struct dentry *debugfs_root)
> +{
> +	struct dentry *file = NULL;
> +
> +	dev->esbin = debugfs_create_dir("pb", debugfs_root);
> +	if (IS_ERR(dev->esbin))
> +		return -EINVAL;
> +
> +	file = debugfs_create_file("update_policy", 0644, dev->esbin, dev, &pb_fops);
> +	if (!file)
> +		return -EINVAL;
> +
> +	return 0;
> +}
> +#endif
> +
>  static int amd_pmf_get_bios_buffer(struct amd_pmf_dev *dev)
>  {
>  	dev->policy_buf = kzalloc(dev->policy_sz, GFP_KERNEL);
> @@ -279,6 +330,11 @@ static int amd_pmf_get_bios_buffer(struct amd_pmf_dev *dev)
>  
>  	memcpy(dev->policy_buf, dev->policy_base, dev->policy_sz);
>  
> +#ifdef CONFIG_AMD_PMF_DEBUG
> +	if (pb_side_load)

Can't this go into amd_pmf_open_pb() as early return?

> +		amd_pmf_open_pb(dev, dev->dbgfs_dir);

If you provide #else and empty amd_pmf_open_pb() above, you don't need to 
do ifdefs here.

> +#endif
> +
>  	return amd_pmf_start_policy_engine(dev);
>  }
>  
> @@ -381,6 +437,10 @@ int amd_pmf_init_smart_pc(struct amd_pmf_dev *dev)
>  
>  void amd_pmf_deinit_smart_pc(struct amd_pmf_dev *dev)
>  {
> +#ifdef CONFIG_AMD_PMF_DEBUG
> +	if (pb_side_load)
> +		debugfs_remove_recursive(dev->esbin);
> +#endif

Likewise here, if you add amd_pmf_remove_pb() into the above #ifdef + new 
#else block with empty body, you can just call it w/o #ifdefs here.

>  	kfree(dev->prev_data);
>  	kfree(dev->policy_buf);
>  	cancel_delayed_work_sync(&dev->pb_work);
> 

-- 
 i.


^ permalink raw reply	[flat|nested] 54+ messages in thread

* Re: [PATCH 12/15] platform/x86/amd/pmf: Add PMF-AMDGPU get interface
  2023-09-22 17:50 ` [PATCH 12/15] platform/x86/amd/pmf: Add PMF-AMDGPU get interface Shyam Sundar S K
@ 2023-09-27 12:54   ` Ilpo Järvinen
  0 siblings, 0 replies; 54+ messages in thread
From: Ilpo Järvinen @ 2023-09-27 12:54 UTC (permalink / raw)
  To: Shyam Sundar S K
  Cc: Xinhui.Pan, Patil.Reddy, basavaraj.natikar, dri-devel, jikos,
	amd-gfx, platform-driver-x86, markgross, Hans de Goede,
	benjamin.tissoires, mario.limonciello, linux-input,
	alexander.deucher, christian.koenig

On Fri, 22 Sep 2023, Shyam Sundar S K wrote:

> In order to provide GPU inputs to TA for the Smart PC solution to work, we
> need to have interface between the PMF driver and the AMDGPU driver.
> 
> Add the initial code path for get interface from AMDGPU.
> 
> Co-developed-by: Mario Limonciello <mario.limonciello@amd.com>
> Signed-off-by: Mario Limonciello <mario.limonciello@amd.com>
> Signed-off-by: Shyam Sundar S K <Shyam-sundar.S-k@amd.com>
> ---
>  drivers/gpu/drm/amd/amdgpu/Makefile     |  2 +
>  drivers/gpu/drm/amd/amdgpu/amdgpu.h     |  1 +
>  drivers/gpu/drm/amd/amdgpu/amdgpu_pmf.c | 70 +++++++++++++++++++++++++
>  drivers/platform/x86/amd/pmf/Kconfig    |  1 +
>  drivers/platform/x86/amd/pmf/core.c     |  1 +
>  drivers/platform/x86/amd/pmf/pmf.h      |  4 ++
>  drivers/platform/x86/amd/pmf/spc.c      | 13 +++++
>  drivers/platform/x86/amd/pmf/tee-if.c   | 22 ++++++++
>  include/linux/amd-pmf-io.h              | 28 ++++++++++
>  9 files changed, 142 insertions(+)
>  create mode 100644 drivers/gpu/drm/amd/amdgpu/amdgpu_pmf.c
>  create mode 100644 include/linux/amd-pmf-io.h
> 
> diff --git a/drivers/gpu/drm/amd/amdgpu/Makefile b/drivers/gpu/drm/amd/amdgpu/Makefile
> index 384b798a9bad..7fafccefbd7a 100644
> --- a/drivers/gpu/drm/amd/amdgpu/Makefile
> +++ b/drivers/gpu/drm/amd/amdgpu/Makefile
> @@ -86,6 +86,8 @@ amdgpu-$(CONFIG_PROC_FS) += amdgpu_fdinfo.o
>  
>  amdgpu-$(CONFIG_PERF_EVENTS) += amdgpu_pmu.o
>  
> +amdgpu-$(CONFIG_AMD_PMF) += amdgpu_pmf.o
> +
>  # add asic specific block
>  amdgpu-$(CONFIG_DRM_AMDGPU_CIK)+= cik.o cik_ih.o \
>  	dce_v8_0.o gfx_v7_0.o cik_sdma.o uvd_v4_2.o vce_v2_0.o
> diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu.h b/drivers/gpu/drm/amd/amdgpu/amdgpu.h
> index dc2d53081e80..475f3e248f35 100644
> --- a/drivers/gpu/drm/amd/amdgpu/amdgpu.h
> +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu.h
> @@ -50,6 +50,7 @@
>  #include <linux/hashtable.h>
>  #include <linux/dma-fence.h>
>  #include <linux/pci.h>
> +#include <linux/amd-pmf-io.h>
>  
>  #include <drm/ttm/ttm_bo.h>
>  #include <drm/ttm/ttm_placement.h>
> diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_pmf.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_pmf.c
> new file mode 100644
> index 000000000000..232d11833ddc
> --- /dev/null
> +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_pmf.c
> @@ -0,0 +1,70 @@
> +/*
> + * Copyright 2023 Advanced Micro Devices, Inc.
> + *
> + * Permission is hereby granted, free of charge, to any person obtaining a
> + * copy of this software and associated documentation files (the "Software"),
> + * to deal in the Software without restriction, including without limitation
> + * the rights to use, copy, modify, merge, publish, distribute, sublicense,
> + * and/or sell copies of the Software, and to permit persons to whom the
> + * Software is furnished to do so, subject to the following conditions:
> + *
> + * The above copyright notice and this permission notice shall be included in
> + * all copies or substantial portions of the Software.
> + *
> + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
> + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
> + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
> + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
> + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
> + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
> + * OTHER DEALINGS IN THE SOFTWARE.
> +
> + * * Author: Shyam Sundar S K <Shyam-sundar.S-k@amd.com>
> + */
> +
> +#include <linux/backlight.h>
> +#include "amdgpu.h"
> +
> +int amd_pmf_get_gfx_data(struct amd_gpu_pmf_data *pmf)
> +{
> +	struct drm_device *drm_dev = pci_get_drvdata(pmf->gpu_dev);
> +	struct drm_mode_config *mode_config = &drm_dev->mode_config;
> +	struct amdgpu_device *adev = drm_to_adev(drm_dev);
> +	struct drm_connector_list_iter iter;
> +	struct drm_connector *connector;
> +	struct backlight_device *bd;
> +	int i = 0;
> +
> +	/* reset the count to zero */
> +	pmf->display_count = 0;
> +	if (!(adev->flags & AMD_IS_APU)) {
> +		DRM_ERROR("PMF-AMDGPU interface not supported\n");
> +		return -ENODEV;
> +	}
> +
> +	bd = backlight_device_get_by_type(BACKLIGHT_RAW);
> +	if (!bd)
> +		return -ENODEV;
> +
> +	pmf->brightness = backlight_get_brightness(bd);
> +
> +	mutex_lock(&mode_config->mutex);
> +	drm_connector_list_iter_begin(drm_dev, &iter);
> +
> +	drm_for_each_connector_iter(connector, &iter) {
> +		if (i > MAX_SUPPORTED)
> +			break;

I'd put this below right after i++.

> +		if (connector->status == connector_status_connected) {
> +			pmf->con_status[i] = connector->status;
> +			pmf->connector_type[i] = connector->connector_type;
> +			pmf->display_count++;
> +		}
> +		i++;
> +	}
> +	drm_connector_list_iter_end(&iter);
> +	mutex_unlock(&mode_config->mutex);
> +
> +	return 0;
> +}
> +EXPORT_SYMBOL_GPL(amd_pmf_get_gfx_data);
> diff --git a/drivers/platform/x86/amd/pmf/Kconfig b/drivers/platform/x86/amd/pmf/Kconfig
> index 437b78c6d1c5..0cd08f9ab51b 100644
> --- a/drivers/platform/x86/amd/pmf/Kconfig
> +++ b/drivers/platform/x86/amd/pmf/Kconfig
> @@ -10,6 +10,7 @@ config AMD_PMF
>  	depends on AMD_NB
>  	select ACPI_PLATFORM_PROFILE
>  	depends on AMDTEE
> +	depends on DRM_AMDGPU
>  	help
>  	  This driver provides support for the AMD Platform Management Framework.
>  	  The goal is to enhance end user experience by making AMD PCs smarter,
> diff --git a/drivers/platform/x86/amd/pmf/core.c b/drivers/platform/x86/amd/pmf/core.c
> index dbfe7c1d6fc4..c468d208b1dc 100644
> --- a/drivers/platform/x86/amd/pmf/core.c
> +++ b/drivers/platform/x86/amd/pmf/core.c
> @@ -396,6 +396,7 @@ static int amd_pmf_probe(struct platform_device *pdev)
>  	}
>  
>  	dev->cpu_id = rdev->device;
> +	dev->root = rdev;
>  
>  	err = amd_smn_read(0, AMD_PMF_BASE_ADDR_LO, &val);
>  	if (err) {
> diff --git a/drivers/platform/x86/amd/pmf/pmf.h b/drivers/platform/x86/amd/pmf/pmf.h
> index 780c442239e3..9032df4ba48a 100644
> --- a/drivers/platform/x86/amd/pmf/pmf.h
> +++ b/drivers/platform/x86/amd/pmf/pmf.h
> @@ -13,6 +13,8 @@
>  
>  #include <linux/acpi.h>
>  #include <linux/platform_profile.h>
> +#include <linux/amd-pmf-io.h>
> +
>  #define POLICY_BUF_MAX_SZ		0x4b000
>  #define POLICY_SIGN_COOKIE		0x31535024
>  
> @@ -224,9 +226,11 @@ struct amd_pmf_dev {
>  	void *shbuf;
>  	struct delayed_work pb_work;
>  	struct pmf_action_table *prev_data;
> +	struct amd_gpu_pmf_data gfx_data;
>  	u64 policy_addr;
>  	void *policy_base;
>  	bool smart_pc_enabled;
> +	struct pci_dev *root;
>  };
>  
>  struct apmf_sps_prop_granular {
> diff --git a/drivers/platform/x86/amd/pmf/spc.c b/drivers/platform/x86/amd/pmf/spc.c
> index 5c6745f56ed1..5f3ab1ce09d2 100644
> --- a/drivers/platform/x86/amd/pmf/spc.c
> +++ b/drivers/platform/x86/amd/pmf/spc.c
> @@ -43,6 +43,10 @@ void amd_pmf_dump_ta_inputs(struct amd_pmf_dev *dev, struct ta_pmf_enact_table *
>  	dev_dbg(dev->dev, "Max C0 Residency : %d\n", in->ev_info.max_c0residency);
>  	dev_dbg(dev->dev, "GFX Busy : %d\n", in->ev_info.gfx_busy);
>  	dev_dbg(dev->dev, "Connected Display Count : %d\n", in->ev_info.monitor_count);
> +	dev_dbg(dev->dev, "Primary Display Type : %s\n",
> +		drm_get_connector_type_name(in->ev_info.display_type));
> +	dev_dbg(dev->dev, "Primary Display State : %s\n", in->ev_info.display_state ?
> +			"Connected" : "disconnected/unknown");
>  	dev_dbg(dev->dev, "LID State : %s\n", in->ev_info.lid_state ? "Close" : "Open");
>  	dev_dbg(dev->dev, "==== TA inputs END ====\n");
>  }
> @@ -144,6 +148,14 @@ static int amd_pmf_get_slider_info(struct amd_pmf_dev *dev, struct ta_pmf_enact_
>  	return 0;
>  }
>  
> +static void amd_pmf_get_gpu_info(struct amd_pmf_dev *dev, struct ta_pmf_enact_table *in)
> +{
> +	amd_pmf_get_gfx_data(&dev->gfx_data);
> +	in->ev_info.monitor_count = dev->gfx_data.display_count;
> +	in->ev_info.display_type = dev->gfx_data.connector_type[0];
> +	in->ev_info.display_state = dev->gfx_data.con_status[0];
> +}
> +
>  void amd_pmf_populate_ta_inputs(struct amd_pmf_dev *dev, struct ta_pmf_enact_table *in)
>  {
>  	/* TA side lid open is 1 and close is 0, hence the ! here */
> @@ -152,4 +164,5 @@ void amd_pmf_populate_ta_inputs(struct amd_pmf_dev *dev, struct ta_pmf_enact_tab
>  	amd_pmf_get_smu_info(dev, in);
>  	amd_pmf_get_battery_info(dev, in);
>  	amd_pmf_get_slider_info(dev, in);
> +	amd_pmf_get_gpu_info(dev, in);
>  }
> diff --git a/drivers/platform/x86/amd/pmf/tee-if.c b/drivers/platform/x86/amd/pmf/tee-if.c
> index 3daa122f35d5..1608996654e8 100644
> --- a/drivers/platform/x86/amd/pmf/tee-if.c
> +++ b/drivers/platform/x86/amd/pmf/tee-if.c
> @@ -9,6 +9,7 @@
>   */
>  
>  #include <linux/debugfs.h>
> +#include <linux/pci.h>
>  #include <linux/tee_drv.h>
>  #include <linux/uuid.h>
>  #include "pmf.h"
> @@ -345,6 +346,20 @@ static int amd_pmf_get_bios_buffer(struct amd_pmf_dev *dev)
>  	return amd_pmf_start_policy_engine(dev);
>  }
>  
> +static int amd_pmf_get_gpu_handle(struct pci_dev *pdev, void *data)
> +{
> +	struct amd_pmf_dev *dev = data;
> +
> +	if (pdev->vendor == PCI_VENDOR_ID_ATI && pdev->devfn == 0) {
> +		dev->gfx_data.gpu_dev = pci_get_device(pdev->vendor, pdev->device, NULL);

What is this attempting to do??

-- 
 i.


> +		if (dev->gfx_data.gpu_dev) {
> +			pci_dev_put(pdev);
> +			return 1; /* stop walking */
> +		}
> +	}
> +	return 0; /* continue walking */
> +}
> +
>  static int amd_pmf_amdtee_ta_match(struct tee_ioctl_version_data *ver, const void *data)
>  {
>  	return ver->impl_id == TEE_IMPL_ID_AMDTEE;
> @@ -435,6 +450,12 @@ int amd_pmf_init_smart_pc(struct amd_pmf_dev *dev)
>  	INIT_DELAYED_WORK(&dev->pb_work, amd_pmf_invoke_cmd);
>  	amd_pmf_set_dram_addr(dev);
>  	amd_pmf_get_bios_buffer(dev);
> +
> +	/* get amdgpu handle */
> +	pci_walk_bus(dev->root->bus, amd_pmf_get_gpu_handle, dev);
> +	if (!dev->gfx_data.gpu_dev)
> +		dev_err(dev->dev, "GPU handle not found!\n");
> +
>  	dev->prev_data = kzalloc(sizeof(*dev->prev_data), GFP_KERNEL);
>  	if (!dev->prev_data)
>  		return -ENOMEM;
> @@ -451,5 +472,6 @@ void amd_pmf_deinit_smart_pc(struct amd_pmf_dev *dev)
>  	kfree(dev->prev_data);
>  	kfree(dev->policy_buf);
>  	cancel_delayed_work_sync(&dev->pb_work);
> +	pci_dev_put(dev->gfx_data.gpu_dev);
>  	amd_pmf_tee_deinit(dev);
>  }
> diff --git a/include/linux/amd-pmf-io.h b/include/linux/amd-pmf-io.h
> new file mode 100644
> index 000000000000..a2d4af231362
> --- /dev/null
> +++ b/include/linux/amd-pmf-io.h
> @@ -0,0 +1,28 @@
> +/* SPDX-License-Identifier: GPL-2.0 */
> +/*
> + * AMD Platform Management Framework Interface
> + *
> + * Copyright (c) 2023, Advanced Micro Devices, Inc.
> + * All Rights Reserved.
> + *
> + * Author: Shyam Sundar S K <Shyam-sundar.S-k@amd.com>
> + */
> +
> +#ifndef AMD_PMF_IO_H
> +#define AMD_PMF_IO_H
> +
> +#include <drm/drm_connector.h>
> +
> +#define MAX_SUPPORTED 4
> +
> +/* amdgpu */
> +struct amd_gpu_pmf_data {
> +	struct pci_dev *gpu_dev;
> +	enum drm_connector_status con_status[MAX_SUPPORTED];
> +	int display_count;
> +	int connector_type[MAX_SUPPORTED];
> +	int brightness;
> +};
> +
> +int amd_pmf_get_gfx_data(struct amd_gpu_pmf_data *pmf);
> +#endif
> 

^ permalink raw reply	[flat|nested] 54+ messages in thread

* Re: [PATCH 13/15] platform/x86/amd/pmf: Add PMF-AMDGPU set interface
  2023-09-26 13:17         ` Christian König
  2023-09-26 13:48           ` Shyam Sundar S K
@ 2023-09-27 13:04           ` Hans de Goede
  2023-09-27 13:47             ` Shyam Sundar S K
  1 sibling, 1 reply; 54+ messages in thread
From: Hans de Goede @ 2023-09-27 13:04 UTC (permalink / raw)
  To: Christian König, Shyam Sundar S K, markgross,
	basavaraj.natikar, jikos, benjamin.tissoires, alexander.deucher,
	Xinhui.Pan, airlied, daniel
  Cc: amd-gfx, dri-devel, platform-driver-x86, mario.limonciello,
	Patil.Reddy, linux-input

HI,

On 9/26/23 15:17, Christian König wrote:
> Am 26.09.23 um 14:56 schrieb Hans de Goede:
>> Hi,
>>
>> On 9/26/23 13:24, Shyam Sundar S K wrote:
>>> Hi Hans,
>>>
>>> On 9/26/2023 4:05 PM, Hans de Goede wrote:
>>>> Hi,
>>>>
>>>> On 9/22/23 19:50, Shyam Sundar S K wrote:
>>>>> For the Smart PC Solution to fully work, it has to enact to the actions
>>>>> coming from TA. Add the initial code path for set interface to AMDGPU.
>>>>>
>>>>> Co-developed-by: Mario Limonciello <mario.limonciello@amd.com>
>>>>> Signed-off-by: Mario Limonciello <mario.limonciello@amd.com>
>>>>> Signed-off-by: Shyam Sundar S K <Shyam-sundar.S-k@amd.com>
>>>>> ---
>>>>>   drivers/gpu/drm/amd/amdgpu/amdgpu_pmf.c | 21 +++++++++++++++++++++
>>>>>   drivers/platform/x86/amd/pmf/pmf.h      |  2 ++
>>>>>   drivers/platform/x86/amd/pmf/tee-if.c   | 19 +++++++++++++++++--
>>>>>   include/linux/amd-pmf-io.h              |  1 +
>>>>>   4 files changed, 41 insertions(+), 2 deletions(-)
>>>>>
>>>>> diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_pmf.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_pmf.c
>>>>> index 232d11833ddc..5c567bff0548 100644
>>>>> --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_pmf.c
>>>>> +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_pmf.c
>>>>> @@ -68,3 +68,24 @@ int amd_pmf_get_gfx_data(struct amd_gpu_pmf_data *pmf)
>>>>>       return 0;
>>>>>   }
>>>>>   EXPORT_SYMBOL_GPL(amd_pmf_get_gfx_data);
>>>>> +
>>>>> +int amd_pmf_set_gfx_data(struct amd_gpu_pmf_data *pmf)
>>>>> +{
>>>>> +    struct drm_device *drm_dev = pci_get_drvdata(pmf->gpu_dev);
>>>>> +    struct amdgpu_device *adev = drm_to_adev(drm_dev);
>>>>> +    struct backlight_device *bd;
>>>>> +
>>>>> +    if (!(adev->flags & AMD_IS_APU)) {
>>>>> +        DRM_ERROR("PMF-AMDGPU interface not supported\n");
>>>>> +        return -ENODEV;
>>>>> +    }
>>>>> +
>>>>> +    bd = backlight_device_get_by_type(BACKLIGHT_RAW);
>>>>> +    if (!bd)
>>>>> +        return -ENODEV;
>>>> This assumes that the backlight is always controller by the amdgpu's
>>>> native backlight driver, but it might e.g. also be handled by
>>>> eacpi-video or by nvidia_wmi_ec_backlight (when using an AMD APU +
>>>> nvidia dgpu).
>>> PMF is meant for AMD APUs(atleast for now) and the _HID will only be
>>> made visible if its AMD laptop. So using amdgpu's native BACKLIGHT_RAW
>>> should be safe, right?
>> Users can pass say acpi_backlight=video and use the acpi_video
>> driver for backlight control instead of the native GPU backlight
>> control.
>>
>>>> For now what should be done here is to call acpi_video_get_backlight_type()
>>>> and then translate the return value from this into a backlight-type:
>>>>
>>>>          acpi_backlight_video        -> BACKLIGHT_FIRMWARE
>>>>          acpi_backlight_vendor,        -> BACKLIGHT_PLATFORM
>>>>          acpi_backlight_native,        -> BACKLIGHT_RAW
>>>>          acpi_backlight_nvidia_wmi_ec,    -> BACKLIGHT_FIRMWARE
>>>>          acpi_backlight_apple_gmux,    -> BACKLIGHT_PLATFORM
>>>>
>>> I can add this change in the v2, do you insist on this?
>> Insist is a strong word, but I think that it is a good idea to have
>> this. Evenutally it looks like this code will need to either integrate with
>> the drm drivers lot more; or the drm core needs to export some special
>> hooks for this which the PMF code can then call.
>>
>> Actually thinking more about this, I think that the right thing to do
>> here is make some code register brightness control as a cooling device
>> (which I think is already done in some cases) and then have the PMF
>> code use the cooling-device APIs for this.
>>
>> IMHO that would be a much cleaner solution then this hack.
> 
> Yeah, fully agree with Hans. This looks like a rather extreme hack to me.

Shyam, the cooling device interface is defined in:

include/linux/thermal.h

And then look for cooling_device .

An example of code registering a cooling_device for backlight control is:

drivers/acpi/acpi_video.c

and then specifically the code starting around line 257 with:

video_get_max_state()

until

static const struct thermal_cooling_device_ops video_cooling_ops = {
...

And the code around line 1750 for actually registering the cooling-dev.

To use the cooling_device interface witt amdgpu's native backlight control
you will need to make the amdgpu backlight control register a cooling-device
for this in a similar manner.

Regards,

Hans




> 
> Apart from that what exactly is this thing supposed to do? Prevent overheating by reducing the brightness?
> 
> Regards,
> Christian.
> 
>>
>> Regards,
>>
>> Hans
>>
>>
>>
>>> Thanks,
>>> Shyam
>>>
>>>> Also I'm worried about probe order here, this code currently assumes
>>>> that the GPU or other backlight driver has loaded before this runs,
>>>> which is not necessarily the case.
>>>>
>>>> I think that if the backlight_device_get_by_type() fails this
>>>> should be retried say every 10 seconds from some delayed workqueue
>>>> for at least a couple of minutes after boot.
>>>>
>>>> Regards,
>>>>
>>>> Hans
>>>>
>>>>
>>>>
>>>>
>>>>> +
>>>>> +    backlight_device_set_brightness(bd, pmf->brightness);
>>>>> +
>>>>> +    return 0;
>>>>> +}
>>>>> +EXPORT_SYMBOL_GPL(amd_pmf_set_gfx_data);
>>>>> diff --git a/drivers/platform/x86/amd/pmf/pmf.h b/drivers/platform/x86/amd/pmf/pmf.h
>>>>> index 9032df4ba48a..ce89cc0daa5a 100644
>>>>> --- a/drivers/platform/x86/amd/pmf/pmf.h
>>>>> +++ b/drivers/platform/x86/amd/pmf/pmf.h
>>>>> @@ -73,6 +73,7 @@
>>>>>   #define PMF_POLICY_STT_SKINTEMP_APU                7
>>>>>   #define PMF_POLICY_STT_SKINTEMP_HS2                8
>>>>>   #define PMF_POLICY_SYSTEM_STATE                    9
>>>>> +#define PMF_POLICY_DISPLAY_BRIGHTNESS                12
>>>>>   #define PMF_POLICY_P3T                        38
>>>>>     /* TA macros */
>>>>> @@ -480,6 +481,7 @@ enum ta_pmf_error_type {
>>>>>   };
>>>>>     struct pmf_action_table {
>>>>> +    unsigned long display_brightness;
>>>>>       enum system_state system_state;
>>>>>       unsigned long spl; /* in mW */
>>>>>       unsigned long sppt; /* in mW */
>>>>> diff --git a/drivers/platform/x86/amd/pmf/tee-if.c b/drivers/platform/x86/amd/pmf/tee-if.c
>>>>> index 1608996654e8..eefffff83a4c 100644
>>>>> --- a/drivers/platform/x86/amd/pmf/tee-if.c
>>>>> +++ b/drivers/platform/x86/amd/pmf/tee-if.c
>>>>> @@ -79,10 +79,10 @@ static int amd_pmf_update_uevents(struct amd_pmf_dev *dev, u16 event)
>>>>>       return 0;
>>>>>   }
>>>>>   -static void amd_pmf_apply_policies(struct amd_pmf_dev *dev, struct ta_pmf_enact_result *out)
>>>>> +static int amd_pmf_apply_policies(struct amd_pmf_dev *dev, struct ta_pmf_enact_result *out)
>>>>>   {
>>>>>       u32 val, event = 0;
>>>>> -    int idx;
>>>>> +    int idx, ret;
>>>>>         for (idx = 0; idx < out->actions_count; idx++) {
>>>>>           val = out->actions_list[idx].value;
>>>>> @@ -160,8 +160,23 @@ static void amd_pmf_apply_policies(struct amd_pmf_dev *dev, struct ta_pmf_enact_
>>>>>                   dev->prev_data->system_state = 0;
>>>>>               }
>>>>>               break;
>>>>> +
>>>>> +        case PMF_POLICY_DISPLAY_BRIGHTNESS:
>>>>> +            ret = amd_pmf_get_gfx_data(&dev->gfx_data);
>>>>> +            if (ret)
>>>>> +                return ret;
>>>>> +
>>>>> +            dev->prev_data->display_brightness = dev->gfx_data.brightness;
>>>>> +            if (dev->prev_data->display_brightness != val) {
>>>>> +                dev->gfx_data.brightness = val;
>>>>> +                amd_pmf_set_gfx_data(&dev->gfx_data);
>>>>> +                dev_dbg(dev->dev, "update DISPLAY_BRIGHTNESS : %d\n", val);
>>>>> +            }
>>>>> +            break;
>>>>>           }
>>>>>       }
>>>>> +
>>>>> +    return 0;
>>>>>   }
>>>>>     static int amd_pmf_invoke_cmd_enact(struct amd_pmf_dev *dev)
>>>>> diff --git a/include/linux/amd-pmf-io.h b/include/linux/amd-pmf-io.h
>>>>> index a2d4af231362..ecae387ddaa6 100644
>>>>> --- a/include/linux/amd-pmf-io.h
>>>>> +++ b/include/linux/amd-pmf-io.h
>>>>> @@ -25,4 +25,5 @@ struct amd_gpu_pmf_data {
>>>>>   };
>>>>>     int amd_pmf_get_gfx_data(struct amd_gpu_pmf_data *pmf);
>>>>> +int amd_pmf_set_gfx_data(struct amd_gpu_pmf_data *pmf);
>>>>>   #endif
> 


^ permalink raw reply	[flat|nested] 54+ messages in thread

* Re: [PATCH 14/15] platform/x86/amd/pmf: Add PMF-AMDSFH interface for HPD
  2023-09-22 17:50 ` [PATCH 14/15] platform/x86/amd/pmf: Add PMF-AMDSFH interface for HPD Shyam Sundar S K
  2023-09-22 19:04   ` Mario Limonciello
@ 2023-09-27 13:32   ` Ilpo Järvinen
  1 sibling, 0 replies; 54+ messages in thread
From: Ilpo Järvinen @ 2023-09-27 13:32 UTC (permalink / raw)
  To: Shyam Sundar S K
  Cc: Xinhui.Pan, Patil.Reddy, Basavaraj Natikar, dri-devel, jikos,
	amd-gfx, platform-driver-x86, markgross, hdegoede,
	benjamin.tissoires, mario.limonciello, linux-input,
	alexander.deucher, christian.koenig

On Fri, 22 Sep 2023, Shyam Sundar S K wrote:

> From: Basavaraj Natikar <Basavaraj.Natikar@amd.com>
> 
> AMDSFH has information about the User presence information via the Human
> Presence Detection (HPD) sensor which is part of the AMD sensor fusion hub.
> Add PMF and AMDSFH interface to get this information.
> 
> Co-developed-by: Shyam Sundar S K <Shyam-sundar.S-k@amd.com>
> Signed-off-by: Shyam Sundar S K <Shyam-sundar.S-k@amd.com>
> Signed-off-by: Basavaraj Natikar <Basavaraj.Natikar@amd.com>
> ---
>  drivers/hid/amd-sfh-hid/amd_sfh_common.h      |  5 ++++
>  drivers/hid/amd-sfh-hid/sfh1_1/amd_sfh_desc.c |  2 +-
>  drivers/hid/amd-sfh-hid/sfh1_1/amd_sfh_init.c | 11 ++++++++
>  .../amd-sfh-hid/sfh1_1/amd_sfh_interface.c    | 28 +++++++++++++++++++
>  .../amd-sfh-hid/sfh1_1/amd_sfh_interface.h    |  1 +
>  drivers/platform/x86/amd/pmf/spc.c            | 21 ++++++++++++++
>  include/linux/amd-pmf-io.h                    | 22 ++++++++++++++-
>  7 files changed, 88 insertions(+), 2 deletions(-)
> 
> diff --git a/drivers/hid/amd-sfh-hid/amd_sfh_common.h b/drivers/hid/amd-sfh-hid/amd_sfh_common.h
> index 2643bb14fee2..cd57037bf217 100644
> --- a/drivers/hid/amd-sfh-hid/amd_sfh_common.h
> +++ b/drivers/hid/amd-sfh-hid/amd_sfh_common.h
> @@ -37,6 +37,10 @@ struct amd_mp2_sensor_info {
>  	dma_addr_t dma_address;
>  };
>  
> +struct sfh_dev_status {
> +	bool is_hpd_present;
> +};
> +
>  struct amd_mp2_dev {
>  	struct pci_dev *pdev;
>  	struct amdtp_cl_data *cl_data;
> @@ -47,6 +51,7 @@ struct amd_mp2_dev {
>  	struct amd_input_data in_data;
>  	/* mp2 active control status */
>  	u32 mp2_acs;
> +	struct sfh_dev_status dev_en;
>  };
>  
>  struct amd_mp2_ops {
> diff --git a/drivers/hid/amd-sfh-hid/sfh1_1/amd_sfh_desc.c b/drivers/hid/amd-sfh-hid/sfh1_1/amd_sfh_desc.c
> index 06bdcf072d10..d7467c41ad3b 100644
> --- a/drivers/hid/amd-sfh-hid/sfh1_1/amd_sfh_desc.c
> +++ b/drivers/hid/amd-sfh-hid/sfh1_1/amd_sfh_desc.c
> @@ -132,7 +132,7 @@ static void get_common_inputs(struct common_input_property *common, int report_i
>  	common->event_type = HID_USAGE_SENSOR_EVENT_DATA_UPDATED_ENUM;
>  }
>  
> -static int float_to_int(u32 flt32_val)
> +int float_to_int(u32 flt32_val)

This is way too generic name to be exposed by a driver, add proper 
prefix for it to make sure it never hits a compile problem.

>  {
>  	int fraction, shift, mantissa, sign, exp, zeropre;
>  
> diff --git a/drivers/hid/amd-sfh-hid/sfh1_1/amd_sfh_init.c b/drivers/hid/amd-sfh-hid/sfh1_1/amd_sfh_init.c
> index e9c6413af24a..9c623456ee12 100644
> --- a/drivers/hid/amd-sfh-hid/sfh1_1/amd_sfh_init.c
> +++ b/drivers/hid/amd-sfh-hid/sfh1_1/amd_sfh_init.c
> @@ -73,6 +73,12 @@ static int amd_sfh_hid_client_deinit(struct amd_mp2_dev *privdata)
>  	int i, status;
>  
>  	for (i = 0; i < cl_data->num_hid_devices; i++) {
> +		switch (cl_data->sensor_idx[i]) {
> +		case HPD_IDX:
> +			privdata->dev_en.is_hpd_present = false;
> +			break;
> +		}
> +
>  		if (cl_data->sensor_sts[i] == SENSOR_ENABLED) {
>  			privdata->mp2_ops->stop(privdata, cl_data->sensor_idx[i]);
>  			status = amd_sfh_wait_for_response
> @@ -178,6 +184,11 @@ static int amd_sfh1_1_hid_client_init(struct amd_mp2_dev *privdata)
>  			rc = amdtp_hid_probe(i, cl_data);
>  			if (rc)
>  				goto cleanup;
> +			switch (cl_data->sensor_idx[i]) {
> +			case HPD_IDX:
> +			privdata->dev_en.is_hpd_present = true;
> +				break;
> +			}
>  		}
>  		dev_dbg(dev, "sid 0x%x (%s) status 0x%x\n",
>  			cl_data->sensor_idx[i], get_sensor_name(cl_data->sensor_idx[i]),
> diff --git a/drivers/hid/amd-sfh-hid/sfh1_1/amd_sfh_interface.c b/drivers/hid/amd-sfh-hid/sfh1_1/amd_sfh_interface.c
> index 4f81ef2d4f56..63a5bbca5a09 100644
> --- a/drivers/hid/amd-sfh-hid/sfh1_1/amd_sfh_interface.c
> +++ b/drivers/hid/amd-sfh-hid/sfh1_1/amd_sfh_interface.c
> @@ -7,11 +7,14 @@
>   *
>   * Author: Basavaraj Natikar <Basavaraj.Natikar@amd.com>
>   */
> +#include <linux/amd-pmf-io.h>
>  #include <linux/io-64-nonatomic-lo-hi.h>
>  #include <linux/iopoll.h>
>  
>  #include "amd_sfh_interface.h"
>  
> +static struct amd_mp2_dev *emp2;
> +
>  static int amd_sfh_wait_response(struct amd_mp2_dev *mp2, u8 sid, u32 cmd_id)
>  {
>  	struct sfh_cmd_response cmd_resp;
> @@ -76,4 +79,29 @@ static struct amd_mp2_ops amd_sfh_ops = {
>  void sfh_interface_init(struct amd_mp2_dev *mp2)
>  {
>  	mp2->mp2_ops = &amd_sfh_ops;
> +	emp2 = mp2;
> +}
> +
> +static int amd_sfh_hpd_info(u8 *user_present)
> +{
> +	if (emp2 && emp2->dev_en.is_hpd_present) {
> +		struct hpd_status hpdstatus;
> +
> +		hpdstatus.val = readl(emp2->mmio + AMD_C2P_MSG(4));
> +		*user_present = hpdstatus.shpd.presence;
> +		return 0;
> +	}
> +	return  -ENODEV;
> +}
> +
> +int amd_get_sfh_info(struct amd_sfh_info *sfh_info, enum sfh_message_type op)
> +{
> +	if (sfh_info) {
> +		switch (op) {
> +		case MT_HPD:
> +			return amd_sfh_hpd_info(&sfh_info->user_present);
> +		}
> +	}
> +	return -1;
>  }
> +EXPORT_SYMBOL_GPL(amd_get_sfh_info);
> diff --git a/drivers/hid/amd-sfh-hid/sfh1_1/amd_sfh_interface.h b/drivers/hid/amd-sfh-hid/sfh1_1/amd_sfh_interface.h
> index 9d31d5b510eb..8a36386e6bce 100644
> --- a/drivers/hid/amd-sfh-hid/sfh1_1/amd_sfh_interface.h
> +++ b/drivers/hid/amd-sfh-hid/sfh1_1/amd_sfh_interface.h
> @@ -149,6 +149,7 @@ struct hpd_status {
>  	};
>  };
>  
> +int float_to_int(u32 flt32_val);
>  void sfh_interface_init(struct amd_mp2_dev *mp2);
>  void amd_sfh1_1_set_desc_ops(struct amd_mp2_ops *mp2_ops);
>  #endif
> diff --git a/drivers/platform/x86/amd/pmf/spc.c b/drivers/platform/x86/amd/pmf/spc.c
> index 5f3ab1ce09d2..97293ae25cf5 100644
> --- a/drivers/platform/x86/amd/pmf/spc.c
> +++ b/drivers/platform/x86/amd/pmf/spc.c
> @@ -48,6 +48,7 @@ void amd_pmf_dump_ta_inputs(struct amd_pmf_dev *dev, struct ta_pmf_enact_table *
>  	dev_dbg(dev->dev, "Primary Display State : %s\n", in->ev_info.display_state ?
>  			"Connected" : "disconnected/unknown");
>  	dev_dbg(dev->dev, "LID State : %s\n", in->ev_info.lid_state ? "Close" : "Open");
> +	dev_dbg(dev->dev, "User Presence : %s\n", in->ev_info.user_present ? "Present" : "Away");
>  	dev_dbg(dev->dev, "==== TA inputs END ====\n");
>  }
>  #else
> @@ -156,6 +157,25 @@ static void amd_pmf_get_gpu_info(struct amd_pmf_dev *dev, struct ta_pmf_enact_ta
>  	in->ev_info.display_state = dev->gfx_data.con_status[0];
>  }
>  
> +static void amd_pmf_get_sensor_info(struct amd_pmf_dev *dev, struct ta_pmf_enact_table *in)
> +{
> +	struct amd_sfh_info sfh_info;
> +
> +	/* get HPD data */
> +	amd_get_sfh_info(&sfh_info, MT_HPD);
> +	switch (sfh_info.user_present) {
> +	case SFH_NOT_DETECTED:
> +		in->ev_info.user_present = 0xff; /* assume no sensors connected */
> +		break;
> +	case SFH_USER_PRESENT:
> +		in->ev_info.user_present = 1;
> +		break;
> +	case SFH_USER_AWAY:
> +		in->ev_info.user_present = 0;
> +		break;
> +	}
> +}
> +
>  void amd_pmf_populate_ta_inputs(struct amd_pmf_dev *dev, struct ta_pmf_enact_table *in)
>  {
>  	/* TA side lid open is 1 and close is 0, hence the ! here */
> @@ -165,4 +185,5 @@ void amd_pmf_populate_ta_inputs(struct amd_pmf_dev *dev, struct ta_pmf_enact_tab
>  	amd_pmf_get_battery_info(dev, in);
>  	amd_pmf_get_slider_info(dev, in);
>  	amd_pmf_get_gpu_info(dev, in);
> +	amd_pmf_get_sensor_info(dev, in);
>  }
> diff --git a/include/linux/amd-pmf-io.h b/include/linux/amd-pmf-io.h
> index ecae387ddaa6..4f82973f6ad2 100644
> --- a/include/linux/amd-pmf-io.h
> +++ b/include/linux/amd-pmf-io.h
> @@ -5,7 +5,8 @@
>   * Copyright (c) 2023, Advanced Micro Devices, Inc.
>   * All Rights Reserved.
>   *
> - * Author: Shyam Sundar S K <Shyam-sundar.S-k@amd.com>
> + * Authors: Shyam Sundar S K <Shyam-sundar.S-k@amd.com>
> + *          Basavaraj Natikar <Basavaraj.Natikar@amd.com>
>   */
>  
>  #ifndef AMD_PMF_IO_H
> @@ -26,4 +27,23 @@ struct amd_gpu_pmf_data {
>  
>  int amd_pmf_get_gfx_data(struct amd_gpu_pmf_data *pmf);
>  int amd_pmf_set_gfx_data(struct amd_gpu_pmf_data *pmf);
> +
> +/* amd-sfh */
> +enum sfh_message_type {
> +	MT_HPD,
> +};
> +
> +enum hpd_info {
> +	SFH_NOT_DETECTED,
> +	SFH_USER_PRESENT,
> +	SFH_USER_AWAY
> +};
> +
> +struct amd_sfh_info {
> +	u8 user_present;
> +	/* add future caps below */

Remove the comment?

> +};
> +
> +int amd_get_sfh_info(struct amd_sfh_info *sfh_info, enum sfh_message_type op);
> +
>  #endif
> 

-- 
 i.


^ permalink raw reply	[flat|nested] 54+ messages in thread

* Re: [PATCH 15/15] platform/x86/amd/pmf: Add PMF-AMDSFH interface for ALS
  2023-09-22 17:50 ` [PATCH 15/15] platform/x86/amd/pmf: Add PMF-AMDSFH interface for ALS Shyam Sundar S K
  2023-09-22 19:06   ` Mario Limonciello
@ 2023-09-27 13:33   ` Ilpo Järvinen
  2023-09-27 13:48     ` Shyam Sundar S K
  1 sibling, 1 reply; 54+ messages in thread
From: Ilpo Järvinen @ 2023-09-27 13:33 UTC (permalink / raw)
  To: Shyam Sundar S K
  Cc: Xinhui.Pan, Patil.Reddy, Basavaraj Natikar, dri-devel, jikos,
	amd-gfx, platform-driver-x86, markgross, hdegoede,
	benjamin.tissoires, mario.limonciello, linux-input,
	alexander.deucher, christian.koenig

On Fri, 22 Sep 2023, Shyam Sundar S K wrote:

> From: Basavaraj Natikar <Basavaraj.Natikar@amd.com>
> 
> AMDSFH has information about the Ambient light via the Ambient
> Light Sensor (ALS) which is part of the AMD sensor fusion hub.
> Add PMF and AMDSFH interface to get this information.
> 
> Co-developed-by: Shyam Sundar S K <Shyam-sundar.S-k@amd.com>
> Signed-off-by: Shyam Sundar S K <Shyam-sundar.S-k@amd.com>
> Signed-off-by: Basavaraj Natikar <Basavaraj.Natikar@amd.com>
> ---
>  drivers/hid/amd-sfh-hid/amd_sfh_common.h      |  1 +
>  drivers/hid/amd-sfh-hid/sfh1_1/amd_sfh_init.c |  6 ++++++
>  .../amd-sfh-hid/sfh1_1/amd_sfh_interface.c    | 20 +++++++++++++++++++
>  drivers/platform/x86/amd/pmf/spc.c            |  5 +++++
>  include/linux/amd-pmf-io.h                    |  2 ++
>  5 files changed, 34 insertions(+)
> 
> diff --git a/drivers/hid/amd-sfh-hid/amd_sfh_common.h b/drivers/hid/amd-sfh-hid/amd_sfh_common.h
> index cd57037bf217..a1950bc6e6ce 100644
> --- a/drivers/hid/amd-sfh-hid/amd_sfh_common.h
> +++ b/drivers/hid/amd-sfh-hid/amd_sfh_common.h
> @@ -39,6 +39,7 @@ struct amd_mp2_sensor_info {
>  
>  struct sfh_dev_status {
>  	bool is_hpd_present;
> +	bool is_als_present;
>  };
>  
>  struct amd_mp2_dev {
> diff --git a/drivers/hid/amd-sfh-hid/sfh1_1/amd_sfh_init.c b/drivers/hid/amd-sfh-hid/sfh1_1/amd_sfh_init.c
> index 9c623456ee12..d8dad39d68b5 100644
> --- a/drivers/hid/amd-sfh-hid/sfh1_1/amd_sfh_init.c
> +++ b/drivers/hid/amd-sfh-hid/sfh1_1/amd_sfh_init.c
> @@ -77,6 +77,9 @@ static int amd_sfh_hid_client_deinit(struct amd_mp2_dev *privdata)
>  		case HPD_IDX:
>  			privdata->dev_en.is_hpd_present = false;
>  			break;
> +		case ALS_IDX:
> +			privdata->dev_en.is_als_present = false;
> +			break;
>  		}
>  
>  		if (cl_data->sensor_sts[i] == SENSOR_ENABLED) {
> @@ -188,6 +191,9 @@ static int amd_sfh1_1_hid_client_init(struct amd_mp2_dev *privdata)
>  			case HPD_IDX:
>  			privdata->dev_en.is_hpd_present = true;
>  				break;
> +			case ALS_IDX:
> +			privdata->dev_en.is_als_present = true;
> +				break;
>  			}
>  		}
>  		dev_dbg(dev, "sid 0x%x (%s) status 0x%x\n",
> diff --git a/drivers/hid/amd-sfh-hid/sfh1_1/amd_sfh_interface.c b/drivers/hid/amd-sfh-hid/sfh1_1/amd_sfh_interface.c
> index 63a5bbca5a09..2f8200fc3062 100644
> --- a/drivers/hid/amd-sfh-hid/sfh1_1/amd_sfh_interface.c
> +++ b/drivers/hid/amd-sfh-hid/sfh1_1/amd_sfh_interface.c
> @@ -94,12 +94,32 @@ static int amd_sfh_hpd_info(u8 *user_present)
>  	return  -ENODEV;
>  }
>  
> +static int amd_sfh_als_info(u32 *ambient_light)
> +{
> +	if (emp2 && emp2->dev_en.is_als_present) {
> +		struct sfh_als_data als_data;
> +		void __iomem *sensoraddr;
> +
> +		sensoraddr = emp2->vsbase +
> +			(ALS_IDX * SENSOR_DATA_MEM_SIZE_DEFAULT) +
> +			OFFSET_SENSOR_DATA_DEFAULT;
> +		memcpy_fromio(&als_data, sensoraddr, sizeof(struct sfh_als_data));
> +		*ambient_light = float_to_int(als_data.lux);
> +
> +		return 0;
> +	}
> +
> +	return -ENODEV;
> +}
> +
>  int amd_get_sfh_info(struct amd_sfh_info *sfh_info, enum sfh_message_type op)
>  {
>  	if (sfh_info) {
>  		switch (op) {
>  		case MT_HPD:
>  			return amd_sfh_hpd_info(&sfh_info->user_present);
> +		case MT_ALS:
> +			return amd_sfh_als_info(&sfh_info->ambient_light);
>  		}
>  	}
>  	return -1;
> diff --git a/drivers/platform/x86/amd/pmf/spc.c b/drivers/platform/x86/amd/pmf/spc.c
> index 97293ae25cf5..8e19b351e76f 100644
> --- a/drivers/platform/x86/amd/pmf/spc.c
> +++ b/drivers/platform/x86/amd/pmf/spc.c
> @@ -49,6 +49,7 @@ void amd_pmf_dump_ta_inputs(struct amd_pmf_dev *dev, struct ta_pmf_enact_table *
>  			"Connected" : "disconnected/unknown");
>  	dev_dbg(dev->dev, "LID State : %s\n", in->ev_info.lid_state ? "Close" : "Open");
>  	dev_dbg(dev->dev, "User Presence : %s\n", in->ev_info.user_present ? "Present" : "Away");
> +	dev_dbg(dev->dev, "Ambient Light : %d\n", in->ev_info.ambient_light);

%d vs u32

>  	dev_dbg(dev->dev, "==== TA inputs END ====\n");
>  }
>  #else
> @@ -161,6 +162,10 @@ static void amd_pmf_get_sensor_info(struct amd_pmf_dev *dev, struct ta_pmf_enact
>  {
>  	struct amd_sfh_info sfh_info;
>  
> +	/* get ALS data */
> +	amd_get_sfh_info(&sfh_info, MT_ALS);
> +	in->ev_info.ambient_light = sfh_info.ambient_light;
> +
>  	/* get HPD data */
>  	amd_get_sfh_info(&sfh_info, MT_HPD);
>  	switch (sfh_info.user_present) {
> diff --git a/include/linux/amd-pmf-io.h b/include/linux/amd-pmf-io.h
> index 4f82973f6ad2..dac0af573a16 100644
> --- a/include/linux/amd-pmf-io.h
> +++ b/include/linux/amd-pmf-io.h
> @@ -31,6 +31,7 @@ int amd_pmf_set_gfx_data(struct amd_gpu_pmf_data *pmf);
>  /* amd-sfh */
>  enum sfh_message_type {
>  	MT_HPD,
> +	MT_ALS,
>  };
>  
>  enum hpd_info {
> @@ -40,6 +41,7 @@ enum hpd_info {
>  };
>  
>  struct amd_sfh_info {
> +	u32 ambient_light;
>  	u8 user_present;
>  	/* add future caps below */
>  };
> 

-- 
 i.


^ permalink raw reply	[flat|nested] 54+ messages in thread

* Re: [PATCH 13/15] platform/x86/amd/pmf: Add PMF-AMDGPU set interface
  2023-09-22 17:50 ` [PATCH 13/15] platform/x86/amd/pmf: Add PMF-AMDGPU set interface Shyam Sundar S K
  2023-09-25 16:27   ` Deucher, Alexander
  2023-09-26 10:35   ` Hans de Goede
@ 2023-09-27 13:36   ` Ilpo Järvinen
  2 siblings, 0 replies; 54+ messages in thread
From: Ilpo Järvinen @ 2023-09-27 13:36 UTC (permalink / raw)
  To: Shyam Sundar S K
  Cc: Xinhui.Pan, Patil.Reddy, basavaraj.natikar, dri-devel, jikos,
	amd-gfx, platform-driver-x86, markgross, hdegoede,
	benjamin.tissoires, mario.limonciello, linux-input,
	alexander.deucher, christian.koenig

On Fri, 22 Sep 2023, Shyam Sundar S K wrote:

> For the Smart PC Solution to fully work, it has to enact to the actions
> coming from TA. Add the initial code path for set interface to AMDGPU.
> 
> Co-developed-by: Mario Limonciello <mario.limonciello@amd.com>
> Signed-off-by: Mario Limonciello <mario.limonciello@amd.com>
> Signed-off-by: Shyam Sundar S K <Shyam-sundar.S-k@amd.com>
> ---
>  drivers/gpu/drm/amd/amdgpu/amdgpu_pmf.c | 21 +++++++++++++++++++++
>  drivers/platform/x86/amd/pmf/pmf.h      |  2 ++
>  drivers/platform/x86/amd/pmf/tee-if.c   | 19 +++++++++++++++++--
>  include/linux/amd-pmf-io.h              |  1 +
>  4 files changed, 41 insertions(+), 2 deletions(-)
> 
> diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_pmf.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_pmf.c
> index 232d11833ddc..5c567bff0548 100644
> --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_pmf.c
> +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_pmf.c
> @@ -68,3 +68,24 @@ int amd_pmf_get_gfx_data(struct amd_gpu_pmf_data *pmf)
>  	return 0;
>  }
>  EXPORT_SYMBOL_GPL(amd_pmf_get_gfx_data);
> +
> +int amd_pmf_set_gfx_data(struct amd_gpu_pmf_data *pmf)
> +{
> +	struct drm_device *drm_dev = pci_get_drvdata(pmf->gpu_dev);
> +	struct amdgpu_device *adev = drm_to_adev(drm_dev);
> +	struct backlight_device *bd;
> +
> +	if (!(adev->flags & AMD_IS_APU)) {
> +		DRM_ERROR("PMF-AMDGPU interface not supported\n");
> +		return -ENODEV;
> +	}
> +
> +	bd = backlight_device_get_by_type(BACKLIGHT_RAW);
> +	if (!bd)
> +		return -ENODEV;
> +
> +	backlight_device_set_brightness(bd, pmf->brightness);
> +
> +	return 0;
> +}
> +EXPORT_SYMBOL_GPL(amd_pmf_set_gfx_data);
> diff --git a/drivers/platform/x86/amd/pmf/pmf.h b/drivers/platform/x86/amd/pmf/pmf.h
> index 9032df4ba48a..ce89cc0daa5a 100644
> --- a/drivers/platform/x86/amd/pmf/pmf.h
> +++ b/drivers/platform/x86/amd/pmf/pmf.h
> @@ -73,6 +73,7 @@
>  #define PMF_POLICY_STT_SKINTEMP_APU				7
>  #define PMF_POLICY_STT_SKINTEMP_HS2				8
>  #define PMF_POLICY_SYSTEM_STATE					9
> +#define PMF_POLICY_DISPLAY_BRIGHTNESS				12
>  #define PMF_POLICY_P3T						38
>  
>  /* TA macros */
> @@ -480,6 +481,7 @@ enum ta_pmf_error_type {
>  };
>  
>  struct pmf_action_table {
> +	unsigned long display_brightness;
>  	enum system_state system_state;
>  	unsigned long spl; /* in mW */
>  	unsigned long sppt; /* in mW */
> diff --git a/drivers/platform/x86/amd/pmf/tee-if.c b/drivers/platform/x86/amd/pmf/tee-if.c
> index 1608996654e8..eefffff83a4c 100644
> --- a/drivers/platform/x86/amd/pmf/tee-if.c
> +++ b/drivers/platform/x86/amd/pmf/tee-if.c
> @@ -79,10 +79,10 @@ static int amd_pmf_update_uevents(struct amd_pmf_dev *dev, u16 event)
>  	return 0;
>  }
>  
> -static void amd_pmf_apply_policies(struct amd_pmf_dev *dev, struct ta_pmf_enact_result *out)
> +static int amd_pmf_apply_policies(struct amd_pmf_dev *dev, struct ta_pmf_enact_result *out)

Changing return type but no caller is changed to handle the error??

>  {
>  	u32 val, event = 0;
> -	int idx;
> +	int idx, ret;
>  
>  	for (idx = 0; idx < out->actions_count; idx++) {
>  		val = out->actions_list[idx].value;
> @@ -160,8 +160,23 @@ static void amd_pmf_apply_policies(struct amd_pmf_dev *dev, struct ta_pmf_enact_
>  				dev->prev_data->system_state = 0;
>  			}
>  			break;
> +
> +		case PMF_POLICY_DISPLAY_BRIGHTNESS:
> +			ret = amd_pmf_get_gfx_data(&dev->gfx_data);
> +			if (ret)
> +				return ret;
> +
> +			dev->prev_data->display_brightness = dev->gfx_data.brightness;
> +			if (dev->prev_data->display_brightness != val) {
> +				dev->gfx_data.brightness = val;
> +				amd_pmf_set_gfx_data(&dev->gfx_data);
> +				dev_dbg(dev->dev, "update DISPLAY_BRIGHTNESS : %d\n", val);
> +			}
> +			break;
>  		}
>  	}
> +
> +	return 0;
>  }
>  
>  static int amd_pmf_invoke_cmd_enact(struct amd_pmf_dev *dev)
> diff --git a/include/linux/amd-pmf-io.h b/include/linux/amd-pmf-io.h
> index a2d4af231362..ecae387ddaa6 100644
> --- a/include/linux/amd-pmf-io.h
> +++ b/include/linux/amd-pmf-io.h
> @@ -25,4 +25,5 @@ struct amd_gpu_pmf_data {
>  };
>  
>  int amd_pmf_get_gfx_data(struct amd_gpu_pmf_data *pmf);
> +int amd_pmf_set_gfx_data(struct amd_gpu_pmf_data *pmf);
>  #endif
> 

-- 
 i.


^ permalink raw reply	[flat|nested] 54+ messages in thread

* Re: [PATCH 13/15] platform/x86/amd/pmf: Add PMF-AMDGPU set interface
  2023-09-27 13:04           ` Hans de Goede
@ 2023-09-27 13:47             ` Shyam Sundar S K
  0 siblings, 0 replies; 54+ messages in thread
From: Shyam Sundar S K @ 2023-09-27 13:47 UTC (permalink / raw)
  To: Hans de Goede, Christian König, markgross,
	basavaraj.natikar, jikos, benjamin.tissoires, alexander.deucher,
	Xinhui.Pan, airlied, daniel
  Cc: amd-gfx, dri-devel, platform-driver-x86, mario.limonciello,
	Patil.Reddy, linux-input

Hi Hans,

On 9/27/2023 6:34 PM, Hans de Goede wrote:
> HI,
> 
> On 9/26/23 15:17, Christian König wrote:
>> Am 26.09.23 um 14:56 schrieb Hans de Goede:
>>> Hi,
>>>
>>> On 9/26/23 13:24, Shyam Sundar S K wrote:
>>>> Hi Hans,
>>>>
>>>> On 9/26/2023 4:05 PM, Hans de Goede wrote:
>>>>> Hi,
>>>>>
>>>>> On 9/22/23 19:50, Shyam Sundar S K wrote:
>>>>>> For the Smart PC Solution to fully work, it has to enact to the actions
>>>>>> coming from TA. Add the initial code path for set interface to AMDGPU.
>>>>>>
>>>>>> Co-developed-by: Mario Limonciello <mario.limonciello@amd.com>
>>>>>> Signed-off-by: Mario Limonciello <mario.limonciello@amd.com>
>>>>>> Signed-off-by: Shyam Sundar S K <Shyam-sundar.S-k@amd.com>
>>>>>> ---
>>>>>>   drivers/gpu/drm/amd/amdgpu/amdgpu_pmf.c | 21 +++++++++++++++++++++
>>>>>>   drivers/platform/x86/amd/pmf/pmf.h      |  2 ++
>>>>>>   drivers/platform/x86/amd/pmf/tee-if.c   | 19 +++++++++++++++++--
>>>>>>   include/linux/amd-pmf-io.h              |  1 +
>>>>>>   4 files changed, 41 insertions(+), 2 deletions(-)
>>>>>>
>>>>>> diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_pmf.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_pmf.c
>>>>>> index 232d11833ddc..5c567bff0548 100644
>>>>>> --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_pmf.c
>>>>>> +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_pmf.c
>>>>>> @@ -68,3 +68,24 @@ int amd_pmf_get_gfx_data(struct amd_gpu_pmf_data *pmf)
>>>>>>       return 0;
>>>>>>   }
>>>>>>   EXPORT_SYMBOL_GPL(amd_pmf_get_gfx_data);
>>>>>> +
>>>>>> +int amd_pmf_set_gfx_data(struct amd_gpu_pmf_data *pmf)
>>>>>> +{
>>>>>> +    struct drm_device *drm_dev = pci_get_drvdata(pmf->gpu_dev);
>>>>>> +    struct amdgpu_device *adev = drm_to_adev(drm_dev);
>>>>>> +    struct backlight_device *bd;
>>>>>> +
>>>>>> +    if (!(adev->flags & AMD_IS_APU)) {
>>>>>> +        DRM_ERROR("PMF-AMDGPU interface not supported\n");
>>>>>> +        return -ENODEV;
>>>>>> +    }
>>>>>> +
>>>>>> +    bd = backlight_device_get_by_type(BACKLIGHT_RAW);
>>>>>> +    if (!bd)
>>>>>> +        return -ENODEV;
>>>>> This assumes that the backlight is always controller by the amdgpu's
>>>>> native backlight driver, but it might e.g. also be handled by
>>>>> eacpi-video or by nvidia_wmi_ec_backlight (when using an AMD APU +
>>>>> nvidia dgpu).
>>>> PMF is meant for AMD APUs(atleast for now) and the _HID will only be
>>>> made visible if its AMD laptop. So using amdgpu's native BACKLIGHT_RAW
>>>> should be safe, right?
>>> Users can pass say acpi_backlight=video and use the acpi_video
>>> driver for backlight control instead of the native GPU backlight
>>> control.
>>>
>>>>> For now what should be done here is to call acpi_video_get_backlight_type()
>>>>> and then translate the return value from this into a backlight-type:
>>>>>
>>>>>          acpi_backlight_video        -> BACKLIGHT_FIRMWARE
>>>>>          acpi_backlight_vendor,        -> BACKLIGHT_PLATFORM
>>>>>          acpi_backlight_native,        -> BACKLIGHT_RAW
>>>>>          acpi_backlight_nvidia_wmi_ec,    -> BACKLIGHT_FIRMWARE
>>>>>          acpi_backlight_apple_gmux,    -> BACKLIGHT_PLATFORM
>>>>>
>>>> I can add this change in the v2, do you insist on this?
>>> Insist is a strong word, but I think that it is a good idea to have
>>> this. Evenutally it looks like this code will need to either integrate with
>>> the drm drivers lot more; or the drm core needs to export some special
>>> hooks for this which the PMF code can then call.
>>>
>>> Actually thinking more about this, I think that the right thing to do
>>> here is make some code register brightness control as a cooling device
>>> (which I think is already done in some cases) and then have the PMF
>>> code use the cooling-device APIs for this.
>>>
>>> IMHO that would be a much cleaner solution then this hack.
>>
>> Yeah, fully agree with Hans. This looks like a rather extreme hack to me.
> 
> Shyam, the cooling device interface is defined in:
> 
> include/linux/thermal.h
> 
> And then look for cooling_device .
> 
> An example of code registering a cooling_device for backlight control is:
> 
> drivers/acpi/acpi_video.c
> 
> and then specifically the code starting around line 257 with:
> 
> video_get_max_state()
> 
> until
> 
> static const struct thermal_cooling_device_ops video_cooling_ops = {
> ...
> 
> And the code around line 1750 for actually registering the cooling-dev.
> 
> To use the cooling_device interface witt amdgpu's native backlight control
> you will need to make the amdgpu backlight control register a cooling-device
> for this in a similar manner.
> 

Thank you for pointing to the references. I will address the remarks
from Ilpo and respin a new version soon.

Thanks,
Shyam

> Regards,
> 
> Hans
> 
> 
> 
> 
>>
>> Apart from that what exactly is this thing supposed to do? Prevent overheating by reducing the brightness?
>>
>> Regards,
>> Christian.
>>
>>>
>>> Regards,
>>>
>>> Hans
>>>
>>>
>>>
>>>> Thanks,
>>>> Shyam
>>>>
>>>>> Also I'm worried about probe order here, this code currently assumes
>>>>> that the GPU or other backlight driver has loaded before this runs,
>>>>> which is not necessarily the case.
>>>>>
>>>>> I think that if the backlight_device_get_by_type() fails this
>>>>> should be retried say every 10 seconds from some delayed workqueue
>>>>> for at least a couple of minutes after boot.
>>>>>
>>>>> Regards,
>>>>>
>>>>> Hans
>>>>>
>>>>>
>>>>>
>>>>>
>>>>>> +
>>>>>> +    backlight_device_set_brightness(bd, pmf->brightness);
>>>>>> +
>>>>>> +    return 0;
>>>>>> +}
>>>>>> +EXPORT_SYMBOL_GPL(amd_pmf_set_gfx_data);
>>>>>> diff --git a/drivers/platform/x86/amd/pmf/pmf.h b/drivers/platform/x86/amd/pmf/pmf.h
>>>>>> index 9032df4ba48a..ce89cc0daa5a 100644
>>>>>> --- a/drivers/platform/x86/amd/pmf/pmf.h
>>>>>> +++ b/drivers/platform/x86/amd/pmf/pmf.h
>>>>>> @@ -73,6 +73,7 @@
>>>>>>   #define PMF_POLICY_STT_SKINTEMP_APU                7
>>>>>>   #define PMF_POLICY_STT_SKINTEMP_HS2                8
>>>>>>   #define PMF_POLICY_SYSTEM_STATE                    9
>>>>>> +#define PMF_POLICY_DISPLAY_BRIGHTNESS                12
>>>>>>   #define PMF_POLICY_P3T                        38
>>>>>>     /* TA macros */
>>>>>> @@ -480,6 +481,7 @@ enum ta_pmf_error_type {
>>>>>>   };
>>>>>>     struct pmf_action_table {
>>>>>> +    unsigned long display_brightness;
>>>>>>       enum system_state system_state;
>>>>>>       unsigned long spl; /* in mW */
>>>>>>       unsigned long sppt; /* in mW */
>>>>>> diff --git a/drivers/platform/x86/amd/pmf/tee-if.c b/drivers/platform/x86/amd/pmf/tee-if.c
>>>>>> index 1608996654e8..eefffff83a4c 100644
>>>>>> --- a/drivers/platform/x86/amd/pmf/tee-if.c
>>>>>> +++ b/drivers/platform/x86/amd/pmf/tee-if.c
>>>>>> @@ -79,10 +79,10 @@ static int amd_pmf_update_uevents(struct amd_pmf_dev *dev, u16 event)
>>>>>>       return 0;
>>>>>>   }
>>>>>>   -static void amd_pmf_apply_policies(struct amd_pmf_dev *dev, struct ta_pmf_enact_result *out)
>>>>>> +static int amd_pmf_apply_policies(struct amd_pmf_dev *dev, struct ta_pmf_enact_result *out)
>>>>>>   {
>>>>>>       u32 val, event = 0;
>>>>>> -    int idx;
>>>>>> +    int idx, ret;
>>>>>>         for (idx = 0; idx < out->actions_count; idx++) {
>>>>>>           val = out->actions_list[idx].value;
>>>>>> @@ -160,8 +160,23 @@ static void amd_pmf_apply_policies(struct amd_pmf_dev *dev, struct ta_pmf_enact_
>>>>>>                   dev->prev_data->system_state = 0;
>>>>>>               }
>>>>>>               break;
>>>>>> +
>>>>>> +        case PMF_POLICY_DISPLAY_BRIGHTNESS:
>>>>>> +            ret = amd_pmf_get_gfx_data(&dev->gfx_data);
>>>>>> +            if (ret)
>>>>>> +                return ret;
>>>>>> +
>>>>>> +            dev->prev_data->display_brightness = dev->gfx_data.brightness;
>>>>>> +            if (dev->prev_data->display_brightness != val) {
>>>>>> +                dev->gfx_data.brightness = val;
>>>>>> +                amd_pmf_set_gfx_data(&dev->gfx_data);
>>>>>> +                dev_dbg(dev->dev, "update DISPLAY_BRIGHTNESS : %d\n", val);
>>>>>> +            }
>>>>>> +            break;
>>>>>>           }
>>>>>>       }
>>>>>> +
>>>>>> +    return 0;
>>>>>>   }
>>>>>>     static int amd_pmf_invoke_cmd_enact(struct amd_pmf_dev *dev)
>>>>>> diff --git a/include/linux/amd-pmf-io.h b/include/linux/amd-pmf-io.h
>>>>>> index a2d4af231362..ecae387ddaa6 100644
>>>>>> --- a/include/linux/amd-pmf-io.h
>>>>>> +++ b/include/linux/amd-pmf-io.h
>>>>>> @@ -25,4 +25,5 @@ struct amd_gpu_pmf_data {
>>>>>>   };
>>>>>>     int amd_pmf_get_gfx_data(struct amd_gpu_pmf_data *pmf);
>>>>>> +int amd_pmf_set_gfx_data(struct amd_gpu_pmf_data *pmf);
>>>>>>   #endif
>>
> 

^ permalink raw reply	[flat|nested] 54+ messages in thread

* Re: [PATCH 15/15] platform/x86/amd/pmf: Add PMF-AMDSFH interface for ALS
  2023-09-27 13:33   ` Ilpo Järvinen
@ 2023-09-27 13:48     ` Shyam Sundar S K
  0 siblings, 0 replies; 54+ messages in thread
From: Shyam Sundar S K @ 2023-09-27 13:48 UTC (permalink / raw)
  To: Ilpo Järvinen
  Cc: Xinhui.Pan, Patil.Reddy, Basavaraj Natikar, dri-devel, jikos,
	amd-gfx, platform-driver-x86, markgross, hdegoede,
	benjamin.tissoires, mario.limonciello, linux-input,
	alexander.deucher, christian.koenig

Hi Ilpo,

On 9/27/2023 7:03 PM, Ilpo Järvinen wrote:
> On Fri, 22 Sep 2023, Shyam Sundar S K wrote:
> 
>> From: Basavaraj Natikar <Basavaraj.Natikar@amd.com>
>>
>> AMDSFH has information about the Ambient light via the Ambient
>> Light Sensor (ALS) which is part of the AMD sensor fusion hub.
>> Add PMF and AMDSFH interface to get this information.
>>
>> Co-developed-by: Shyam Sundar S K <Shyam-sundar.S-k@amd.com>
>> Signed-off-by: Shyam Sundar S K <Shyam-sundar.S-k@amd.com>
>> Signed-off-by: Basavaraj Natikar <Basavaraj.Natikar@amd.com>
>> ---
>>  drivers/hid/amd-sfh-hid/amd_sfh_common.h      |  1 +
>>  drivers/hid/amd-sfh-hid/sfh1_1/amd_sfh_init.c |  6 ++++++
>>  .../amd-sfh-hid/sfh1_1/amd_sfh_interface.c    | 20 +++++++++++++++++++
>>  drivers/platform/x86/amd/pmf/spc.c            |  5 +++++
>>  include/linux/amd-pmf-io.h                    |  2 ++
>>  5 files changed, 34 insertions(+)
>>
>> diff --git a/drivers/hid/amd-sfh-hid/amd_sfh_common.h b/drivers/hid/amd-sfh-hid/amd_sfh_common.h
>> index cd57037bf217..a1950bc6e6ce 100644
>> --- a/drivers/hid/amd-sfh-hid/amd_sfh_common.h
>> +++ b/drivers/hid/amd-sfh-hid/amd_sfh_common.h
>> @@ -39,6 +39,7 @@ struct amd_mp2_sensor_info {
>>  
>>  struct sfh_dev_status {
>>  	bool is_hpd_present;
>> +	bool is_als_present;
>>  };
>>  
>>  struct amd_mp2_dev {
>> diff --git a/drivers/hid/amd-sfh-hid/sfh1_1/amd_sfh_init.c b/drivers/hid/amd-sfh-hid/sfh1_1/amd_sfh_init.c
>> index 9c623456ee12..d8dad39d68b5 100644
>> --- a/drivers/hid/amd-sfh-hid/sfh1_1/amd_sfh_init.c
>> +++ b/drivers/hid/amd-sfh-hid/sfh1_1/amd_sfh_init.c
>> @@ -77,6 +77,9 @@ static int amd_sfh_hid_client_deinit(struct amd_mp2_dev *privdata)
>>  		case HPD_IDX:
>>  			privdata->dev_en.is_hpd_present = false;
>>  			break;
>> +		case ALS_IDX:
>> +			privdata->dev_en.is_als_present = false;
>> +			break;
>>  		}
>>  
>>  		if (cl_data->sensor_sts[i] == SENSOR_ENABLED) {
>> @@ -188,6 +191,9 @@ static int amd_sfh1_1_hid_client_init(struct amd_mp2_dev *privdata)
>>  			case HPD_IDX:
>>  			privdata->dev_en.is_hpd_present = true;
>>  				break;
>> +			case ALS_IDX:
>> +			privdata->dev_en.is_als_present = true;
>> +				break;
>>  			}
>>  		}
>>  		dev_dbg(dev, "sid 0x%x (%s) status 0x%x\n",
>> diff --git a/drivers/hid/amd-sfh-hid/sfh1_1/amd_sfh_interface.c b/drivers/hid/amd-sfh-hid/sfh1_1/amd_sfh_interface.c
>> index 63a5bbca5a09..2f8200fc3062 100644
>> --- a/drivers/hid/amd-sfh-hid/sfh1_1/amd_sfh_interface.c
>> +++ b/drivers/hid/amd-sfh-hid/sfh1_1/amd_sfh_interface.c
>> @@ -94,12 +94,32 @@ static int amd_sfh_hpd_info(u8 *user_present)
>>  	return  -ENODEV;
>>  }
>>  
>> +static int amd_sfh_als_info(u32 *ambient_light)
>> +{
>> +	if (emp2 && emp2->dev_en.is_als_present) {
>> +		struct sfh_als_data als_data;
>> +		void __iomem *sensoraddr;
>> +
>> +		sensoraddr = emp2->vsbase +
>> +			(ALS_IDX * SENSOR_DATA_MEM_SIZE_DEFAULT) +
>> +			OFFSET_SENSOR_DATA_DEFAULT;
>> +		memcpy_fromio(&als_data, sensoraddr, sizeof(struct sfh_als_data));
>> +		*ambient_light = float_to_int(als_data.lux);
>> +
>> +		return 0;
>> +	}
>> +
>> +	return -ENODEV;
>> +}
>> +
>>  int amd_get_sfh_info(struct amd_sfh_info *sfh_info, enum sfh_message_type op)
>>  {
>>  	if (sfh_info) {
>>  		switch (op) {
>>  		case MT_HPD:
>>  			return amd_sfh_hpd_info(&sfh_info->user_present);
>> +		case MT_ALS:
>> +			return amd_sfh_als_info(&sfh_info->ambient_light);
>>  		}
>>  	}
>>  	return -1;
>> diff --git a/drivers/platform/x86/amd/pmf/spc.c b/drivers/platform/x86/amd/pmf/spc.c
>> index 97293ae25cf5..8e19b351e76f 100644
>> --- a/drivers/platform/x86/amd/pmf/spc.c
>> +++ b/drivers/platform/x86/amd/pmf/spc.c
>> @@ -49,6 +49,7 @@ void amd_pmf_dump_ta_inputs(struct amd_pmf_dev *dev, struct ta_pmf_enact_table *
>>  			"Connected" : "disconnected/unknown");
>>  	dev_dbg(dev->dev, "LID State : %s\n", in->ev_info.lid_state ? "Close" : "Open");
>>  	dev_dbg(dev->dev, "User Presence : %s\n", in->ev_info.user_present ? "Present" : "Away");
>> +	dev_dbg(dev->dev, "Ambient Light : %d\n", in->ev_info.ambient_light);
> 
> %d vs u32

Thank you very much for your feedback. I will respin a new version
soon addressing your review remarks.

Thanks,
Shyam

> 
>>  	dev_dbg(dev->dev, "==== TA inputs END ====\n");
>>  }
>>  #else
>> @@ -161,6 +162,10 @@ static void amd_pmf_get_sensor_info(struct amd_pmf_dev *dev, struct ta_pmf_enact
>>  {
>>  	struct amd_sfh_info sfh_info;
>>  
>> +	/* get ALS data */
>> +	amd_get_sfh_info(&sfh_info, MT_ALS);
>> +	in->ev_info.ambient_light = sfh_info.ambient_light;
>> +
>>  	/* get HPD data */
>>  	amd_get_sfh_info(&sfh_info, MT_HPD);
>>  	switch (sfh_info.user_present) {
>> diff --git a/include/linux/amd-pmf-io.h b/include/linux/amd-pmf-io.h
>> index 4f82973f6ad2..dac0af573a16 100644
>> --- a/include/linux/amd-pmf-io.h
>> +++ b/include/linux/amd-pmf-io.h
>> @@ -31,6 +31,7 @@ int amd_pmf_set_gfx_data(struct amd_gpu_pmf_data *pmf);
>>  /* amd-sfh */
>>  enum sfh_message_type {
>>  	MT_HPD,
>> +	MT_ALS,
>>  };
>>  
>>  enum hpd_info {
>> @@ -40,6 +41,7 @@ enum hpd_info {
>>  };
>>  
>>  struct amd_sfh_info {
>> +	u32 ambient_light;
>>  	u8 user_present;
>>  	/* add future caps below */
>>  };
>>
> 

^ permalink raw reply	[flat|nested] 54+ messages in thread

* Re: [PATCH 04/15] platform/x86/amd/pmf: Add support for PMF Policy Binary
  2023-09-22 18:51   ` Mario Limonciello
@ 2023-09-30  3:55     ` Shyam Sundar S K
  0 siblings, 0 replies; 54+ messages in thread
From: Shyam Sundar S K @ 2023-09-30  3:55 UTC (permalink / raw)
  To: Mario Limonciello, hdegoede, markgross, basavaraj.natikar, jikos,
	benjamin.tissoires, alexander.deucher, christian.koenig,
	Xinhui.Pan, airlied, daniel
  Cc: dri-devel, linux-input, amd-gfx, Patil.Reddy, platform-driver-x86



On 9/23/2023 12:21 AM, Mario Limonciello wrote:
> On 9/22/2023 12:50, Shyam Sundar S K wrote:
>> PMF Policy binary is a encrypted and signed binary that will be part
>> of the BIOS. PMF driver via the ACPI interface checks the existence
>> of Smart PC bit. If the advertised bit is found, PMF driver walks
>> the acpi namespace to find out the policy binary size and the address
>> which has to be passed to the TA during the TA init sequence.
>>
>> The policy binary is comprised of inputs (or the events) and outputs
>> (or the actions). With the PMF ecosystem, OEMs generate the policy
>> binary (or could be multiple binaries) that contains a supported set
>> of inputs and outputs which could be specifically carved out for each
>> usage segment (or for each user also) that could influence the system
>> behavior either by enriching the user experience or/and boost/throttle
>> power limits.
>>
>> Once the TA init command succeeds, the PMF driver sends the changing
>> events in the current environment to the TA for a constant sampling
>> frequency time (the event here could be a lid close or open) and
>> if the policy binary has corresponding action built within it, the
>> TA sends the action for it in the subsequent enact command.
>>
>> If the inputs sent to the TA has no output defined in the policy
>> binary generated by OEMs, there will be no action to be performed
>> by the PMF driver.
>>
>> Example policies:
>>
>> 1) if slider is performance ; set the SPL to 40W
>> Here PMF driver registers with the platform profile interface and
>> when the slider position is changed, PMF driver lets the TA know
>> about this. TA sends back an action to update the Sustained
>> Power Limit (SPL). PMF driver updates this limit via the PMFW mailbox.
>>
>> 2) if user_away ; then lock the system
>> Here PMF driver hooks to the AMD SFH driver to know the user presence
>> and send the inputs to TA and if the condition is met, the TA sends
>> the action of locking the system. PMF driver generates a uevent and
>> based on the udev rule in the userland the system gets locked with
>> systemctl.
>>
>> The intent here is to provide the OEM's to make a policy to lock the
>> system when the user is away ; but the userland can make a choice to
>> ignore it.
>>
>> and so on.
>>
>> The OEMs will have an utility to create numerous such policies and
>> the policies shall be reviewed by AMD before signing and encrypting
>> them. Policies are shared between operating systems to have seemless
>> user
>> experience.
>>
>> Since all this action has to happen via the "amdtee" driver, currently
>> there is no caller for it in the kernel which can load the amdtee
>> driver.
>> Without amdtee driver loading onto the system the "tee" calls shall
>> fail
>> from the PMF driver. Hence an explicit "request_module" has been added
>> to address this.
>>
>> Signed-off-by: Shyam Sundar S K <Shyam-sundar.S-k@amd.com>
>> ---
>>   drivers/platform/x86/amd/pmf/Kconfig  |   1 +
>>   drivers/platform/x86/amd/pmf/acpi.c   |  37 +++++++
>>   drivers/platform/x86/amd/pmf/core.c   |  12 +++
>>   drivers/platform/x86/amd/pmf/pmf.h    | 132 ++++++++++++++++++++++++
>>   drivers/platform/x86/amd/pmf/tee-if.c | 141
>> +++++++++++++++++++++++++-
>>   5 files changed, 321 insertions(+), 2 deletions(-)
>>
>> diff --git a/drivers/platform/x86/amd/pmf/Kconfig
>> b/drivers/platform/x86/amd/pmf/Kconfig
>> index 3064bc8ea167..437b78c6d1c5 100644
>> --- a/drivers/platform/x86/amd/pmf/Kconfig
>> +++ b/drivers/platform/x86/amd/pmf/Kconfig
>> @@ -9,6 +9,7 @@ config AMD_PMF
>>       depends on POWER_SUPPLY
>>       depends on AMD_NB
>>       select ACPI_PLATFORM_PROFILE
>> +    depends on AMDTEE
>>       help
>>         This driver provides support for the AMD Platform Management
>> Framework.
>>         The goal is to enhance end user experience by making AMD PCs
>> smarter,
>> diff --git a/drivers/platform/x86/amd/pmf/acpi.c
>> b/drivers/platform/x86/amd/pmf/acpi.c
>> index 3fc5e4547d9f..d0512af2cd42 100644
>> --- a/drivers/platform/x86/amd/pmf/acpi.c
>> +++ b/drivers/platform/x86/amd/pmf/acpi.c
>> @@ -286,6 +286,43 @@ int apmf_install_handler(struct amd_pmf_dev
>> *pmf_dev)
>>       return 0;
>>   }
>>   +static acpi_status apmf_walk_resources(struct acpi_resource *res,
>> void *data)
>> +{
>> +    struct amd_pmf_dev *dev = data;
>> +
>> +    switch (res->type) {
>> +    case ACPI_RESOURCE_TYPE_ADDRESS64:
>> +        dev->policy_addr = res->data.address64.address.minimum;
>> +        dev->policy_sz = res->data.address64.address.address_length;
>> +        break;
>> +    case ACPI_RESOURCE_TYPE_FIXED_MEMORY32:
>> +        dev->policy_addr = res->data.fixed_memory32.address;
>> +        dev->policy_sz = res->data.fixed_memory32.address_length;
>> +        break;
>> +    }
>> +
>> +    if (!dev->policy_addr || dev->policy_sz > POLICY_BUF_MAX_SZ ||
>> dev->policy_sz == 0) {
>> +        pr_err("Incorrect Policy params, possibly a SBIOS bug\n");
>> +        return AE_ERROR;
>> +    }
>> +
>> +    return AE_OK;
>> +}
>> +
>> +int apmf_check_smart_pc(struct amd_pmf_dev *pmf_dev)
>> +{
>> +    acpi_handle ahandle = ACPI_HANDLE(pmf_dev->dev);
>> +    acpi_status status;
>> +
>> +    status = acpi_walk_resources(ahandle, METHOD_NAME__CRS,
>> apmf_walk_resources, pmf_dev);
>> +    if (ACPI_FAILURE(status)) {
>> +        dev_err(pmf_dev->dev, "acpi_walk_resources failed\n");
>> +        return status;
>> +    }
>> +
>> +    return 0;
>> +}
>> +
>>   void apmf_acpi_deinit(struct amd_pmf_dev *pmf_dev)
>>   {
>>       acpi_handle ahandle = ACPI_HANDLE(pmf_dev->dev);
>> diff --git a/drivers/platform/x86/amd/pmf/core.c
>> b/drivers/platform/x86/amd/pmf/core.c
>> index 5fb03ed614ff..6f36c43e081e 100644
>> --- a/drivers/platform/x86/amd/pmf/core.c
>> +++ b/drivers/platform/x86/amd/pmf/core.c
>> @@ -376,6 +376,18 @@ static int amd_pmf_probe(struct platform_device
>> *pdev)
>>           return -ENOMEM;
>>         dev->dev = &pdev->dev;
>> +    err = apmf_check_smart_pc(dev);
>> +    if (!err) {
>> +        /* in order for Smart PC solution to work it has a hard
>> dependency
>> +         * on the amdtee driver to be loaded first even before the
>> PMF driver
>> +         * loads. PMF ASL has a _CRS method that advertises the
>> existence
>> +         * of Smart PC bit. If this information is present, use
>> this to
>> +         * explicitly probe the amdtee driver, so that "tee"
>> plumbing is done
>> +         * before the PMF Smart PC init happens.
>> +         */
>> +        if (request_module("amdtee"))
>> +            pr_err("Failed to load amdtee. PMF Smart PC not
>> enabled!\n");
> 
> In this case; would it make sense to fail the driver load entirely?
> I tend to think yes.
> 
> My argument for failing driver load is that if the platform uses Smart
> PC policies, then falling back will basically leave you with at best a
> broken static slider and at worst a driver that you can't fix by
> loading amdtee manually later on.

I don't think so we need to return from here. But not doing so,
atleast we will have users to have a functional static slider.

I have tested it now on multiple reference boards and static slider
will not be broken. And yes, manually loading "amdtee" later will not
help in this case.

Thanks,
Shyam

> 
>> +    }
>>         rdev = pci_get_domain_bus_and_slot(0, 0, PCI_DEVFN(0, 0));
>>       if (!rdev || !pci_match_id(pmf_pci_ids, rdev)) {
>> diff --git a/drivers/platform/x86/amd/pmf/pmf.h
>> b/drivers/platform/x86/amd/pmf/pmf.h
>> index ea15ce547d24..81acf2a37366 100644
>> --- a/drivers/platform/x86/amd/pmf/pmf.h
>> +++ b/drivers/platform/x86/amd/pmf/pmf.h
>> @@ -13,6 +13,8 @@
>>     #include <linux/acpi.h>
>>   #include <linux/platform_profile.h>
>> +#define POLICY_BUF_MAX_SZ        0x4b000
>> +#define POLICY_SIGN_COOKIE        0x31535024
>>     /* APMF Functions */
>>   #define APMF_FUNC_VERIFY_INTERFACE            0
>> @@ -59,8 +61,20 @@
>>   #define ARG_NONE 0
>>   #define AVG_SAMPLE_SIZE 3
>>   +/* Policy Actions */
>> +#define PMF_POLICY_SPL                        2
>> +#define PMF_POLICY_SPPT                        3
>> +#define PMF_POLICY_FPPT                        4
>> +#define PMF_POLICY_SPPT_APU_ONLY                5
>> +#define PMF_POLICY_STT_MIN                    6
>> +#define PMF_POLICY_STT_SKINTEMP_APU                7
>> +#define PMF_POLICY_STT_SKINTEMP_HS2                8
>> +
>>   /* TA macros */
>>   #define PMF_TA_IF_VERSION__MAJOR                1
>> +#define TA_PMF_ACTION_MAX                    32
>> +#define TA_PMF_UNDO_MAX                        8
>> +#define MAX_OPERATION_PARAMS                    4
>>     /* AMD PMF BIOS interfaces */
>>   struct apmf_verify_interface {
>> @@ -183,11 +197,16 @@ struct amd_pmf_dev {
>>       bool cnqf_supported;
>>       struct notifier_block pwr_src_notifier;
>>       /* Smart PC solution builder */
>> +    unsigned char *policy_buf;
>> +    u32 policy_sz;
>>       struct tee_context *tee_ctx;
>>       struct tee_shm *fw_shm_pool;
>>       u32 session_id;
>>       void *shbuf;
>>       struct delayed_work pb_work;
>> +    struct pmf_action_table *prev_data;
>> +    u64 policy_addr;
>> +    void *policy_base;
>>       bool smart_pc_enabled;
>>   };
>>   @@ -399,17 +418,129 @@ struct apmf_dyn_slider_output {
>>       struct apmf_cnqf_power_set ps[APMF_CNQF_MAX];
>>   } __packed;
>>   +/* Smart PC - TA internals */
>> +enum ta_slider {
>> +    TA_BEST_BATTERY, /* Best Battery */
>> +    TA_BETTER_BATTERY, /* Better Battery */
>> +    TA_BETTER_PERFORMANCE, /* Better Performance */
>> +    TA_BEST_PERFORMANCE, /* Best Performance */
>> +    TA_MAX,
>> +};
>> +
>>   /* cmd ids for TA communication */
>>   enum ta_pmf_command {
>>       TA_PMF_COMMAND_POLICY_BUILDER__INITIALIZE,
>>       TA_PMF_COMMAND_POLICY_BUILDER__ENACT_POLICIES
>>   };
>>   +enum ta_pmf_error_type {
>> +    TA_PMF_TYPE__SUCCESS,
>> +    TA_PMF_ERROR_TYPE__GENERIC,
>> +    TA_PMF_ERROR_TYPE__CRYPTO,
>> +    TA_PMF_ERROR_TYPE__CRYPTO_VALIDATE,
>> +    TA_PMF_ERROR_TYPE__CRYPTO_VERIFY_OEM,
>> +    TA_PMF_ERROR_TYPE__POLICY_BUILDER,
>> +    TA_PMF_ERROR_TYPE__PB_CONVERT,
>> +    TA_PMF_ERROR_TYPE__PB_SETUP,
>> +    TA_PMF_ERROR_TYPE__PB_ENACT,
>> +    TA_PMF_ERROR_TYPE__ASD_GET_DEVICE_INFO,
>> +    TA_PMF_ERROR_TYPE__ASD_GET_DEVICE_PCIE_INFO,
>> +    TA_PMF_ERROR_TYPE__SYS_DRV_FW_VALIDATION,
>> +    TA_PMF_ERROR_TYPE__MAX,
>> +};
>> +
>> +struct pmf_action_table {
>> +    unsigned long spl; /* in mW */
>> +    unsigned long sppt; /* in mW */
>> +    unsigned long sppt_apuonly; /* in mW */
>> +    unsigned long fppt; /* in mW */
>> +    unsigned long stt_minlimit; /* in mW */
>> +    unsigned long stt_skintemp_apu; /* in C */
>> +    unsigned long stt_skintemp_hs2; /* in C */
>> +};
>> +
>> +/* Input conditions */
>> +struct ta_pmf_condition_info {
>> +    u32 power_source;
>> +    u32 bat_percentage;
>> +    u32 power_slider;
>> +    u32 lid_state;
>> +    bool user_present;
>> +    u32 rsvd1[2];
>> +    u32 monitor_count;
>> +    u32 rsvd2[2];
>> +    u32 bat_design;
>> +    u32 full_charge_capacity;
>> +    int drain_rate;
>> +    bool user_engaged;
>> +    u32 device_state;
>> +    u32 socket_power;
>> +    u32 skin_temperature;
>> +    u32 rsvd3[5];
>> +    u32 ambient_light;
>> +    u32 length;
>> +    u32 avg_c0residency;
>> +    u32 max_c0residency;
>> +    u32 s0i3_entry;
>> +    u32 gfx_busy;
>> +    u32 rsvd4[7];
>> +    bool camera_state;
>> +    u32 workload_type;
>> +    u32 display_type;
>> +    u32 display_state;
>> +    u32 rsvd5[150];
>> +};
>> +
>> +struct ta_pmf_load_policy_table {
>> +    u32 table_size;
>> +    u8 table[POLICY_BUF_MAX_SZ];
>> +};
>> +
>> +/* TA initialization params */
>> +struct ta_pmf_init_table {
>> +    u32 frequency; /* SMU sampling frequency */
>> +    bool validate;
>> +    bool sku_check;
>> +    bool metadata_macrocheck;
>> +    struct ta_pmf_load_policy_table policies_table;
>> +};
>> +
>> +/* Everything the TA needs to Enact Policies */
>> +struct ta_pmf_enact_table {
>> +    struct ta_pmf_condition_info ev_info;
>> +    u32 name;
>> +};
>> +
>> +struct ta_pmf_action {
>> +    u32 action_index;
>> +    u32 value;
>> +};
>> +
>> +/* output actions from TA */
>> +struct ta_pmf_enact_result {
>> +    u32 actions_count;
>> +    struct ta_pmf_action actions_list[TA_PMF_ACTION_MAX];
>> +    u32 undo_count;
>> +    struct ta_pmf_action undo_list[TA_PMF_UNDO_MAX];
>> +};
>> +
>> +union ta_pmf_input {
>> +    struct ta_pmf_enact_table enact_table;
>> +    struct ta_pmf_init_table init_table;
>> +};
>> +
>> +union ta_pmf_output {
>> +    struct ta_pmf_enact_result policy_apply_table;
>> +    u32 rsvd[906];
>> +};
>> +
>>   struct ta_pmf_shared_memory {
>>       int command_id;
>>       int resp_id;
>>       u32 pmf_result;
>>       u32 if_version;
>> +    union ta_pmf_output pmf_output;
>> +    union ta_pmf_input pmf_input;
>>   };
>>     /* Core Layer */
>> @@ -460,4 +591,5 @@ extern const struct attribute_group
>> cnqf_feature_attribute_group;
>>   /* Smart PC builder Layer*/
>>   int amd_pmf_init_smart_pc(struct amd_pmf_dev *dev);
>>   void amd_pmf_deinit_smart_pc(struct amd_pmf_dev *dev);
>> +int apmf_check_smart_pc(struct amd_pmf_dev *pmf_dev);
>>   #endif /* PMF_H */
>> diff --git a/drivers/platform/x86/amd/pmf/tee-if.c
>> b/drivers/platform/x86/amd/pmf/tee-if.c
>> index 1fce04beacb3..a8b05e746efd 100644
>> --- a/drivers/platform/x86/amd/pmf/tee-if.c
>> +++ b/drivers/platform/x86/amd/pmf/tee-if.c
>> @@ -42,9 +42,77 @@ static void amd_pmf_prepare_args(struct
>> amd_pmf_dev *dev, int cmd,
>>       param[0].u.memref.shm_offs = 0;
>>   }
>>   +static void amd_pmf_apply_policies(struct amd_pmf_dev *dev,
>> struct ta_pmf_enact_result *out)
>> +{
>> +    u32 val;
>> +    int idx;
>> +
>> +    for (idx = 0; idx < out->actions_count; idx++) {
>> +        val = out->actions_list[idx].value;
>> +        switch (out->actions_list[idx].action_index) {
>> +        case PMF_POLICY_SPL:
>> +            if (dev->prev_data->spl != val) {
>> +                amd_pmf_send_cmd(dev, SET_SPL, false, val, NULL);
>> +                dev_dbg(dev->dev, "update SPL : %d\n", val);
>> +                dev->prev_data->spl = val;
>> +            }
>> +            break;
>> +
>> +        case PMF_POLICY_SPPT:
>> +            if (dev->prev_data->sppt != val) {
>> +                amd_pmf_send_cmd(dev, SET_SPPT, false, val, NULL);
>> +                dev_dbg(dev->dev, "update SPPT : %d\n", val);
>> +                dev->prev_data->sppt = val;
>> +            }
>> +            break;
>> +
>> +        case PMF_POLICY_FPPT:
>> +            if (dev->prev_data->fppt != val) {
>> +                amd_pmf_send_cmd(dev, SET_FPPT, false, val, NULL);
>> +                dev_dbg(dev->dev, "update FPPT : %d\n", val);
>> +                dev->prev_data->fppt = val;
>> +            }
>> +            break;
>> +
>> +        case PMF_POLICY_SPPT_APU_ONLY:
>> +            if (dev->prev_data->sppt_apuonly != val) {
>> +                amd_pmf_send_cmd(dev, SET_SPPT_APU_ONLY, false,
>> val, NULL);
>> +                dev_dbg(dev->dev, "update SPPT_APU_ONLY : %d\n", val);
>> +                dev->prev_data->sppt_apuonly = val;
>> +            }
>> +            break;
>> +
>> +        case PMF_POLICY_STT_MIN:
>> +            if (dev->prev_data->stt_minlimit != val) {
>> +                amd_pmf_send_cmd(dev, SET_STT_MIN_LIMIT, false,
>> val, NULL);
>> +                dev_dbg(dev->dev, "update STT_MIN : %d\n", val);
>> +                dev->prev_data->stt_minlimit = val;
>> +            }
>> +            break;
>> +
>> +        case PMF_POLICY_STT_SKINTEMP_APU:
>> +            if (dev->prev_data->stt_skintemp_apu != val) {
>> +                amd_pmf_send_cmd(dev, SET_STT_LIMIT_APU, false,
>> val, NULL);
>> +                dev_dbg(dev->dev, "update STT_SKINTEMP_APU : %d\n",
>> val);
>> +                dev->prev_data->stt_skintemp_apu = val;
>> +            }
>> +            break;
>> +
>> +        case PMF_POLICY_STT_SKINTEMP_HS2:
>> +            if (dev->prev_data->stt_skintemp_hs2 != val) {
>> +                amd_pmf_send_cmd(dev, SET_STT_LIMIT_HS2, false,
>> val, NULL);
>> +                dev_dbg(dev->dev, "update STT_SKINTEMP_HS2 : %d\n",
>> val);
>> +                dev->prev_data->stt_skintemp_hs2 = val;
>> +            }
>> +            break;
>> +        }
>> +    }
>> +}
>> +
>>   static int amd_pmf_invoke_cmd_enact(struct amd_pmf_dev *dev)
>>   {
>>       struct ta_pmf_shared_memory *ta_sm = NULL;
>> +    struct ta_pmf_enact_result *out = NULL;
>>       struct tee_param param[MAX_TEE_PARAM];
>>       struct tee_ioctl_invoke_arg arg;
>>       int ret = 0;
>> @@ -52,7 +120,10 @@ static int amd_pmf_invoke_cmd_enact(struct
>> amd_pmf_dev *dev)
>>       if (!dev->tee_ctx)
>>           return -ENODEV;
>>   +    memset(dev->shbuf, 0, dev->policy_sz);
>>       ta_sm = (struct ta_pmf_shared_memory *)dev->shbuf;
>> +    out = &ta_sm->pmf_output.policy_apply_table;
>> +
>>       memset(ta_sm, 0, sizeof(struct ta_pmf_shared_memory));
>>       ta_sm->command_id =
>> TA_PMF_COMMAND_POLICY_BUILDER__ENACT_POLICIES;
>>       ta_sm->if_version = PMF_TA_IF_VERSION__MAJOR;
>> @@ -65,6 +136,12 @@ static int amd_pmf_invoke_cmd_enact(struct
>> amd_pmf_dev *dev)
>>           return -EINVAL;
>>       }
>>   +    if (ta_sm->pmf_result == TA_PMF_TYPE__SUCCESS &&
>> out->actions_count) {
>> +        dev_dbg(dev->dev, "action count:%d result:%x\n",
>> out->actions_count,
>> +            ta_sm->pmf_result);
>> +        amd_pmf_apply_policies(dev, out);
>> +    }
>> +
>>       return 0;
>>   }
>>   @@ -72,6 +149,7 @@ static int amd_pmf_invoke_cmd_init(struct
>> amd_pmf_dev *dev)
>>   {
>>       struct ta_pmf_shared_memory *ta_sm = NULL;
>>       struct tee_param param[MAX_TEE_PARAM];
>> +    struct ta_pmf_init_table *in = NULL;
>>       struct tee_ioctl_invoke_arg arg;
>>       int ret = 0;
>>   @@ -80,10 +158,20 @@ static int amd_pmf_invoke_cmd_init(struct
>> amd_pmf_dev *dev)
>>           return -ENODEV;
>>       }
>>   +    dev_dbg(dev->dev, "Policy Binary size: %d bytes\n",
>> dev->policy_sz);
>> +    memset(dev->shbuf, 0, dev->policy_sz);
>>       ta_sm = (struct ta_pmf_shared_memory *)dev->shbuf;
>> +    in = &ta_sm->pmf_input.init_table;
>> +
>>       ta_sm->command_id = TA_PMF_COMMAND_POLICY_BUILDER__INITIALIZE;
>>       ta_sm->if_version = PMF_TA_IF_VERSION__MAJOR;
>> +    in->metadata_macrocheck = false;
>> +    in->sku_check = false;
>> +    in->validate = true;
>> +    in->frequency = pb_actions_ms;
>> +    in->policies_table.table_size = dev->policy_sz;
>>   +    memcpy(in->policies_table.table, dev->policy_buf,
>> dev->policy_sz);
>>       amd_pmf_prepare_args(dev,
>> TA_PMF_COMMAND_POLICY_BUILDER__INITIALIZE, &arg, param);
>>         ret = tee_client_invoke_func(dev->tee_ctx, &arg, param);
>> @@ -103,6 +191,47 @@ static void amd_pmf_invoke_cmd(struct
>> work_struct *work)
>>       schedule_delayed_work(&dev->pb_work,
>> msecs_to_jiffies(pb_actions_ms));
>>   }
>>   +static int amd_pmf_start_policy_engine(struct amd_pmf_dev *dev)
>> +{
>> +    u32 cookie, length;
>> +    int res;
>> +
>> +    cookie = readl(dev->policy_buf + 0x10);
>> +    length = readl(dev->policy_buf + 0x14);
>> +
>> +    if (cookie != POLICY_SIGN_COOKIE || !length)
>> +        return -EINVAL;
>> +
>> +    /* update the actual length */
>> +    dev->policy_sz = length + 512;
>> +    res = amd_pmf_invoke_cmd_init(dev);
>> +    if (res == TA_PMF_TYPE__SUCCESS) {
>> +        /* now its safe to announce that smart pc is enabled */
>> +        dev->smart_pc_enabled = 1;
>> +        schedule_delayed_work(&dev->pb_work,
>> msecs_to_jiffies(pb_actions_ms * 3));
>> +    } else {
>> +        dev_err(dev->dev, "%s ta invoke_cmd_init failed err: %x\n",
>> __func__, res);
>> +        return res;
>> +    }
>> +
>> +    return 0;
>> +}
>> +
>> +static int amd_pmf_get_bios_buffer(struct amd_pmf_dev *dev)
>> +{
>> +    dev->policy_buf = kzalloc(dev->policy_sz, GFP_KERNEL);
>> +    if (!dev->policy_buf)
>> +        return -ENOMEM;
>> +
>> +    dev->policy_base = ioremap(dev->policy_addr, dev->policy_sz);
>> +    if (!dev->policy_base)
>> +        return -ENOMEM;
>> +
>> +    memcpy(dev->policy_buf, dev->policy_base, dev->policy_sz);
>> +
>> +    return amd_pmf_start_policy_engine(dev);
>> +}
>> +
>>   static int amd_pmf_amdtee_ta_match(struct tee_ioctl_version_data
>> *ver, const void *data)
>>   {
>>       return ver->impl_id == TEE_IMPL_ID_AMDTEE;
>> @@ -149,7 +278,7 @@ static int amd_pmf_tee_init(struct amd_pmf_dev
>> *dev)
>>           goto out_ctx;
>>       }
>>   -    size = sizeof(struct ta_pmf_shared_memory);
>> +    size = sizeof(struct ta_pmf_shared_memory) + dev->policy_sz;
>>       dev->fw_shm_pool = tee_shm_alloc_kernel_buf(dev->tee_ctx, size);
>>       if (IS_ERR(dev->fw_shm_pool)) {
>>           dev_err(dev->dev, "%s: tee_shm_alloc_kernel_buf failed\n",
>> __func__);
>> @@ -191,11 +320,19 @@ int amd_pmf_init_smart_pc(struct amd_pmf_dev
>> *dev)
>>           return ret;
>>         INIT_DELAYED_WORK(&dev->pb_work, amd_pmf_invoke_cmd);
>> -    return 0;
>> +    amd_pmf_set_dram_addr(dev);
>> +    amd_pmf_get_bios_buffer(dev);
>> +    dev->prev_data = kzalloc(sizeof(*dev->prev_data), GFP_KERNEL);
>> +    if (!dev->prev_data)
>> +        return -ENOMEM;
>> +
>> +    return dev->smart_pc_enabled;
>>   }
>>     void amd_pmf_deinit_smart_pc(struct amd_pmf_dev *dev)
>>   {
>> +    kfree(dev->prev_data);
>> +    kfree(dev->policy_buf);
>>       cancel_delayed_work_sync(&dev->pb_work);
>>       amd_pmf_tee_deinit(dev);
>>   }
> 

^ permalink raw reply	[flat|nested] 54+ messages in thread

* Re: [PATCH 11/15] platform/x86/amd/pmf: dump policy binary data
  2023-09-22 19:01   ` Mario Limonciello
@ 2023-09-30  4:41     ` Shyam Sundar S K
  0 siblings, 0 replies; 54+ messages in thread
From: Shyam Sundar S K @ 2023-09-30  4:41 UTC (permalink / raw)
  To: Mario Limonciello, hdegoede, markgross, basavaraj.natikar, jikos,
	benjamin.tissoires, alexander.deucher, christian.koenig,
	Xinhui.Pan, airlied, daniel
  Cc: dri-devel, linux-input, amd-gfx, Patil.Reddy, platform-driver-x86



On 9/23/2023 12:31 AM, Mario Limonciello wrote:
> On 9/22/2023 12:50, Shyam Sundar S K wrote:
>> Sometimes policy binary retrieved from the BIOS maybe incorrect that
>> can
>> end up in failing to enable the Smart PC solution feature.
>>
>> Use print_hex_dump_debug() to dump the policy binary in hex, so that we
>> debug the issues related to the binary even before sending that to TA.
>>
>> Signed-off-by: Shyam Sundar S K <Shyam-sundar.S-k@amd.com>
>> ---
>>   drivers/platform/x86/amd/pmf/tee-if.c | 7 +++++++
>>   1 file changed, 7 insertions(+)
>>
>> diff --git a/drivers/platform/x86/amd/pmf/tee-if.c
>> b/drivers/platform/x86/amd/pmf/tee-if.c
>> index fa37cfab2dc7..3daa122f35d5 100644
>> --- a/drivers/platform/x86/amd/pmf/tee-if.c
>> +++ b/drivers/platform/x86/amd/pmf/tee-if.c
>> @@ -290,6 +290,9 @@ static ssize_t amd_pmf_get_pb_data(struct file
>> *filp, const char __user *buf,
>>       if (copy_from_user(dev->policy_buf, buf, dev->policy_sz))
>>           return -EFAULT;
>>   +    print_hex_dump_debug("(pb):  ", DUMP_PREFIX_OFFSET, 16, 1,
>> dev->policy_buf,
>> +                 dev->policy_sz, false);
>> +
> 
> Should this one also be guarded by CONFIG_AMD_PMF_DEBUG or no?

No, as this dump is called from amd_pmf_get_pb_data() which is already
under CONFIG_AMD_PMF_DEBUG.

> 
>>       ret = amd_pmf_start_policy_engine(dev);
>>       if (ret)
>>           return -EINVAL;
>> @@ -329,6 +332,10 @@ static int amd_pmf_get_bios_buffer(struct
>> amd_pmf_dev *dev)
>>           return -ENOMEM;
>>         memcpy(dev->policy_buf, dev->policy_base, dev->policy_sz);
>> +#ifdef CONFIG_AMD_PMF_DEBUG
>> +    print_hex_dump_debug("(pb):  ", DUMP_PREFIX_OFFSET, 16, 1,
>> dev->policy_buf,
>> +                 dev->policy_sz, false);
>> +#endif
>>     #ifdef CONFIG_AMD_PMF_DEBUG
>>       if (pb_side_load)
> 
> It looks like you can combine the two #ifdef from the previous patches.

Thank you, I have addressed this in v2.

Thanks,
Shyam


^ permalink raw reply	[flat|nested] 54+ messages in thread

* Re: [PATCH 06/15] platform/x86/amd/pmf: Add support to get inputs from other subsystems
  2023-09-26 17:08   ` Ilpo Järvinen
@ 2023-09-30  8:40     ` Shyam Sundar S K
  2023-10-02  9:10       ` Ilpo Järvinen
  0 siblings, 1 reply; 54+ messages in thread
From: Shyam Sundar S K @ 2023-09-30  8:40 UTC (permalink / raw)
  To: Ilpo Järvinen
  Cc: Xinhui.Pan, Patil.Reddy, basavaraj.natikar, dri-devel, jikos,
	amd-gfx, platform-driver-x86, markgross, hdegoede,
	benjamin.tissoires, mario.limonciello, linux-input,
	alexander.deucher, christian.koenig



On 9/26/2023 10:38 PM, Ilpo Järvinen wrote:
> On Fri, 22 Sep 2023, Shyam Sundar S K wrote:
> 
>> PMF driver sends changing inputs from each subystem to TA for evaluating
>> the conditions in the policy binary.
>>
>> Add initial support of plumbing in the PMF driver for Smart PC to get
>> information from other subsystems in the kernel.
>>
>> Signed-off-by: Shyam Sundar S K <Shyam-sundar.S-k@amd.com>
>> ---
>>  drivers/platform/x86/amd/pmf/Makefile |   2 +-
>>  drivers/platform/x86/amd/pmf/pmf.h    |  18 ++++
>>  drivers/platform/x86/amd/pmf/spc.c    | 118 ++++++++++++++++++++++++++
>>  drivers/platform/x86/amd/pmf/tee-if.c |   3 +
>>  4 files changed, 140 insertions(+), 1 deletion(-)
>>  create mode 100644 drivers/platform/x86/amd/pmf/spc.c
>>
>> diff --git a/drivers/platform/x86/amd/pmf/Makefile b/drivers/platform/x86/amd/pmf/Makefile
>> index d2746ee7369f..6b26e48ce8ad 100644
>> --- a/drivers/platform/x86/amd/pmf/Makefile
>> +++ b/drivers/platform/x86/amd/pmf/Makefile
>> @@ -7,4 +7,4 @@
>>  obj-$(CONFIG_AMD_PMF) += amd-pmf.o
>>  amd-pmf-objs := core.o acpi.o sps.o \
>>  		auto-mode.o cnqf.o \
>> -		tee-if.o
>> +		tee-if.o spc.o
>> diff --git a/drivers/platform/x86/amd/pmf/pmf.h b/drivers/platform/x86/amd/pmf/pmf.h
>> index 81acf2a37366..e64b4d285624 100644
>> --- a/drivers/platform/x86/amd/pmf/pmf.h
>> +++ b/drivers/platform/x86/amd/pmf/pmf.h
>> @@ -146,6 +146,21 @@ struct smu_pmf_metrics {
>>  	u16 infra_gfx_maxfreq; /* in MHz */
>>  	u16 skin_temp; /* in centi-Celsius */
>>  	u16 device_state;
>> +	u16 curtemp; /* in centi-Celsius */
>> +	u16 filter_alpha_value;
>> +	u16 avg_gfx_clkfrequency;
>> +	u16 avg_fclk_frequency;
>> +	u16 avg_gfx_activity;
>> +	u16 avg_socclk_frequency;
>> +	u16 avg_vclk_frequency;
>> +	u16 avg_vcn_activity;
>> +	u16 avg_dram_reads;
>> +	u16 avg_dram_writes;
>> +	u16 avg_socket_power;
>> +	u16 avg_core_power[2];
>> +	u16 avg_core_c0residency[16];
>> +	u16 spare1;
>> +	u32 metrics_counter;
>>  } __packed;
>>  
>>  enum amd_stt_skin_temp {
>> @@ -592,4 +607,7 @@ extern const struct attribute_group cnqf_feature_attribute_group;
>>  int amd_pmf_init_smart_pc(struct amd_pmf_dev *dev);
>>  void amd_pmf_deinit_smart_pc(struct amd_pmf_dev *dev);
>>  int apmf_check_smart_pc(struct amd_pmf_dev *pmf_dev);
>> +
>> +/* Smart PC - TA interfaces */
>> +void amd_pmf_populate_ta_inputs(struct amd_pmf_dev *dev, struct ta_pmf_enact_table *in);
>>  #endif /* PMF_H */
>> diff --git a/drivers/platform/x86/amd/pmf/spc.c b/drivers/platform/x86/amd/pmf/spc.c
>> new file mode 100644
>> index 000000000000..08159cd5f853
>> --- /dev/null
>> +++ b/drivers/platform/x86/amd/pmf/spc.c
>> @@ -0,0 +1,118 @@
>> +// SPDX-License-Identifier: GPL-2.0
>> +/*
>> + * AMD Platform Management Framework Driver - Smart PC Capabilities
>> + *
>> + * Copyright (c) 2023, Advanced Micro Devices, Inc.
>> + * All Rights Reserved.
>> + *
>> + * Authors: Shyam Sundar S K <Shyam-sundar.S-k@amd.com>
>> + *          Patil Rajesh Reddy <Patil.Reddy@amd.com>
>> + */
>> +
>> +#include <acpi/button.h>
>> +#include <linux/power_supply.h>
>> +#include "pmf.h"
>> +
>> +static void amd_pmf_get_smu_info(struct amd_pmf_dev *dev, struct ta_pmf_enact_table *in)
>> +{
>> +	u16 max, avg = 0;
>> +	int i;
>> +
>> +	memset(dev->buf, 0, sizeof(dev->m_table));
>> +	amd_pmf_send_cmd(dev, SET_TRANSFER_TABLE, 0, 7, NULL);
>> +	memcpy(&dev->m_table, dev->buf, sizeof(dev->m_table));
>> +
>> +	in->ev_info.socket_power = dev->m_table.apu_power + dev->m_table.dgpu_power;
>> +	in->ev_info.skin_temperature = dev->m_table.skin_temp;
>> +
>> +	/* get the avg C0 residency of all the cores */
>> +	for (i = 0; i < ARRAY_SIZE(dev->m_table.avg_core_c0residency); i++)
>> +		avg += dev->m_table.avg_core_c0residency[i];
> 
> Is this safe from overflow?

Yes I think. Can you elaborate a bit more please if there a overflow
and I am missing it?

Thanks,
Shyam

> 
>> +
>> +	/* get the max C0 residency of all the cores */
>> +	max = dev->m_table.avg_core_c0residency[0];
>> +	for (i = 1; i < ARRAY_SIZE(dev->m_table.avg_core_c0residency); i++) {
>> +		if (dev->m_table.avg_core_c0residency[i] > max)
>> +			max = dev->m_table.avg_core_c0residency[i];
>> +	}
>> +
>> +	in->ev_info.avg_c0residency = avg / ARRAY_SIZE(dev->m_table.avg_core_c0residency);
>> +	in->ev_info.max_c0residency = max;
>> +	in->ev_info.gfx_busy = dev->m_table.avg_gfx_activity;
>> +}
>> +
>> +static const char * const pmf_battery_supply_name[] = {
>> +	"BATT",
>> +	"BAT0",
>> +};
>> +
>> +static int get_battery_prop(enum power_supply_property prop)
>> +{
>> +	union power_supply_propval value;
>> +	struct power_supply *psy;
>> +	int i, ret = -EINVAL;
>> +
>> +	for (i = 0; i < ARRAY_SIZE(pmf_battery_supply_name); i++) {
>> +		psy = power_supply_get_by_name(pmf_battery_supply_name[i]);
>> +		if (!psy)
>> +			continue;
>> +
>> +		ret = power_supply_get_property(psy, prop, &value);
>> +		if (ret) {
>> +			power_supply_put(psy);
>> +			return ret;
>> +		}
>> +	}
>> +
>> +	return value.intval;
>> +}
>> +
>> +static int amd_pmf_get_battery_info(struct amd_pmf_dev *dev, struct ta_pmf_enact_table *in)
>> +{
>> +	int val;
>> +
>> +	val = get_battery_prop(POWER_SUPPLY_PROP_PRESENT);
>> +	if (val != 1)
>> +		return -EINVAL;
>> +
>> +	in->ev_info.bat_percentage = get_battery_prop(POWER_SUPPLY_PROP_CAPACITY);
>> +	/* all values in mWh metrics */
>> +	in->ev_info.bat_design = get_battery_prop(POWER_SUPPLY_PROP_ENERGY_FULL_DESIGN) / 1000;
>> +	in->ev_info.full_charge_capacity = get_battery_prop(POWER_SUPPLY_PROP_ENERGY_FULL) / 1000;
>> +	in->ev_info.drain_rate = get_battery_prop(POWER_SUPPLY_PROP_POWER_NOW) / 1000;
> 
> You don't need literal, use the defines provided in linux/units.h.
> 
>> +
>> +	return 0;
>> +}
>> +
>> +static int amd_pmf_get_slider_info(struct amd_pmf_dev *dev, struct ta_pmf_enact_table *in)
>> +{
>> +	int val;
>> +
>> +	switch (dev->current_profile) {
>> +	case PLATFORM_PROFILE_PERFORMANCE:
>> +		val = TA_BEST_PERFORMANCE;
>> +		break;
>> +	case PLATFORM_PROFILE_BALANCED:
>> +		val = TA_BETTER_PERFORMANCE;
>> +		break;
>> +	case PLATFORM_PROFILE_LOW_POWER:
>> +		val = TA_BEST_BATTERY;
>> +		break;
>> +	default:
>> +		dev_err(dev->dev, "Unknown Platform Profile.\n");
>> +		return -EOPNOTSUPP;
>> +	}
>> +	in->ev_info.power_slider = val;
>> +
>> +	return 0;
>> +}
>> +
>> +void amd_pmf_populate_ta_inputs(struct amd_pmf_dev *dev, struct ta_pmf_enact_table *in)
>> +{
>> +	/* TA side lid open is 1 and close is 0, hence the ! here */
>> +	in->ev_info.lid_state = !acpi_lid_open();
>> +	in->ev_info.power_source = amd_pmf_get_power_source();
>> +	amd_pmf_get_smu_info(dev, in);
>> +	amd_pmf_get_battery_info(dev, in);
>> +	amd_pmf_get_slider_info(dev, in);
>> +}
>> diff --git a/drivers/platform/x86/amd/pmf/tee-if.c b/drivers/platform/x86/amd/pmf/tee-if.c
>> index a8b05e746efd..eb25d5ce3a9a 100644
>> --- a/drivers/platform/x86/amd/pmf/tee-if.c
>> +++ b/drivers/platform/x86/amd/pmf/tee-if.c
>> @@ -113,6 +113,7 @@ static int amd_pmf_invoke_cmd_enact(struct amd_pmf_dev *dev)
>>  {
>>  	struct ta_pmf_shared_memory *ta_sm = NULL;
>>  	struct ta_pmf_enact_result *out = NULL;
>> +	struct ta_pmf_enact_table *in = NULL;
>>  	struct tee_param param[MAX_TEE_PARAM];
>>  	struct tee_ioctl_invoke_arg arg;
>>  	int ret = 0;
>> @@ -123,11 +124,13 @@ static int amd_pmf_invoke_cmd_enact(struct amd_pmf_dev *dev)
>>  	memset(dev->shbuf, 0, dev->policy_sz);
>>  	ta_sm = (struct ta_pmf_shared_memory *)dev->shbuf;
>>  	out = &ta_sm->pmf_output.policy_apply_table;
>> +	in = &ta_sm->pmf_input.enact_table;
>>  
>>  	memset(ta_sm, 0, sizeof(struct ta_pmf_shared_memory));
>>  	ta_sm->command_id = TA_PMF_COMMAND_POLICY_BUILDER__ENACT_POLICIES;
>>  	ta_sm->if_version = PMF_TA_IF_VERSION__MAJOR;
>>  
>> +	amd_pmf_populate_ta_inputs(dev, in);
>>  	amd_pmf_prepare_args(dev, TA_PMF_COMMAND_POLICY_BUILDER__ENACT_POLICIES, &arg, param);
>>  
>>  	ret = tee_client_invoke_func(dev->tee_ctx, &arg, param);
>>
> 

^ permalink raw reply	[flat|nested] 54+ messages in thread

* Re: [PATCH 06/15] platform/x86/amd/pmf: Add support to get inputs from other subsystems
  2023-09-30  8:40     ` Shyam Sundar S K
@ 2023-10-02  9:10       ` Ilpo Järvinen
  0 siblings, 0 replies; 54+ messages in thread
From: Ilpo Järvinen @ 2023-10-02  9:10 UTC (permalink / raw)
  To: Shyam Sundar S K
  Cc: Xinhui.Pan, Patil.Reddy, basavaraj.natikar, dri-devel, jikos,
	amd-gfx, platform-driver-x86, markgross, Hans de Goede,
	benjamin.tissoires, mario.limonciello, linux-input,
	alexander.deucher, christian.koenig

[-- Attachment #1: Type: text/plain, Size: 8828 bytes --]

On Sat, 30 Sep 2023, Shyam Sundar S K wrote:
> On 9/26/2023 10:38 PM, Ilpo Järvinen wrote:
> > On Fri, 22 Sep 2023, Shyam Sundar S K wrote:
> > 
> >> PMF driver sends changing inputs from each subystem to TA for evaluating
> >> the conditions in the policy binary.
> >>
> >> Add initial support of plumbing in the PMF driver for Smart PC to get
> >> information from other subsystems in the kernel.
> >>
> >> Signed-off-by: Shyam Sundar S K <Shyam-sundar.S-k@amd.com>
> >> ---
> >>  drivers/platform/x86/amd/pmf/Makefile |   2 +-
> >>  drivers/platform/x86/amd/pmf/pmf.h    |  18 ++++
> >>  drivers/platform/x86/amd/pmf/spc.c    | 118 ++++++++++++++++++++++++++
> >>  drivers/platform/x86/amd/pmf/tee-if.c |   3 +
> >>  4 files changed, 140 insertions(+), 1 deletion(-)
> >>  create mode 100644 drivers/platform/x86/amd/pmf/spc.c
> >>
> >> diff --git a/drivers/platform/x86/amd/pmf/Makefile b/drivers/platform/x86/amd/pmf/Makefile
> >> index d2746ee7369f..6b26e48ce8ad 100644
> >> --- a/drivers/platform/x86/amd/pmf/Makefile
> >> +++ b/drivers/platform/x86/amd/pmf/Makefile
> >> @@ -7,4 +7,4 @@
> >>  obj-$(CONFIG_AMD_PMF) += amd-pmf.o
> >>  amd-pmf-objs := core.o acpi.o sps.o \
> >>  		auto-mode.o cnqf.o \
> >> -		tee-if.o
> >> +		tee-if.o spc.o
> >> diff --git a/drivers/platform/x86/amd/pmf/pmf.h b/drivers/platform/x86/amd/pmf/pmf.h
> >> index 81acf2a37366..e64b4d285624 100644
> >> --- a/drivers/platform/x86/amd/pmf/pmf.h
> >> +++ b/drivers/platform/x86/amd/pmf/pmf.h
> >> @@ -146,6 +146,21 @@ struct smu_pmf_metrics {
> >>  	u16 infra_gfx_maxfreq; /* in MHz */
> >>  	u16 skin_temp; /* in centi-Celsius */
> >>  	u16 device_state;
> >> +	u16 curtemp; /* in centi-Celsius */
> >> +	u16 filter_alpha_value;
> >> +	u16 avg_gfx_clkfrequency;
> >> +	u16 avg_fclk_frequency;
> >> +	u16 avg_gfx_activity;
> >> +	u16 avg_socclk_frequency;
> >> +	u16 avg_vclk_frequency;
> >> +	u16 avg_vcn_activity;
> >> +	u16 avg_dram_reads;
> >> +	u16 avg_dram_writes;
> >> +	u16 avg_socket_power;
> >> +	u16 avg_core_power[2];
> >> +	u16 avg_core_c0residency[16];
> >> +	u16 spare1;
> >> +	u32 metrics_counter;
> >>  } __packed;
> >>  
> >>  enum amd_stt_skin_temp {
> >> @@ -592,4 +607,7 @@ extern const struct attribute_group cnqf_feature_attribute_group;
> >>  int amd_pmf_init_smart_pc(struct amd_pmf_dev *dev);
> >>  void amd_pmf_deinit_smart_pc(struct amd_pmf_dev *dev);
> >>  int apmf_check_smart_pc(struct amd_pmf_dev *pmf_dev);
> >> +
> >> +/* Smart PC - TA interfaces */
> >> +void amd_pmf_populate_ta_inputs(struct amd_pmf_dev *dev, struct ta_pmf_enact_table *in);
> >>  #endif /* PMF_H */
> >> diff --git a/drivers/platform/x86/amd/pmf/spc.c b/drivers/platform/x86/amd/pmf/spc.c
> >> new file mode 100644
> >> index 000000000000..08159cd5f853
> >> --- /dev/null
> >> +++ b/drivers/platform/x86/amd/pmf/spc.c
> >> @@ -0,0 +1,118 @@
> >> +// SPDX-License-Identifier: GPL-2.0
> >> +/*
> >> + * AMD Platform Management Framework Driver - Smart PC Capabilities
> >> + *
> >> + * Copyright (c) 2023, Advanced Micro Devices, Inc.
> >> + * All Rights Reserved.
> >> + *
> >> + * Authors: Shyam Sundar S K <Shyam-sundar.S-k@amd.com>
> >> + *          Patil Rajesh Reddy <Patil.Reddy@amd.com>
> >> + */
> >> +
> >> +#include <acpi/button.h>
> >> +#include <linux/power_supply.h>
> >> +#include "pmf.h"
> >> +
> >> +static void amd_pmf_get_smu_info(struct amd_pmf_dev *dev, struct ta_pmf_enact_table *in)
> >> +{
> >> +	u16 max, avg = 0;
> >> +	int i;
> >> +
> >> +	memset(dev->buf, 0, sizeof(dev->m_table));
> >> +	amd_pmf_send_cmd(dev, SET_TRANSFER_TABLE, 0, 7, NULL);
> >> +	memcpy(&dev->m_table, dev->buf, sizeof(dev->m_table));
> >> +
> >> +	in->ev_info.socket_power = dev->m_table.apu_power + dev->m_table.dgpu_power;
> >> +	in->ev_info.skin_temperature = dev->m_table.skin_temp;
> >> +
> >> +	/* get the avg C0 residency of all the cores */
> >> +	for (i = 0; i < ARRAY_SIZE(dev->m_table.avg_core_c0residency); i++)
> >> +		avg += dev->m_table.avg_core_c0residency[i];
> > 
> > Is this safe from overflow?
> 
> Yes I think. Can you elaborate a bit more please if there a overflow
> and I am missing it?

You're adding 16 * u16 together into a single u16 here. If it overflows, 
the average of averages calculated below will be pseudo-garbage. (I don't 
know what's the maximum value in the field so it could be safe).

> Thanks,
> Shyam
> 
> > 
> >> +
> >> +	/* get the max C0 residency of all the cores */
> >> +	max = dev->m_table.avg_core_c0residency[0];
> >> +	for (i = 1; i < ARRAY_SIZE(dev->m_table.avg_core_c0residency); i++) {
> >> +		if (dev->m_table.avg_core_c0residency[i] > max)
> >> +			max = dev->m_table.avg_core_c0residency[i];

Why this is done in the different loop? AFAICT, it could be in the same 
loop as avg calculation above. (I know you start from = 1 but it won't 
change the result when starting with 0 index).

> >> +	}
> >> +
> >> +	in->ev_info.avg_c0residency = avg / ARRAY_SIZE(dev->m_table.avg_core_c0residency);

-- 
 i.



> >> +	in->ev_info.max_c0residency = max;
> >> +	in->ev_info.gfx_busy = dev->m_table.avg_gfx_activity;
> >> +}
> >> +
> >> +static const char * const pmf_battery_supply_name[] = {
> >> +	"BATT",
> >> +	"BAT0",
> >> +};
> >> +
> >> +static int get_battery_prop(enum power_supply_property prop)
> >> +{
> >> +	union power_supply_propval value;
> >> +	struct power_supply *psy;
> >> +	int i, ret = -EINVAL;
> >> +
> >> +	for (i = 0; i < ARRAY_SIZE(pmf_battery_supply_name); i++) {
> >> +		psy = power_supply_get_by_name(pmf_battery_supply_name[i]);
> >> +		if (!psy)
> >> +			continue;
> >> +
> >> +		ret = power_supply_get_property(psy, prop, &value);
> >> +		if (ret) {
> >> +			power_supply_put(psy);
> >> +			return ret;
> >> +		}
> >> +	}
> >> +
> >> +	return value.intval;
> >> +}
> >> +
> >> +static int amd_pmf_get_battery_info(struct amd_pmf_dev *dev, struct ta_pmf_enact_table *in)
> >> +{
> >> +	int val;
> >> +
> >> +	val = get_battery_prop(POWER_SUPPLY_PROP_PRESENT);
> >> +	if (val != 1)
> >> +		return -EINVAL;
> >> +
> >> +	in->ev_info.bat_percentage = get_battery_prop(POWER_SUPPLY_PROP_CAPACITY);
> >> +	/* all values in mWh metrics */
> >> +	in->ev_info.bat_design = get_battery_prop(POWER_SUPPLY_PROP_ENERGY_FULL_DESIGN) / 1000;
> >> +	in->ev_info.full_charge_capacity = get_battery_prop(POWER_SUPPLY_PROP_ENERGY_FULL) / 1000;
> >> +	in->ev_info.drain_rate = get_battery_prop(POWER_SUPPLY_PROP_POWER_NOW) / 1000;
> > 
> > You don't need literal, use the defines provided in linux/units.h.
> > 
> >> +
> >> +	return 0;
> >> +}
> >> +
> >> +static int amd_pmf_get_slider_info(struct amd_pmf_dev *dev, struct ta_pmf_enact_table *in)
> >> +{
> >> +	int val;
> >> +
> >> +	switch (dev->current_profile) {
> >> +	case PLATFORM_PROFILE_PERFORMANCE:
> >> +		val = TA_BEST_PERFORMANCE;
> >> +		break;
> >> +	case PLATFORM_PROFILE_BALANCED:
> >> +		val = TA_BETTER_PERFORMANCE;
> >> +		break;
> >> +	case PLATFORM_PROFILE_LOW_POWER:
> >> +		val = TA_BEST_BATTERY;
> >> +		break;
> >> +	default:
> >> +		dev_err(dev->dev, "Unknown Platform Profile.\n");
> >> +		return -EOPNOTSUPP;
> >> +	}
> >> +	in->ev_info.power_slider = val;
> >> +
> >> +	return 0;
> >> +}
> >> +
> >> +void amd_pmf_populate_ta_inputs(struct amd_pmf_dev *dev, struct ta_pmf_enact_table *in)
> >> +{
> >> +	/* TA side lid open is 1 and close is 0, hence the ! here */
> >> +	in->ev_info.lid_state = !acpi_lid_open();
> >> +	in->ev_info.power_source = amd_pmf_get_power_source();
> >> +	amd_pmf_get_smu_info(dev, in);
> >> +	amd_pmf_get_battery_info(dev, in);
> >> +	amd_pmf_get_slider_info(dev, in);
> >> +}
> >> diff --git a/drivers/platform/x86/amd/pmf/tee-if.c b/drivers/platform/x86/amd/pmf/tee-if.c
> >> index a8b05e746efd..eb25d5ce3a9a 100644
> >> --- a/drivers/platform/x86/amd/pmf/tee-if.c
> >> +++ b/drivers/platform/x86/amd/pmf/tee-if.c
> >> @@ -113,6 +113,7 @@ static int amd_pmf_invoke_cmd_enact(struct amd_pmf_dev *dev)
> >>  {
> >>  	struct ta_pmf_shared_memory *ta_sm = NULL;
> >>  	struct ta_pmf_enact_result *out = NULL;
> >> +	struct ta_pmf_enact_table *in = NULL;
> >>  	struct tee_param param[MAX_TEE_PARAM];
> >>  	struct tee_ioctl_invoke_arg arg;
> >>  	int ret = 0;
> >> @@ -123,11 +124,13 @@ static int amd_pmf_invoke_cmd_enact(struct amd_pmf_dev *dev)
> >>  	memset(dev->shbuf, 0, dev->policy_sz);
> >>  	ta_sm = (struct ta_pmf_shared_memory *)dev->shbuf;
> >>  	out = &ta_sm->pmf_output.policy_apply_table;
> >> +	in = &ta_sm->pmf_input.enact_table;
> >>  
> >>  	memset(ta_sm, 0, sizeof(struct ta_pmf_shared_memory));
> >>  	ta_sm->command_id = TA_PMF_COMMAND_POLICY_BUILDER__ENACT_POLICIES;
> >>  	ta_sm->if_version = PMF_TA_IF_VERSION__MAJOR;
> >>  
> >> +	amd_pmf_populate_ta_inputs(dev, in);
> >>  	amd_pmf_prepare_args(dev, TA_PMF_COMMAND_POLICY_BUILDER__ENACT_POLICIES, &arg, param);
> >>  
> >>  	ret = tee_client_invoke_func(dev->tee_ctx, &arg, param);
> >>
> > 
> 

^ permalink raw reply	[flat|nested] 54+ messages in thread

end of thread, other threads:[~2023-10-02  9:15 UTC | newest]

Thread overview: 54+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2023-09-22 17:50 [PATCH 00/15] Introduce PMF Smart PC Solution Builder Feature Shyam Sundar S K
2023-09-22 17:50 ` [PATCH 01/15] platform/x86/amd/pmf: Add PMF TEE interface Shyam Sundar S K
2023-09-26 16:42   ` Ilpo Järvinen
2023-09-22 17:50 ` [PATCH 02/15] platform/x86/amd/pmf: Add support PMF-TA interaction Shyam Sundar S K
2023-09-26 16:48   ` Ilpo Järvinen
2023-09-22 17:50 ` [PATCH 03/15] platform/x86/amd/pmf: Change signature of amd_pmf_set_dram_addr Shyam Sundar S K
2023-09-26 16:52   ` Ilpo Järvinen
2023-09-22 17:50 ` [PATCH 04/15] platform/x86/amd/pmf: Add support for PMF Policy Binary Shyam Sundar S K
2023-09-22 18:51   ` Mario Limonciello
2023-09-30  3:55     ` Shyam Sundar S K
2023-09-26 17:05   ` Ilpo Järvinen
2023-09-27 12:19   ` Ilpo Järvinen
2023-09-22 17:50 ` [PATCH 05/15] platform/x86/amd/pmf: change debugfs init sequence Shyam Sundar S K
2023-09-26 16:53   ` Ilpo Järvinen
2023-09-22 17:50 ` [PATCH 06/15] platform/x86/amd/pmf: Add support to get inputs from other subsystems Shyam Sundar S K
2023-09-26 17:08   ` Ilpo Järvinen
2023-09-30  8:40     ` Shyam Sundar S K
2023-10-02  9:10       ` Ilpo Järvinen
2023-09-22 17:50 ` [PATCH 07/15] platform/x86/amd/pmf: Add support update p3t limit Shyam Sundar S K
2023-09-27 12:19   ` Ilpo Järvinen
2023-09-22 17:50 ` [PATCH 08/15] platform/x86/amd/pmf: Add support to update system state Shyam Sundar S K
2023-09-25 21:42   ` kernel test robot
2023-09-27 12:22   ` Ilpo Järvinen
2023-09-22 17:50 ` [PATCH 09/15] platform/x86/amd/pmf: Add facility to dump TA inputs Shyam Sundar S K
2023-09-27 12:25   ` Ilpo Järvinen
2023-09-22 17:50 ` [PATCH 10/15] platform/x86/amd/pmf: Add capability to sideload of policy binary Shyam Sundar S K
2023-09-25  2:14   ` kernel test robot
2023-09-27 12:33   ` Ilpo Järvinen
2023-09-22 17:50 ` [PATCH 11/15] platform/x86/amd/pmf: dump policy binary data Shyam Sundar S K
2023-09-22 19:01   ` Mario Limonciello
2023-09-30  4:41     ` Shyam Sundar S K
2023-09-22 17:50 ` [PATCH 12/15] platform/x86/amd/pmf: Add PMF-AMDGPU get interface Shyam Sundar S K
2023-09-27 12:54   ` Ilpo Järvinen
2023-09-22 17:50 ` [PATCH 13/15] platform/x86/amd/pmf: Add PMF-AMDGPU set interface Shyam Sundar S K
2023-09-25 16:27   ` Deucher, Alexander
2023-09-25 16:30     ` Mario Limonciello
2023-09-26 11:17       ` Shyam Sundar S K
2023-09-26 11:15     ` Shyam Sundar S K
2023-09-26 10:35   ` Hans de Goede
2023-09-26 11:24     ` Shyam Sundar S K
2023-09-26 12:56       ` Hans de Goede
2023-09-26 13:17         ` Christian König
2023-09-26 13:48           ` Shyam Sundar S K
2023-09-27 13:04           ` Hans de Goede
2023-09-27 13:47             ` Shyam Sundar S K
2023-09-27 13:36   ` Ilpo Järvinen
2023-09-22 17:50 ` [PATCH 14/15] platform/x86/amd/pmf: Add PMF-AMDSFH interface for HPD Shyam Sundar S K
2023-09-22 19:04   ` Mario Limonciello
2023-09-22 21:04     ` Mario Limonciello
2023-09-27 13:32   ` Ilpo Järvinen
2023-09-22 17:50 ` [PATCH 15/15] platform/x86/amd/pmf: Add PMF-AMDSFH interface for ALS Shyam Sundar S K
2023-09-22 19:06   ` Mario Limonciello
2023-09-27 13:33   ` Ilpo Järvinen
2023-09-27 13:48     ` Shyam Sundar S K

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).