dri-devel.lists.freedesktop.org archive mirror
 help / color / mirror / Atom feed
* [PATCH v4 00/17] Introduce PMF Smart PC Solution Builder Feature
@ 2023-10-18  7:02 Shyam Sundar S K
  2023-10-18  7:02 ` [PATCH v4 01/17] platform/x86/amd/pmf: Add PMF TEE interface Shyam Sundar S K
                   ` (16 more replies)
  0 siblings, 17 replies; 35+ messages in thread
From: Shyam Sundar S K @ 2023-10-18  7:02 UTC (permalink / raw)
  To: hdegoede, markgross, ilpo.jarvinen, 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.

v3->v4:
---------
- Split v3 9/16 into 2 patches, that addresses using generic fn names
- Add softdep [Ilpo] instead of request_module()
- return proper ACPI status [Mario]
- Update comments in code [Mario]
- Remove missed double _ remarks
- handle battery status branches [Ilpo]
- Address KASAN problems 

v2->v3:
---------
- Remove pci_get_device() for getting gpu handle
- add .suspend handler for pmf driver
- remove unwanted type caste
- Align comments, spaces etc.
- add wrapper for print_hex_dump_debug()
- Remove lkp tags in commit-msg
- Add macros for magic numbers
- use right format specifiers for printing
- propagate error codes back to the caller
- remove unwanted comments


v1->v2:
---------
- Remove __func__ macros
- Remove manual function names inside prints
- Handle tee_shm_get_va() failure
- Remove double _
- Add meaningful prints
- pass amd_pmf_set_dram_addr() failure errors
- Add more information to commit messages
- use right format specifiers
- use devm_ioremap() instead of ioremap()
- address unsigned long vs u32 problems
- Fix lkp reported issues
- Add amd_pmf_remove_pb() to remove the debugfs files created(if any).
- Make amd_pmf_open_pb() as static.
- Add cooling device APIs for controlling amdgpu backlight
- handle amd_pmf_apply_policies() failures
- Split v1 14/15 into 2 patches further
- use linux/units.h for better handling
- add "depends on" AMD_SFH_HID for interaction with SFH
- other cosmetic remarks

Basavaraj Natikar (3):
  HID: amd_sfh: rename float_to_int() to amd_sfh_float_to_int()
  platform/x86/amd/pmf: Add PMF-AMDSFH interface for HPD
  platform/x86/amd/pmf: Add PMF-AMDSFH interface for ALS

Shyam Sundar S K (14):
  platform/x86/amd/pmf: Add PMF TEE interface
  platform/x86/amd/pmf: Add support for PMF-TA interaction
  platform/x86/amd/pmf: Change return type of amd_pmf_set_dram_addr()
  platform/x86/amd/pmf: Add support for PMF Policy Binary
  platform/x86/amd/pmf: change amd_pmf_init_features() call 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: Make source_as_str() as non-static
  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/index.rst           |   1 +
 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       | 156 ++++++
 drivers/hid/amd-sfh-hid/amd_sfh_common.h      |   6 +
 drivers/hid/amd-sfh-hid/sfh1_1/amd_sfh_desc.c |  22 +-
 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          |   3 +
 drivers/platform/x86/amd/pmf/Makefile         |   3 +-
 drivers/platform/x86/amd/pmf/acpi.c           |  37 ++
 drivers/platform/x86/amd/pmf/core.c           |  64 ++-
 drivers/platform/x86/amd/pmf/pmf.h            | 208 +++++++
 drivers/platform/x86/amd/pmf/spc.c            | 198 +++++++
 drivers/platform/x86/amd/pmf/sps.c            |   5 +-
 drivers/platform/x86/amd/pmf/tee-if.c         | 508 ++++++++++++++++++
 include/linux/amd-pmf-io.h                    |  55 ++
 19 files changed, 1331 insertions(+), 28 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] 35+ messages in thread

* [PATCH v4 01/17] platform/x86/amd/pmf: Add PMF TEE interface
  2023-10-18  7:02 [PATCH v4 00/17] Introduce PMF Smart PC Solution Builder Feature Shyam Sundar S K
@ 2023-10-18  7:02 ` Shyam Sundar S K
  2023-10-18  7:02 ` [PATCH v4 02/17] platform/x86/amd/pmf: Add support for PMF-TA interaction Shyam Sundar S K
                   ` (15 subsequent siblings)
  16 siblings, 0 replies; 35+ messages in thread
From: Shyam Sundar S K @ 2023-10-18  7:02 UTC (permalink / raw)
  To: hdegoede, markgross, ilpo.jarvinen, 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/Kconfig  |   1 +
 drivers/platform/x86/amd/pmf/Makefile |   3 +-
 drivers/platform/x86/amd/pmf/core.c   |  10 ++-
 drivers/platform/x86/amd/pmf/pmf.h    |  16 ++++
 drivers/platform/x86/amd/pmf/tee-if.c | 105 ++++++++++++++++++++++++++
 5 files changed, 130 insertions(+), 5 deletions(-)
 create mode 100644 drivers/platform/x86/amd/pmf/tee-if.c

diff --git a/drivers/platform/x86/amd/pmf/Kconfig b/drivers/platform/x86/amd/pmf/Kconfig
index 3064bc8ea167..32a029e8db80 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 TEE
 	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/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..ec92d1cc0dac 100644
--- a/drivers/platform/x86/amd/pmf/core.c
+++ b/drivers/platform/x86/amd/pmf/core.c
@@ -309,13 +309,13 @@ 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)) {
+		dev_dbg(dev->dev, "Smart PC Solution Enabled\n");
+	} else if (is_apmf_func_supported(dev, APMF_FUNC_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) ||
 			  is_apmf_func_supported(dev, APMF_FUNC_DYN_SLIDER_DC)) {
-		/* Enable Cool n Quiet Framework (CnQF) */
 		ret = amd_pmf_init_cnqf(dev);
 		if (ret)
 			dev_warn(dev->dev, "CnQF Init failed\n");
@@ -330,7 +330,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..bd40458937ba 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..6ec8c3726624
--- /dev/null
+++ b/drivers/platform/x86/amd/pmf/tee-if.c
@@ -0,0 +1,105 @@
+// 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("Failed to open TEE session err:%#x, rc:%d\n", sess_arg.ret, rc);
+		return rc;
+	}
+
+	*id = sess_arg.session;
+
+	return rc;
+}
+
+static int amd_pmf_tee_init(struct amd_pmf_dev *dev)
+{
+	u32 size;
+	int ret;
+
+	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, "Failed to open TEE context\n");
+		return PTR_ERR(dev->tee_ctx);
+	}
+
+	ret = amd_pmf_ta_open_session(dev->tee_ctx, &dev->session_id);
+	if (ret) {
+		dev_err(dev->dev, "Failed to open TA session (%d)\n", 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, "Failed to alloc TEE shared memory\n");
+		ret = PTR_ERR(dev->fw_shm_pool);
+		goto out_sess;
+	}
+
+	dev->shbuf = tee_shm_get_va(dev->fw_shm_pool, 0);
+	if (IS_ERR(dev->shbuf)) {
+		dev_err(dev->dev, "Failed to get TEE virtual address\n");
+		ret = PTR_ERR(dev->shbuf);
+		goto out_shm;
+	}
+	dev_dbg(dev->dev, "TEE init done\n");
+
+	return 0;
+
+out_shm:
+	tee_shm_free(dev->fw_shm_pool);
+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)
+{
+	tee_shm_free(dev->fw_shm_pool);
+	tee_client_close_session(dev->tee_ctx, dev->session_id);
+	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] 35+ messages in thread

* [PATCH v4 02/17] platform/x86/amd/pmf: Add support for PMF-TA interaction
  2023-10-18  7:02 [PATCH v4 00/17] Introduce PMF Smart PC Solution Builder Feature Shyam Sundar S K
  2023-10-18  7:02 ` [PATCH v4 01/17] platform/x86/amd/pmf: Add PMF TEE interface Shyam Sundar S K
@ 2023-10-18  7:02 ` Shyam Sundar S K
  2023-10-18  7:02 ` [PATCH v4 03/17] platform/x86/amd/pmf: Change return type of amd_pmf_set_dram_addr() Shyam Sundar S K
                   ` (14 subsequent siblings)
  16 siblings, 0 replies; 35+ messages in thread
From: Shyam Sundar S K @ 2023-10-18  7:02 UTC (permalink / raw)
  To: hdegoede, markgross, ilpo.jarvinen, 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 bd40458937ba..a24e34e42032 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;
 
+/* Command 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 6ec8c3726624..4036f435f1e2 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 = MSEC_PER_SEC;
+#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 = dev->shbuf;
+	memset(ta_sm, 0, sizeof(*ta_sm));
+	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, "TEE enact cmd failed. err: %x, ret:%d\n", arg.ret, ret);
+		return ret;
+	}
+
+	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, "Failed to get TEE context\n");
+		return -ENODEV;
+	}
+
+	ta_sm = 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, "Failed to invoke TEE init cmd. err: %x, ret:%d\n", arg.ret, ret);
+		return ret;
+	}
+
+	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;
@@ -96,10 +183,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] 35+ messages in thread

* [PATCH v4 03/17] platform/x86/amd/pmf: Change return type of amd_pmf_set_dram_addr()
  2023-10-18  7:02 [PATCH v4 00/17] Introduce PMF Smart PC Solution Builder Feature Shyam Sundar S K
  2023-10-18  7:02 ` [PATCH v4 01/17] platform/x86/amd/pmf: Add PMF TEE interface Shyam Sundar S K
  2023-10-18  7:02 ` [PATCH v4 02/17] platform/x86/amd/pmf: Add support for PMF-TA interaction Shyam Sundar S K
@ 2023-10-18  7:02 ` Shyam Sundar S K
  2023-10-18  7:02 ` [PATCH v4 04/17] platform/x86/amd/pmf: Add support for PMF Policy Binary Shyam Sundar S K
                   ` (13 subsequent siblings)
  16 siblings, 0 replies; 35+ messages in thread
From: Shyam Sundar S K @ 2023-10-18  7:02 UTC (permalink / raw)
  To: hdegoede, markgross, ilpo.jarvinen, 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 the current code, the metrics table information was required only
for auto-mode or CnQF at a given time. Hence keeping the return type
of amd_pmf_set_dram_addr() as static made sense.

But with the addition of Smart PC builder feature, the metrics table
information has to be shared by the Smart PC also and this feature
resides outside of core.c.

To make amd_pmf_set_dram_addr() visible outside of core.c make it
as a non-static function and move the allocation of memory for
metrics table from amd_pmf_init_metrics_table() to amd_pmf_set_dram_addr()
as amd_pmf_set_dram_addr() is the common function to set the DRAM
address.

Add a suspend handler that can free up the allocated memory for getting
the metrics table information.

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 | 42 ++++++++++++++++++++++-------
 drivers/platform/x86/amd/pmf/pmf.h  |  1 +
 2 files changed, 34 insertions(+), 9 deletions(-)

diff --git a/drivers/platform/x86/amd/pmf/core.c b/drivers/platform/x86/amd/pmf/core.c
index ec92d1cc0dac..f50b7ec9a625 100644
--- a/drivers/platform/x86/amd/pmf/core.c
+++ b/drivers/platform/x86/amd/pmf/core.c
@@ -251,29 +251,35 @@ 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;
+	int ret;
 
 	INIT_DELAYED_WORK(&dev->work_buffer, amd_pmf_get_metrics);
 
-	amd_pmf_set_dram_addr(dev);
+	ret = amd_pmf_set_dram_addr(dev);
+	if (ret)
+		return ret;
 
 	/*
 	 * Start collecting the metrics data after a small delay
@@ -284,17 +290,35 @@ int amd_pmf_init_metrics_table(struct amd_pmf_dev *dev)
 	return 0;
 }
 
+static int amd_pmf_suspend_handler(struct device *dev)
+{
+	struct amd_pmf_dev *pdev = dev_get_drvdata(dev);
+
+	/*
+	 * Free the buffer allocated for storing the metrics table
+	 * information, as will have to allocate it freshly after
+	 * resume.
+	 */
+	kfree(pdev->buf);
+
+	return 0;
+}
+
 static int amd_pmf_resume_handler(struct device *dev)
 {
 	struct amd_pmf_dev *pdev = dev_get_drvdata(dev);
+	int ret;
 
-	if (pdev->buf)
-		amd_pmf_set_dram_addr(pdev);
+	if (pdev->buf) {
+		ret = amd_pmf_set_dram_addr(pdev);
+		if (ret)
+			return ret;
+	}
 
 	return 0;
 }
 
-static DEFINE_SIMPLE_DEV_PM_OPS(amd_pmf_pm, NULL, amd_pmf_resume_handler);
+static DEFINE_SIMPLE_DEV_PM_OPS(amd_pmf_pm, amd_pmf_suspend_handler, amd_pmf_resume_handler);
 
 static void amd_pmf_init_features(struct amd_pmf_dev *dev)
 {
diff --git a/drivers/platform/x86/amd/pmf/pmf.h b/drivers/platform/x86/amd/pmf/pmf.h
index a24e34e42032..6a0e4c446dd3 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] 35+ messages in thread

* [PATCH v4 04/17] platform/x86/amd/pmf: Add support for PMF Policy Binary
  2023-10-18  7:02 [PATCH v4 00/17] Introduce PMF Smart PC Solution Builder Feature Shyam Sundar S K
                   ` (2 preceding siblings ...)
  2023-10-18  7:02 ` [PATCH v4 03/17] platform/x86/amd/pmf: Change return type of amd_pmf_set_dram_addr() Shyam Sundar S K
@ 2023-10-18  7:02 ` Shyam Sundar S K
  2023-10-18  7:02 ` [PATCH v4 05/17] platform/x86/amd/pmf: change amd_pmf_init_features() call sequence Shyam Sundar S K
                   ` (12 subsequent siblings)
  16 siblings, 0 replies; 35+ messages in thread
From: Shyam Sundar S K @ 2023-10-18  7:02 UTC (permalink / raw)
  To: hdegoede, markgross, ilpo.jarvinen, 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 MODULE_SOFTDEP 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  |   2 +-
 drivers/platform/x86/amd/pmf/acpi.c   |  37 +++++++
 drivers/platform/x86/amd/pmf/core.c   |   9 ++
 drivers/platform/x86/amd/pmf/pmf.h    | 141 ++++++++++++++++++++++++
 drivers/platform/x86/amd/pmf/tee-if.c | 147 +++++++++++++++++++++++++-
 5 files changed, 333 insertions(+), 3 deletions(-)

diff --git a/drivers/platform/x86/amd/pmf/Kconfig b/drivers/platform/x86/amd/pmf/Kconfig
index 32a029e8db80..f246252bddd8 100644
--- a/drivers/platform/x86/amd/pmf/Kconfig
+++ b/drivers/platform/x86/amd/pmf/Kconfig
@@ -9,7 +9,7 @@ config AMD_PMF
 	depends on POWER_SUPPLY
 	depends on AMD_NB
 	select ACPI_PLATFORM_PROFILE
-	depends on TEE
+	depends on TEE && 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..4ec7957eb707 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 :%d\n", status);
+		return -EINVAL;
+	}
+
+	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 f50b7ec9a625..c8f6ec4c2e2c 100644
--- a/drivers/platform/x86/amd/pmf/core.c
+++ b/drivers/platform/x86/amd/pmf/core.c
@@ -395,6 +395,14 @@ static int amd_pmf_probe(struct platform_device *pdev)
 		return -ENOMEM;
 
 	dev->dev = &pdev->dev;
+	err = apmf_check_smart_pc(dev);
+	if (err)
+		/*
+		 * Lets not return from here if Smart PC bit is not advertised in
+		 * the BIOS. This way, there will be some amount of power savings
+		 * to the user with static slider (if enabled).
+		 */
+		pr_err("PMF Smart PC not advertised in BIOS!:%d\n", err);
 
 	rdev = pci_get_domain_bus_and_slot(0, 0, PCI_DEVFN(0, 0));
 	if (!rdev || !pci_match_id(pmf_pci_ids, rdev)) {
@@ -474,3 +482,4 @@ module_platform_driver(amd_pmf_driver);
 
 MODULE_LICENSE("GPL");
 MODULE_DESCRIPTION("AMD Platform Management Framework Driver");
+MODULE_SOFTDEP("pre: amdtee");
diff --git a/drivers/platform/x86/amd/pmf/pmf.h b/drivers/platform/x86/amd/pmf/pmf.h
index 6a0e4c446dd3..092be501d4d3 100644
--- a/drivers/platform/x86/amd/pmf/pmf.h
+++ b/drivers/platform/x86/amd/pmf/pmf.h
@@ -14,6 +14,11 @@
 #include <linux/acpi.h>
 #include <linux/platform_profile.h>
 
+#define POLICY_BUF_MAX_SZ		0x4b000
+#define POLICY_SIGN_COOKIE		0x31535024
+#define POLICY_COOKIE_OFFSET		0x10
+#define POLICY_COOKIE_LEN		0x14
+
 /* APMF Functions */
 #define APMF_FUNC_VERIFY_INTERFACE			0
 #define APMF_FUNC_GET_SYS_PARAMS			1
@@ -59,8 +64,21 @@
 #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 TA_OUTPUT_RESERVED_MEM				906
+#define MAX_OPERATION_PARAMS					4
 
 /* AMD PMF BIOS interfaces */
 struct apmf_verify_interface {
@@ -183,11 +201,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 +422,134 @@ struct apmf_dyn_slider_output {
 	struct apmf_cnqf_power_set ps[APMF_CNQF_MAX];
 } __packed;
 
+enum smart_pc_status {
+	PMF_SMART_PC_ENABLED,
+	PMF_SMART_PC_DISABLED,
+};
+
+/* Smart PC - TA internals */
+enum ta_slider {
+	TA_BEST_BATTERY,
+	TA_BETTER_BATTERY,
+	TA_BETTER_PERFORMANCE,
+	TA_BEST_PERFORMANCE,
+	TA_MAX,
+};
+
 /* Command 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 {
+	u32 spl;		/* in mW */
+	u32 sppt;		/* in mW */
+	u32 sppt_apuonly;	/* in mW */
+	u32 fppt;		/* in mW */
+	u32 stt_minlimit;	/* in mW */
+	u32 stt_skintemp_apu;	/* in C */
+	u32 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[TA_OUTPUT_RESERVED_MEM];
+};
+
 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 +600,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 4036f435f1e2..92290d51a4af 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 : %u\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 : %u\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 : %u\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 : %u\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 : %u\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 : %u\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 : %u\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 = dev->shbuf;
+	out = &ta_sm->pmf_output.policy_apply_table;
+
 	memset(ta_sm, 0, sizeof(*ta_sm));
 	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 ret;
 	}
 
+	if (ta_sm->pmf_result == TA_PMF_TYPE_SUCCESS && out->actions_count) {
+		dev_dbg(dev->dev, "action count:%u 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,21 @@ static int amd_pmf_invoke_cmd_init(struct amd_pmf_dev *dev)
 		return -ENODEV;
 	}
 
+	dev_dbg(dev->dev, "Policy Binary size: %u bytes\n", dev->policy_sz);
+	memset(dev->shbuf, 0, dev->policy_sz);
 	ta_sm = 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 +192,52 @@ 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 + POLICY_COOKIE_OFFSET);
+	length = readl(dev->policy_buf + POLICY_COOKIE_LEN);
+
+	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 = PMF_SMART_PC_ENABLED;
+		/*
+		 * Start collecting the data from TA FW after a small delay
+		 * or else, we might end up getting stale values.
+		 */
+		schedule_delayed_work(&dev->pb_work, msecs_to_jiffies(pb_actions_ms * 3));
+	} else {
+		dev_err(dev->dev, "ta invoke cmd init failed err: %x\n", res);
+		dev->smart_pc_enabled = PMF_SMART_PC_DISABLED;
+		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 = devm_ioremap(dev->dev, 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;
@@ -146,7 +281,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, "Failed to alloc TEE shared memory\n");
@@ -190,11 +325,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] 35+ messages in thread

* [PATCH v4 05/17] platform/x86/amd/pmf: change amd_pmf_init_features() call sequence
  2023-10-18  7:02 [PATCH v4 00/17] Introduce PMF Smart PC Solution Builder Feature Shyam Sundar S K
                   ` (3 preceding siblings ...)
  2023-10-18  7:02 ` [PATCH v4 04/17] platform/x86/amd/pmf: Add support for PMF Policy Binary Shyam Sundar S K
@ 2023-10-18  7:02 ` Shyam Sundar S K
  2023-10-18  7:02 ` [PATCH v4 06/17] platform/x86/amd/pmf: Add support to get inputs from other subsystems Shyam Sundar S K
                   ` (11 subsequent siblings)
  16 siblings, 0 replies; 35+ messages in thread
From: Shyam Sundar S K @ 2023-10-18  7:02 UTC (permalink / raw)
  To: hdegoede, markgross, ilpo.jarvinen, 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

To sideload pmf policy binaries, the Smart PC Solution Builder provides a
debugfs file called "update_policy"; that gets created under a new debugfs
directory called "pb" and this new directory has to be associated with
existing parent directory for PMF driver called "amd_pmf".

In the current code structure, amd_pmf_dbgfs_register() is called after
amd_pmf_init_features(). This will not help when the Smart PC builder
feature has to be assoicated to the parent directory.

Hence change the order of amd_pmf_dbgfs_register() and call it before
amd_pmf_init_features() so that when the Smart PC init happens, it has the
parent debugfs directory to get itself hooked.

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 c8f6ec4c2e2c..4b8156033fa6 100644
--- a/drivers/platform/x86/amd/pmf/core.c
+++ b/drivers/platform/x86/amd/pmf/core.c
@@ -442,9 +442,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] 35+ messages in thread

* [PATCH v4 06/17] platform/x86/amd/pmf: Add support to get inputs from other subsystems
  2023-10-18  7:02 [PATCH v4 00/17] Introduce PMF Smart PC Solution Builder Feature Shyam Sundar S K
                   ` (4 preceding siblings ...)
  2023-10-18  7:02 ` [PATCH v4 05/17] platform/x86/amd/pmf: change amd_pmf_init_features() call sequence Shyam Sundar S K
@ 2023-10-18  7:02 ` Shyam Sundar S K
  2023-10-18  7:02 ` [PATCH v4 07/17] platform/x86/amd/pmf: Add support update p3t limit Shyam Sundar S K
                   ` (10 subsequent siblings)
  16 siblings, 0 replies; 35+ messages in thread
From: Shyam Sundar S K @ 2023-10-18  7:02 UTC (permalink / raw)
  To: hdegoede, markgross, ilpo.jarvinen, 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    | 120 ++++++++++++++++++++++++++
 drivers/platform/x86/amd/pmf/tee-if.c |   3 +
 4 files changed, 142 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 092be501d4d3..a4a73b845c09 100644
--- a/drivers/platform/x86/amd/pmf/pmf.h
+++ b/drivers/platform/x86/amd/pmf/pmf.h
@@ -150,6 +150,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 {
@@ -601,4 +616,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..bd5061fdfdbe
--- /dev/null
+++ b/drivers/platform/x86/amd/pmf/spc.c
@@ -0,0 +1,120 @@
+// 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 <linux/units.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 and max C0 residency of all the cores */
+	max = dev->m_table.avg_core_c0residency[0];
+	for (i = 0; i < ARRAY_SIZE(dev->m_table.avg_core_c0residency); i++) {
+		avg += dev->m_table.avg_core_c0residency[i];
+		if (dev->m_table.avg_core_c0residency[i] > max)
+			max = dev->m_table.avg_core_c0residency[i];
+	}
+
+	avg = DIV_ROUND_CLOSEST(avg, ARRAY_SIZE(dev->m_table.avg_core_c0residency));
+	in->ev_info.avg_c0residency = avg;
+	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 amd_pmf_get_battery_prop(enum power_supply_property prop)
+{
+	union power_supply_propval value;
+	struct power_supply *psy;
+	int i, ret;
+
+	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 = amd_pmf_get_battery_prop(POWER_SUPPLY_PROP_PRESENT);
+	if (val >= 0 && val != 1)
+		return -ENODEV;
+
+	in->ev_info.bat_percentage = amd_pmf_get_battery_prop(POWER_SUPPLY_PROP_CAPACITY);
+	/* all values in mWh metrics */
+	in->ev_info.bat_design = amd_pmf_get_battery_prop(POWER_SUPPLY_PROP_ENERGY_FULL_DESIGN) /
+		MILLIWATT_PER_WATT;
+	in->ev_info.full_charge_capacity = amd_pmf_get_battery_prop(POWER_SUPPLY_PROP_ENERGY_FULL) /
+		MILLIWATT_PER_WATT;
+	in->ev_info.drain_rate = amd_pmf_get_battery_prop(POWER_SUPPLY_PROP_POWER_NOW) /
+		MILLIWATT_PER_WATT;
+
+	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 92290d51a4af..da6520f202e7 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 = dev->shbuf;
 	out = &ta_sm->pmf_output.policy_apply_table;
+	in = &ta_sm->pmf_input.enact_table;
 
 	memset(ta_sm, 0, sizeof(*ta_sm));
 	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] 35+ messages in thread

* [PATCH v4 07/17] platform/x86/amd/pmf: Add support update p3t limit
  2023-10-18  7:02 [PATCH v4 00/17] Introduce PMF Smart PC Solution Builder Feature Shyam Sundar S K
                   ` (5 preceding siblings ...)
  2023-10-18  7:02 ` [PATCH v4 06/17] platform/x86/amd/pmf: Add support to get inputs from other subsystems Shyam Sundar S K
@ 2023-10-18  7:02 ` Shyam Sundar S K
  2023-10-18  7:02 ` [PATCH v4 08/17] platform/x86/amd/pmf: Add support to update system state Shyam Sundar S K
                   ` (9 subsequent siblings)
  16 siblings, 0 replies; 35+ messages in thread
From: Shyam Sundar S K @ 2023-10-18  7:02 UTC (permalink / raw)
  To: hdegoede, markgross, ilpo.jarvinen, 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 a4a73b845c09..781989c7dddd 100644
--- a/drivers/platform/x86/amd/pmf/pmf.h
+++ b/drivers/platform/x86/amd/pmf/pmf.h
@@ -49,6 +49,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
@@ -72,6 +73,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
@@ -481,6 +483,7 @@ struct pmf_action_table {
 	u32 stt_minlimit;	/* in mW */
 	u32 stt_skintemp_apu;	/* in C */
 	u32 stt_skintemp_hs2;	/* in C */
+	u32 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 da6520f202e7..6f4a59950b27 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 : %u\n", val);
+				dev->prev_data->p3t_limit = val;
+			}
+			break;
 		}
 	}
 }
-- 
2.25.1


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

* [PATCH v4 08/17] platform/x86/amd/pmf: Add support to update system state
  2023-10-18  7:02 [PATCH v4 00/17] Introduce PMF Smart PC Solution Builder Feature Shyam Sundar S K
                   ` (6 preceding siblings ...)
  2023-10-18  7:02 ` [PATCH v4 07/17] platform/x86/amd/pmf: Add support update p3t limit Shyam Sundar S K
@ 2023-10-18  7:02 ` Shyam Sundar S K
  2023-10-18  7:02 ` [PATCH v4 09/17] platform/x86/amd/pmf: Make source_as_str() as non-static Shyam Sundar S K
                   ` (8 subsequent siblings)
  16 siblings, 0 replies; 35+ messages in thread
From: Shyam Sundar S K @ 2023-10-18  7:02 UTC (permalink / raw)
  To: hdegoede, markgross, ilpo.jarvinen, 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.

Reviewed-by: Mario Limonciello <mario.limonciello@amd.com>
Signed-off-by: Shyam Sundar S K <Shyam-sundar.S-k@amd.com>
---
 Documentation/admin-guide/index.rst   |  1 +
 Documentation/admin-guide/pmf.rst     | 24 +++++++++++++++++++
 drivers/platform/x86/amd/pmf/pmf.h    |  9 +++++++
 drivers/platform/x86/amd/pmf/tee-if.c | 34 +++++++++++++++++++++++++++
 4 files changed, 68 insertions(+)
 create mode 100644 Documentation/admin-guide/pmf.rst

diff --git a/Documentation/admin-guide/index.rst b/Documentation/admin-guide/index.rst
index 43ea35613dfc..fb40a1f6f79e 100644
--- a/Documentation/admin-guide/index.rst
+++ b/Documentation/admin-guide/index.rst
@@ -119,6 +119,7 @@ configure specific aspects of kernel behavior to your liking.
    parport
    perf-security
    pm/index
+   pmf
    pnp
    rapidio
    ras
diff --git a/Documentation/admin-guide/pmf.rst b/Documentation/admin-guide/pmf.rst
new file mode 100644
index 000000000000..9ee729ffc19b
--- /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}=="0", RUN+="/usr/bin/systemctl suspend"
+        DRIVERS=="amd-pmf", ACTION=="change", ENV{EVENT_ID}=="1", RUN+="/usr/bin/systemctl hibernate"
+        DRIVERS=="amd-pmf", ACTION=="change", ENV{EVENT_ID}=="2", RUN+="/bin/loginctl lock-sessions"
+
+EVENT_ID values:
+0= Put the system to S0i3/S2Idle
+1= Put the system to hibernate
+2= Lock the screen
diff --git a/drivers/platform/x86/amd/pmf/pmf.h b/drivers/platform/x86/amd/pmf/pmf.h
index 781989c7dddd..fb9ce2593236 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_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 */
@@ -445,6 +446,13 @@ enum smart_pc_status {
 };
 
 /* Smart PC - TA internals */
+enum system_state {
+	SYSTEM_STATE_S0i3,
+	SYSTEM_STATE_S4,
+	SYSTEM_STATE_SCREEN_LOCK,
+	SYSTEM_STATE_MAX,
+};
+
 enum ta_slider {
 	TA_BEST_BATTERY,
 	TA_BETTER_BATTERY,
@@ -476,6 +484,7 @@ enum ta_pmf_error_type {
 };
 
 struct pmf_action_table {
+	enum system_state system_state;
 	u32 spl;		/* in mW */
 	u32 sppt;		/* in mW */
 	u32 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 6f4a59950b27..d48f980fb1db 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,6 +56,20 @@ 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;
@@ -113,6 +141,12 @@ 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:
+			amd_pmf_update_uevents(dev, val);
+			dev_dbg(dev->dev, "update SYSTEM_STATE : %s\n",
+				amd_pmf_uevent_as_str(val));
+			break;
 		}
 	}
 }
-- 
2.25.1


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

* [PATCH v4 09/17] platform/x86/amd/pmf: Make source_as_str() as non-static
  2023-10-18  7:02 [PATCH v4 00/17] Introduce PMF Smart PC Solution Builder Feature Shyam Sundar S K
                   ` (7 preceding siblings ...)
  2023-10-18  7:02 ` [PATCH v4 08/17] platform/x86/amd/pmf: Add support to update system state Shyam Sundar S K
@ 2023-10-18  7:02 ` Shyam Sundar S K
  2023-10-18  7:02 ` [PATCH v4 10/17] platform/x86/amd/pmf: Add facility to dump TA inputs Shyam Sundar S K
                   ` (7 subsequent siblings)
  16 siblings, 0 replies; 35+ messages in thread
From: Shyam Sundar S K @ 2023-10-18  7:02 UTC (permalink / raw)
  To: hdegoede, markgross, ilpo.jarvinen, 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

Add amd_pmf prefix to source_as_str() function, so that the function name
does not look generic. As this is a helper function make it as non-static
so that it can be reused across multiple PMF features.

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/sps.c | 5 +++--
 2 files changed, 4 insertions(+), 2 deletions(-)

diff --git a/drivers/platform/x86/amd/pmf/pmf.h b/drivers/platform/x86/amd/pmf/pmf.h
index fb9ce2593236..216a9f795436 100644
--- a/drivers/platform/x86/amd/pmf/pmf.h
+++ b/drivers/platform/x86/amd/pmf/pmf.h
@@ -600,6 +600,7 @@ int apmf_get_static_slider_granular(struct amd_pmf_dev *pdev,
 				    struct apmf_static_slider_granular_output *output);
 bool is_pprof_balanced(struct amd_pmf_dev *pmf);
 int amd_pmf_power_slider_update_event(struct amd_pmf_dev *dev);
+const char *amd_pmf_source_as_str(unsigned int state);
 
 
 int apmf_update_fan_idx(struct amd_pmf_dev *pdev, bool manual, u32 idx);
diff --git a/drivers/platform/x86/amd/pmf/sps.c b/drivers/platform/x86/amd/pmf/sps.c
index a70e67749be3..33e23e25c8b1 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 *amd_pmf_source_as_str(unsigned int state)
 {
 	switch (state) {
 	case POWER_SOURCE_AC:
@@ -47,7 +47,8 @@ static void amd_pmf_dump_sps_defaults(struct amd_pmf_static_slider_granular *dat
 
 	for (i = 0; i < POWER_SOURCE_MAX; i++) {
 		for (j = 0; j < POWER_MODE_MAX; j++) {
-			pr_debug("--- Source:%s Mode:%s ---\n", source_as_str(i), slider_as_str(j));
+			pr_debug("--- Source:%s Mode:%s ---\n", amd_pmf_source_as_str(i),
+				 slider_as_str(j));
 			pr_debug("SPL: %u mW\n", data->prop[i][j].spl);
 			pr_debug("SPPT: %u mW\n", data->prop[i][j].sppt);
 			pr_debug("SPPT_ApuOnly: %u mW\n", data->prop[i][j].sppt_apu_only);
-- 
2.25.1


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

* [PATCH v4 10/17] platform/x86/amd/pmf: Add facility to dump TA inputs
  2023-10-18  7:02 [PATCH v4 00/17] Introduce PMF Smart PC Solution Builder Feature Shyam Sundar S K
                   ` (8 preceding siblings ...)
  2023-10-18  7:02 ` [PATCH v4 09/17] platform/x86/amd/pmf: Make source_as_str() as non-static Shyam Sundar S K
@ 2023-10-18  7:02 ` Shyam Sundar S K
  2023-10-18  9:00   ` Ilpo Järvinen
  2023-10-18  7:02 ` [PATCH v4 11/17] platform/x86/amd/pmf: Add capability to sideload of policy binary Shyam Sundar S K
                   ` (6 subsequent siblings)
  16 siblings, 1 reply; 35+ messages in thread
From: Shyam Sundar S K @ 2023-10-18  7:02 UTC (permalink / raw)
  To: hdegoede, markgross, ilpo.jarvinen, 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.

Also, make source_as_str() as non-static function as this helper is
required outside of sps.c file.

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/tee-if.c |  1 +
 3 files changed, 41 insertions(+)

diff --git a/drivers/platform/x86/amd/pmf/pmf.h b/drivers/platform/x86/amd/pmf/pmf.h
index 216a9f795436..593930519039 100644
--- a/drivers/platform/x86/amd/pmf/pmf.h
+++ b/drivers/platform/x86/amd/pmf/pmf.h
@@ -602,6 +602,7 @@ bool is_pprof_balanced(struct amd_pmf_dev *pmf);
 int amd_pmf_power_slider_update_event(struct amd_pmf_dev *dev);
 const char *amd_pmf_source_as_str(unsigned int state);
 
+const char *amd_pmf_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);
@@ -632,4 +633,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 bd5061fdfdbe..512e0c66efdc 100644
--- a/drivers/platform/x86/amd/pmf/spc.c
+++ b/drivers/platform/x86/amd/pmf/spc.c
@@ -14,6 +14,43 @@
 #include <linux/units.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", amd_pmf_source_as_str(in->ev_info.power_source));
+	dev_dbg(dev->dev, "Battery Percentage : %u\n", in->ev_info.bat_percentage);
+	dev_dbg(dev->dev, "Designed Battery Capacity : %u\n", in->ev_info.bat_design);
+	dev_dbg(dev->dev, "Fully Charged Capacity : %u\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 : %u\n", in->ev_info.socket_power);
+	dev_dbg(dev->dev, "Skin Temperature : %u\n", in->ev_info.skin_temperature);
+	dev_dbg(dev->dev, "Avg C0 Residency : %u\n", in->ev_info.avg_c0residency);
+	dev_dbg(dev->dev, "Max C0 Residency : %u\n", in->ev_info.max_c0residency);
+	dev_dbg(dev->dev, "GFX Busy : %u\n", in->ev_info.gfx_busy);
+	dev_dbg(dev->dev, "Connected Display Count : %u\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/tee-if.c b/drivers/platform/x86/amd/pmf/tee-if.c
index d48f980fb1db..0eba258f4040 100644
--- a/drivers/platform/x86/amd/pmf/tee-if.c
+++ b/drivers/platform/x86/amd/pmf/tee-if.c
@@ -182,6 +182,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:%u 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] 35+ messages in thread

* [PATCH v4 11/17] platform/x86/amd/pmf: Add capability to sideload of policy binary
  2023-10-18  7:02 [PATCH v4 00/17] Introduce PMF Smart PC Solution Builder Feature Shyam Sundar S K
                   ` (9 preceding siblings ...)
  2023-10-18  7:02 ` [PATCH v4 10/17] platform/x86/amd/pmf: Add facility to dump TA inputs Shyam Sundar S K
@ 2023-10-18  7:02 ` Shyam Sundar S K
  2023-10-18 10:21   ` Ilpo Järvinen
  2023-10-18  7:02 ` [PATCH v4 12/17] platform/x86/amd/pmf: dump policy binary data Shyam Sundar S K
                   ` (5 subsequent siblings)
  16 siblings, 1 reply; 35+ messages in thread
From: Shyam Sundar S K @ 2023-10-18  7:02 UTC (permalink / raw)
  To: hdegoede, markgross, ilpo.jarvinen, 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 | 67 +++++++++++++++++++++++++++
 2 files changed, 68 insertions(+)

diff --git a/drivers/platform/x86/amd/pmf/pmf.h b/drivers/platform/x86/amd/pmf/pmf.h
index 593930519039..8712299ad52b 100644
--- a/drivers/platform/x86/amd/pmf/pmf.h
+++ b/drivers/platform/x86/amd/pmf/pmf.h
@@ -219,6 +219,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 0eba258f4040..6c4ce22ba518 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"
@@ -16,9 +17,14 @@
 
 /* Policy binary actions sampling frequency (in ms) */
 static int pb_actions_ms = MSEC_PER_SEC;
+/* Sideload policy binaries to debug policy failures */
+static bool pb_side_load;
+
 #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)");
+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,
@@ -269,6 +275,61 @@ 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,
+};
+
+static 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;
+}
+
+static void amd_pmf_remove_pb(struct amd_pmf_dev *dev)
+{
+	debugfs_remove_recursive(dev->esbin);
+}
+#else
+static int amd_pmf_open_pb(struct amd_pmf_dev *dev, struct dentry *debugfs_root)
+{
+	return 0;
+}
+
+static void amd_pmf_remove_pb(struct amd_pmf_dev *dev) {}
+#endif
+
 static int amd_pmf_get_bios_buffer(struct amd_pmf_dev *dev)
 {
 	dev->policy_buf = kzalloc(dev->policy_sz, GFP_KERNEL);
@@ -281,6 +342,9 @@ static int amd_pmf_get_bios_buffer(struct amd_pmf_dev *dev)
 
 	memcpy(dev->policy_buf, dev->policy_base, dev->policy_sz);
 
+	if (pb_side_load)
+		amd_pmf_open_pb(dev, dev->dbgfs_dir);
+
 	return amd_pmf_start_policy_engine(dev);
 }
 
@@ -382,6 +446,9 @@ int amd_pmf_init_smart_pc(struct amd_pmf_dev *dev)
 
 void amd_pmf_deinit_smart_pc(struct amd_pmf_dev *dev)
 {
+	if (pb_side_load)
+		amd_pmf_remove_pb(dev);
+
 	kfree(dev->prev_data);
 	kfree(dev->policy_buf);
 	cancel_delayed_work_sync(&dev->pb_work);
-- 
2.25.1


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

* [PATCH v4 12/17] platform/x86/amd/pmf: dump policy binary data
  2023-10-18  7:02 [PATCH v4 00/17] Introduce PMF Smart PC Solution Builder Feature Shyam Sundar S K
                   ` (10 preceding siblings ...)
  2023-10-18  7:02 ` [PATCH v4 11/17] platform/x86/amd/pmf: Add capability to sideload of policy binary Shyam Sundar S K
@ 2023-10-18  7:02 ` Shyam Sundar S K
  2023-10-18 10:09   ` Ilpo Järvinen
  2023-10-18  7:02 ` [PATCH v4 13/17] platform/x86/amd/pmf: Add PMF-AMDGPU get interface Shyam Sundar S K
                   ` (4 subsequent siblings)
  16 siblings, 1 reply; 35+ messages in thread
From: Shyam Sundar S K @ 2023-10-18  7:02 UTC (permalink / raw)
  To: hdegoede, markgross, ilpo.jarvinen, 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.

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/tee-if.c | 9 +++++++++
 1 file changed, 9 insertions(+)

diff --git a/drivers/platform/x86/amd/pmf/tee-if.c b/drivers/platform/x86/amd/pmf/tee-if.c
index 6c4ce22ba518..2f5fb8623c20 100644
--- a/drivers/platform/x86/amd/pmf/tee-if.c
+++ b/drivers/platform/x86/amd/pmf/tee-if.c
@@ -276,6 +276,12 @@ static int amd_pmf_start_policy_engine(struct amd_pmf_dev *dev)
 }
 
 #ifdef CONFIG_AMD_PMF_DEBUG
+static void amd_pmf_hex_dump_pb(struct amd_pmf_dev *dev)
+{
+	print_hex_dump_debug("(pb):  ", DUMP_PREFIX_OFFSET, 16, 1, dev->policy_buf,
+			     dev->policy_sz, false);
+}
+
 static ssize_t amd_pmf_get_pb_data(struct file *filp, const char __user *buf,
 				   size_t length, loff_t *pos)
 {
@@ -290,6 +296,7 @@ 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;
 
+	amd_pmf_hex_dump_pb(dev);
 	ret = amd_pmf_start_policy_engine(dev);
 	if (ret)
 		return -EINVAL;
@@ -328,6 +335,7 @@ static int amd_pmf_open_pb(struct amd_pmf_dev *dev, struct dentry *debugfs_root)
 }
 
 static void amd_pmf_remove_pb(struct amd_pmf_dev *dev) {}
+static void amd_pmf_hex_dump_pb(struct amd_pmf_dev *dev) {}
 #endif
 
 static int amd_pmf_get_bios_buffer(struct amd_pmf_dev *dev)
@@ -342,6 +350,7 @@ static int amd_pmf_get_bios_buffer(struct amd_pmf_dev *dev)
 
 	memcpy(dev->policy_buf, dev->policy_base, dev->policy_sz);
 
+	amd_pmf_hex_dump_pb(dev);
 	if (pb_side_load)
 		amd_pmf_open_pb(dev, dev->dbgfs_dir);
 
-- 
2.25.1


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

* [PATCH v4 13/17] platform/x86/amd/pmf: Add PMF-AMDGPU get interface
  2023-10-18  7:02 [PATCH v4 00/17] Introduce PMF Smart PC Solution Builder Feature Shyam Sundar S K
                   ` (11 preceding siblings ...)
  2023-10-18  7:02 ` [PATCH v4 12/17] platform/x86/amd/pmf: dump policy binary data Shyam Sundar S K
@ 2023-10-18  7:02 ` Shyam Sundar S K
  2023-10-18  9:20   ` Ilpo Järvinen
  2023-10-18  7:02 ` [PATCH v4 14/17] platform/x86/amd/pmf: Add PMF-AMDGPU set interface Shyam Sundar S K
                   ` (3 subsequent siblings)
  16 siblings, 1 reply; 35+ messages in thread
From: Shyam Sundar S K @ 2023-10-18  7:02 UTC (permalink / raw)
  To: hdegoede, markgross, ilpo.jarvinen, 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 | 138 ++++++++++++++++++++++++
 drivers/platform/x86/amd/pmf/Kconfig    |   1 +
 drivers/platform/x86/amd/pmf/core.c     |   1 +
 drivers/platform/x86/amd/pmf/pmf.h      |   3 +
 drivers/platform/x86/amd/pmf/spc.c      |  13 +++
 drivers/platform/x86/amd/pmf/tee-if.c   |  26 +++++
 include/linux/amd-pmf-io.h              |  35 ++++++
 9 files changed, 220 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 a79d53bdbe13..26ffa1b4fe57 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..ac981848df50
--- /dev/null
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_pmf.c
@@ -0,0 +1,138 @@
+/*
+ * 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;
+	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;
+	}
+
+	mutex_lock(&mode_config->mutex);
+	drm_connector_list_iter_begin(drm_dev, &iter);
+	drm_for_each_connector_iter(connector, &iter) {
+		if (connector->status == connector_status_connected)
+			pmf->display_count++;
+		if (connector->status != pmf->con_status[i])
+			pmf->con_status[i] = connector->status;
+		if (connector->connector_type != pmf->connector_type[i])
+			pmf->connector_type[i] = connector->connector_type;
+
+		i++;
+		if (i >= MAX_SUPPORTED)
+			break;
+	}
+	drm_connector_list_iter_end(&iter);
+	mutex_unlock(&mode_config->mutex);
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(amd_pmf_get_gfx_data);
+
+static int amd_pmf_gpu_get_cur_state(struct thermal_cooling_device *cooling_dev,
+				     unsigned long *state)
+{
+	struct backlight_device *bd;
+
+	if (!acpi_video_backlight_use_native())
+		return -ENODEV;
+
+	bd = backlight_device_get_by_type(BACKLIGHT_RAW);
+	if (!bd)
+		return -ENODEV;
+
+	*state = backlight_get_brightness(bd);
+
+	return 0;
+}
+
+static int amd_pmf_gpu_get_max_state(struct thermal_cooling_device *cooling_dev,
+				     unsigned long *state)
+{
+	struct backlight_device *bd;
+
+	if (!acpi_video_backlight_use_native())
+		return -ENODEV;
+
+	bd = backlight_device_get_by_type(BACKLIGHT_RAW);
+	if (!bd)
+		return -ENODEV;
+
+	if (backlight_is_blank(bd))
+		*state = 0;
+	else
+		*state = bd->props.max_brightness;
+
+	return 0;
+}
+
+static const struct thermal_cooling_device_ops bd_cooling_ops = {
+	.get_max_state = amd_pmf_gpu_get_max_state,
+	.get_cur_state = amd_pmf_gpu_get_cur_state,
+};
+
+int amd_pmf_gpu_init(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);
+
+	if (!(adev->flags & AMD_IS_APU)) {
+		DRM_ERROR("PMF-AMDGPU interface not supported\n");
+		return -ENODEV;
+	}
+
+	if (!acpi_video_backlight_use_native())
+		return -ENODEV;
+
+	pmf->raw_bd = backlight_device_get_by_type(BACKLIGHT_RAW);
+	if (!pmf->raw_bd)
+		return -ENODEV;
+
+	pmf->cooling_dev = thermal_cooling_device_register("pmf_gpu_bd",
+							   pmf, &bd_cooling_ops);
+	if (IS_ERR(pmf->cooling_dev))
+		return -ENODEV;
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(amd_pmf_gpu_init);
+
+void amd_pmf_gpu_deinit(struct amd_gpu_pmf_data *pmf)
+{
+	thermal_cooling_device_unregister(pmf->cooling_dev);
+}
+EXPORT_SYMBOL_GPL(amd_pmf_gpu_deinit);
diff --git a/drivers/platform/x86/amd/pmf/Kconfig b/drivers/platform/x86/amd/pmf/Kconfig
index f246252bddd8..7f430de7af44 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 TEE && 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 4b8156033fa6..c59ba527ff49 100644
--- a/drivers/platform/x86/amd/pmf/core.c
+++ b/drivers/platform/x86/amd/pmf/core.c
@@ -411,6 +411,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 8712299ad52b..615cd3a31986 100644
--- a/drivers/platform/x86/amd/pmf/pmf.h
+++ b/drivers/platform/x86/amd/pmf/pmf.h
@@ -13,6 +13,7 @@
 
 #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
@@ -228,9 +229,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 512e0c66efdc..cf4962ef97c2 100644
--- a/drivers/platform/x86/amd/pmf/spc.c
+++ b/drivers/platform/x86/amd/pmf/spc.c
@@ -44,6 +44,10 @@ void amd_pmf_dump_ta_inputs(struct amd_pmf_dev *dev, struct ta_pmf_enact_table *
 	dev_dbg(dev->dev, "Max C0 Residency : %u\n", in->ev_info.max_c0residency);
 	dev_dbg(dev->dev, "GFX Busy : %u\n", in->ev_info.gfx_busy);
 	dev_dbg(dev->dev, "Connected Display Count : %u\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");
 }
@@ -146,6 +150,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 */
@@ -154,4 +166,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 2f5fb8623c20..956e66b78605 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"
@@ -357,6 +358,19 @@ 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) {
+		/* Found the amdgpu handle from the pci root after walking through the pci bus */
+		dev->gfx_data.gpu_dev = 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;
@@ -446,6 +460,15 @@ 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");
+
+	if (!amd_pmf_gpu_init(&dev->gfx_data))
+		dev->gfx_data.gpu_dev_en = true;
+
 	dev->prev_data = kzalloc(sizeof(*dev->prev_data), GFP_KERNEL);
 	if (!dev->prev_data)
 		return -ENOMEM;
@@ -461,5 +484,8 @@ 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);
+	if (dev->gfx_data.gpu_dev_en)
+		amd_pmf_gpu_deinit(&dev->gfx_data);
+	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..5f79e66a41b3
--- /dev/null
+++ b/include/linux/amd-pmf-io.h
@@ -0,0 +1,35 @@
+/* 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 <acpi/video.h>
+#include <drm/drm_connector.h>
+#include <linux/backlight.h>
+#include <linux/thermal.h>
+
+#define MAX_SUPPORTED 4
+
+/* amdgpu */
+struct amd_gpu_pmf_data {
+	struct pci_dev *gpu_dev;
+	struct backlight_device *raw_bd;
+	struct thermal_cooling_device *cooling_dev;
+	enum drm_connector_status con_status[MAX_SUPPORTED];
+	int display_count;
+	int connector_type[MAX_SUPPORTED];
+	bool gpu_dev_en;
+};
+
+int amd_pmf_get_gfx_data(struct amd_gpu_pmf_data *pmf);
+int amd_pmf_gpu_init(struct amd_gpu_pmf_data *pmf);
+void amd_pmf_gpu_deinit(struct amd_gpu_pmf_data *pmf);
+#endif
-- 
2.25.1


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

* [PATCH v4 14/17] platform/x86/amd/pmf: Add PMF-AMDGPU set interface
  2023-10-18  7:02 [PATCH v4 00/17] Introduce PMF Smart PC Solution Builder Feature Shyam Sundar S K
                   ` (12 preceding siblings ...)
  2023-10-18  7:02 ` [PATCH v4 13/17] platform/x86/amd/pmf: Add PMF-AMDGPU get interface Shyam Sundar S K
@ 2023-10-18  7:02 ` Shyam Sundar S K
  2023-10-18  7:02 ` [PATCH v4 15/17] HID: amd_sfh: rename float_to_int() to amd_sfh_float_to_int() Shyam Sundar S K
                   ` (2 subsequent siblings)
  16 siblings, 0 replies; 35+ messages in thread
From: Shyam Sundar S K @ 2023-10-18  7:02 UTC (permalink / raw)
  To: hdegoede, markgross, ilpo.jarvinen, 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.

Change amd_pmf_apply_policies() return type, so that it can return
errors when the call to retrieve information from amdgpu fails.

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 | 18 ++++++++++++++++++
 drivers/platform/x86/amd/pmf/pmf.h      |  2 ++
 drivers/platform/x86/amd/pmf/tee-if.c   | 21 +++++++++++++++++++--
 3 files changed, 39 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_pmf.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_pmf.c
index ac981848df50..57acfc32219a 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_pmf.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_pmf.c
@@ -63,6 +63,23 @@ int amd_pmf_get_gfx_data(struct amd_gpu_pmf_data *pmf)
 }
 EXPORT_SYMBOL_GPL(amd_pmf_get_gfx_data);
 
+static int amd_pmf_gpu_set_cur_state(struct thermal_cooling_device *cooling_dev,
+				     unsigned long state)
+{
+	struct backlight_device *bd;
+
+	if (!acpi_video_backlight_use_native())
+		return -ENODEV;
+
+	bd = backlight_device_get_by_type(BACKLIGHT_RAW);
+	if (!bd)
+		return -ENODEV;
+
+	backlight_device_set_brightness(bd, state);
+
+	return 0;
+}
+
 static int amd_pmf_gpu_get_cur_state(struct thermal_cooling_device *cooling_dev,
 				     unsigned long *state)
 {
@@ -103,6 +120,7 @@ static int amd_pmf_gpu_get_max_state(struct thermal_cooling_device *cooling_dev,
 static const struct thermal_cooling_device_ops bd_cooling_ops = {
 	.get_max_state = amd_pmf_gpu_get_max_state,
 	.get_cur_state = amd_pmf_gpu_get_cur_state,
+	.set_cur_state = amd_pmf_gpu_set_cur_state,
 };
 
 int amd_pmf_gpu_init(struct amd_gpu_pmf_data *pmf)
diff --git a/drivers/platform/x86/amd/pmf/pmf.h b/drivers/platform/x86/amd/pmf/pmf.h
index 615cd3a31986..641af94ba378 100644
--- a/drivers/platform/x86/amd/pmf/pmf.h
+++ b/drivers/platform/x86/amd/pmf/pmf.h
@@ -75,6 +75,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 */
@@ -488,6 +489,7 @@ enum ta_pmf_error_type {
 };
 
 struct pmf_action_table {
+	unsigned long display_brightness;
 	enum system_state system_state;
 	u32 spl;		/* in mW */
 	u32 sppt;		/* in mW */
diff --git a/drivers/platform/x86/amd/pmf/tee-if.c b/drivers/platform/x86/amd/pmf/tee-if.c
index 956e66b78605..b39f30a4f92d 100644
--- a/drivers/platform/x86/amd/pmf/tee-if.c
+++ b/drivers/platform/x86/amd/pmf/tee-if.c
@@ -77,8 +77,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)
 {
+	struct thermal_cooling_device *cdev = dev->gfx_data.cooling_dev;
+	unsigned long state;
 	u32 val;
 	int idx;
 
@@ -154,8 +156,21 @@ static void amd_pmf_apply_policies(struct amd_pmf_dev *dev, struct ta_pmf_enact_
 			dev_dbg(dev->dev, "update SYSTEM_STATE : %s\n",
 				amd_pmf_uevent_as_str(val));
 			break;
+
+		case PMF_POLICY_DISPLAY_BRIGHTNESS:
+			if (!dev->gfx_data.gpu_dev_en)
+				return -ENODEV;
+
+			cdev->ops->get_cur_state(cdev, &state);
+			if (state != val) {
+				cdev->ops->set_cur_state(cdev, val);
+				dev_dbg(dev->dev, "update DISPLAY_BRIGHTNESS : %u\n", val);
+			}
+			break;
 		}
 	}
+
+	return 0;
 }
 
 static int amd_pmf_invoke_cmd_enact(struct amd_pmf_dev *dev)
@@ -192,7 +207,9 @@ static int amd_pmf_invoke_cmd_enact(struct amd_pmf_dev *dev)
 		amd_pmf_dump_ta_inputs(dev, in);
 		dev_dbg(dev->dev, "action count:%u result:%x\n", out->actions_count,
 			ta_sm->pmf_result);
-		amd_pmf_apply_policies(dev, out);
+		ret = amd_pmf_apply_policies(dev, out);
+		if (ret)
+			return ret;
 	}
 
 	return 0;
-- 
2.25.1


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

* [PATCH v4 15/17] HID: amd_sfh: rename float_to_int() to amd_sfh_float_to_int()
  2023-10-18  7:02 [PATCH v4 00/17] Introduce PMF Smart PC Solution Builder Feature Shyam Sundar S K
                   ` (13 preceding siblings ...)
  2023-10-18  7:02 ` [PATCH v4 14/17] platform/x86/amd/pmf: Add PMF-AMDGPU set interface Shyam Sundar S K
@ 2023-10-18  7:02 ` Shyam Sundar S K
  2023-10-18  8:15   ` Ilpo Järvinen
  2023-10-18  7:02 ` [PATCH v4 16/17] platform/x86/amd/pmf: Add PMF-AMDSFH interface for HPD Shyam Sundar S K
  2023-10-18  7:02 ` [PATCH v4 17/17] platform/x86/amd/pmf: Add PMF-AMDSFH interface for ALS Shyam Sundar S K
  16 siblings, 1 reply; 35+ messages in thread
From: Shyam Sundar S K @ 2023-10-18  7:02 UTC (permalink / raw)
  To: hdegoede, markgross, ilpo.jarvinen, 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>

Current amd_sfh driver has float_to_int() to convert units from
float to int. This is fine until this function gets called outside of
the current scope of file.

Add a prefix "amd_sfh" to float_to_int() so that function represents
the driver name. This function will be called by multiple callers in the
next patch.

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/sfh1_1/amd_sfh_desc.c | 22 +++++++++----------
 .../amd-sfh-hid/sfh1_1/amd_sfh_interface.h    |  1 +
 2 files changed, 12 insertions(+), 11 deletions(-)

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..dbc8c6943ca1 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 amd_sfh_float_to_int(u32 flt32_val)
 {
 	int fraction, shift, mantissa, sign, exp, zeropre;
 
@@ -200,9 +200,9 @@ static u8 get_input_rep(u8 current_index, int sensor_idx, int report_id,
 			     OFFSET_SENSOR_DATA_DEFAULT;
 		memcpy_fromio(&accel_data, sensoraddr, sizeof(struct sfh_accel_data));
 		get_common_inputs(&acc_input.common_property, report_id);
-		acc_input.in_accel_x_value = float_to_int(accel_data.acceldata.x) / 100;
-		acc_input.in_accel_y_value = float_to_int(accel_data.acceldata.y) / 100;
-		acc_input.in_accel_z_value = float_to_int(accel_data.acceldata.z) / 100;
+		acc_input.in_accel_x_value = amd_sfh_float_to_int(accel_data.acceldata.x) / 100;
+		acc_input.in_accel_y_value = amd_sfh_float_to_int(accel_data.acceldata.y) / 100;
+		acc_input.in_accel_z_value = amd_sfh_float_to_int(accel_data.acceldata.z) / 100;
 		memcpy(input_report, &acc_input, sizeof(acc_input));
 		report_size = sizeof(acc_input);
 		break;
@@ -211,9 +211,9 @@ static u8 get_input_rep(u8 current_index, int sensor_idx, int report_id,
 			     OFFSET_SENSOR_DATA_DEFAULT;
 		memcpy_fromio(&gyro_data, sensoraddr, sizeof(struct sfh_gyro_data));
 		get_common_inputs(&gyro_input.common_property, report_id);
-		gyro_input.in_angel_x_value = float_to_int(gyro_data.gyrodata.x) / 1000;
-		gyro_input.in_angel_y_value = float_to_int(gyro_data.gyrodata.y) / 1000;
-		gyro_input.in_angel_z_value = float_to_int(gyro_data.gyrodata.z) / 1000;
+		gyro_input.in_angel_x_value = amd_sfh_float_to_int(gyro_data.gyrodata.x) / 1000;
+		gyro_input.in_angel_y_value = amd_sfh_float_to_int(gyro_data.gyrodata.y) / 1000;
+		gyro_input.in_angel_z_value = amd_sfh_float_to_int(gyro_data.gyrodata.z) / 1000;
 		memcpy(input_report, &gyro_input, sizeof(gyro_input));
 		report_size = sizeof(gyro_input);
 		break;
@@ -222,9 +222,9 @@ static u8 get_input_rep(u8 current_index, int sensor_idx, int report_id,
 			     OFFSET_SENSOR_DATA_DEFAULT;
 		memcpy_fromio(&mag_data, sensoraddr, sizeof(struct sfh_mag_data));
 		get_common_inputs(&magno_input.common_property, report_id);
-		magno_input.in_magno_x = float_to_int(mag_data.magdata.x) / 100;
-		magno_input.in_magno_y = float_to_int(mag_data.magdata.y) / 100;
-		magno_input.in_magno_z = float_to_int(mag_data.magdata.z) / 100;
+		magno_input.in_magno_x = amd_sfh_float_to_int(mag_data.magdata.x) / 100;
+		magno_input.in_magno_y = amd_sfh_float_to_int(mag_data.magdata.y) / 100;
+		magno_input.in_magno_z = amd_sfh_float_to_int(mag_data.magdata.z) / 100;
 		magno_input.in_magno_accuracy = mag_data.accuracy / 100;
 		memcpy(input_report, &magno_input, sizeof(magno_input));
 		report_size = sizeof(magno_input);
@@ -234,7 +234,7 @@ static u8 get_input_rep(u8 current_index, int sensor_idx, int report_id,
 			     OFFSET_SENSOR_DATA_DEFAULT;
 		memcpy_fromio(&als_data, sensoraddr, sizeof(struct sfh_als_data));
 		get_common_inputs(&als_input.common_property, report_id);
-		als_input.illuminance_value = float_to_int(als_data.lux);
+		als_input.illuminance_value = amd_sfh_float_to_int(als_data.lux);
 		report_size = sizeof(als_input);
 		memcpy(input_report, &als_input, sizeof(als_input));
 		break;
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..78e22850417a 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
@@ -151,4 +151,5 @@ struct hpd_status {
 
 void sfh_interface_init(struct amd_mp2_dev *mp2);
 void amd_sfh1_1_set_desc_ops(struct amd_mp2_ops *mp2_ops);
+int amd_sfh_float_to_int(u32 flt32_val);
 #endif
-- 
2.25.1


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

* [PATCH v4 16/17] platform/x86/amd/pmf: Add PMF-AMDSFH interface for HPD
  2023-10-18  7:02 [PATCH v4 00/17] Introduce PMF Smart PC Solution Builder Feature Shyam Sundar S K
                   ` (14 preceding siblings ...)
  2023-10-18  7:02 ` [PATCH v4 15/17] HID: amd_sfh: rename float_to_int() to amd_sfh_float_to_int() Shyam Sundar S K
@ 2023-10-18  7:02 ` Shyam Sundar S K
  2023-10-18  8:29   ` Ilpo Järvinen
  2023-10-18  7:02 ` [PATCH v4 17/17] platform/x86/amd/pmf: Add PMF-AMDSFH interface for ALS Shyam Sundar S K
  16 siblings, 1 reply; 35+ messages in thread
From: Shyam Sundar S K @ 2023-10-18  7:02 UTC (permalink / raw)
  To: hdegoede, markgross, ilpo.jarvinen, 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_init.c | 11 ++++++++
 .../amd-sfh-hid/sfh1_1/amd_sfh_interface.c    | 28 +++++++++++++++++++
 drivers/platform/x86/amd/pmf/Kconfig          |  1 +
 drivers/platform/x86/amd/pmf/spc.c            | 21 ++++++++++++++
 include/linux/amd-pmf-io.h                    | 20 ++++++++++++-
 6 files changed, 85 insertions(+), 1 deletion(-)

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_init.c b/drivers/hid/amd-sfh-hid/sfh1_1/amd_sfh_init.c
index e9c6413af24a..3dc652d41d7d 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..7637da0dec6f 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 -EINVAL;
 }
+EXPORT_SYMBOL_GPL(amd_get_sfh_info);
diff --git a/drivers/platform/x86/amd/pmf/Kconfig b/drivers/platform/x86/amd/pmf/Kconfig
index 7f430de7af44..d368d35a49ac 100644
--- a/drivers/platform/x86/amd/pmf/Kconfig
+++ b/drivers/platform/x86/amd/pmf/Kconfig
@@ -11,6 +11,7 @@ config AMD_PMF
 	select ACPI_PLATFORM_PROFILE
 	depends on TEE && AMDTEE
 	depends on DRM_AMDGPU
+	depends on AMD_SFH_HID
 	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/spc.c b/drivers/platform/x86/amd/pmf/spc.c
index cf4962ef97c2..8bdfb395f316 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 *
 	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
@@ -158,6 +159,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 */
@@ -167,4 +187,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 5f79e66a41b3..76e42552b62c 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
@@ -32,4 +33,21 @@ struct amd_gpu_pmf_data {
 int amd_pmf_get_gfx_data(struct amd_gpu_pmf_data *pmf);
 int amd_pmf_gpu_init(struct amd_gpu_pmf_data *pmf);
 void amd_pmf_gpu_deinit(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;
+};
+
+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] 35+ messages in thread

* [PATCH v4 17/17] platform/x86/amd/pmf: Add PMF-AMDSFH interface for ALS
  2023-10-18  7:02 [PATCH v4 00/17] Introduce PMF Smart PC Solution Builder Feature Shyam Sundar S K
                   ` (15 preceding siblings ...)
  2023-10-18  7:02 ` [PATCH v4 16/17] platform/x86/amd/pmf: Add PMF-AMDSFH interface for HPD Shyam Sundar S K
@ 2023-10-18  7:02 ` Shyam Sundar S K
  16 siblings, 0 replies; 35+ messages in thread
From: Shyam Sundar S K @ 2023-10-18  7:02 UTC (permalink / raw)
  To: hdegoede, markgross, ilpo.jarvinen, 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.

Reviewed-by: Mario Limonciello <mario.limonciello@amd.com>
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            |  9 ++++++++-
 include/linux/amd-pmf-io.h                    |  2 ++
 5 files changed, 37 insertions(+), 1 deletion(-)

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 3dc652d41d7d..f2890d329459 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 7637da0dec6f..48a7a450e029 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 = amd_sfh_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 -EINVAL;
diff --git a/drivers/platform/x86/amd/pmf/spc.c b/drivers/platform/x86/amd/pmf/spc.c
index 8bdfb395f316..934afe346f7e 100644
--- a/drivers/platform/x86/amd/pmf/spc.c
+++ b/drivers/platform/x86/amd/pmf/spc.c
@@ -50,6 +50,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
@@ -162,8 +163,14 @@ static void amd_pmf_get_gpu_info(struct amd_pmf_dev *dev, struct ta_pmf_enact_ta
 static void amd_pmf_get_sensor_info(struct amd_pmf_dev *dev, struct ta_pmf_enact_table *in)
 {
 	struct amd_sfh_info sfh_info;
+	int ret;
 
-	/* get HPD data */
+	/* Get ALS data */
+	ret = amd_get_sfh_info(&sfh_info, MT_ALS);
+	if (!ret)
+		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) {
 	case SFH_NOT_DETECTED:
diff --git a/include/linux/amd-pmf-io.h b/include/linux/amd-pmf-io.h
index 76e42552b62c..912d341d5fbe 100644
--- a/include/linux/amd-pmf-io.h
+++ b/include/linux/amd-pmf-io.h
@@ -37,6 +37,7 @@ void amd_pmf_gpu_deinit(struct amd_gpu_pmf_data *pmf);
 /* amd-sfh */
 enum sfh_message_type {
 	MT_HPD,
+	MT_ALS,
 };
 
 enum hpd_info {
@@ -46,6 +47,7 @@ enum hpd_info {
 };
 
 struct amd_sfh_info {
+	u32 ambient_light;
 	u8 user_present;
 };
 
-- 
2.25.1


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

* Re: [PATCH v4 15/17] HID: amd_sfh: rename float_to_int() to amd_sfh_float_to_int()
  2023-10-18  7:02 ` [PATCH v4 15/17] HID: amd_sfh: rename float_to_int() to amd_sfh_float_to_int() Shyam Sundar S K
@ 2023-10-18  8:15   ` Ilpo Järvinen
  0 siblings, 0 replies; 35+ messages in thread
From: Ilpo Järvinen @ 2023-10-18  8:15 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: 5104 bytes --]

On Wed, 18 Oct 2023, Shyam Sundar S K wrote:

> From: Basavaraj Natikar <Basavaraj.Natikar@amd.com>
> 
> Current amd_sfh driver has float_to_int() to convert units from
> float to int. This is fine until this function gets called outside of
> the current scope of file.
> 
> Add a prefix "amd_sfh" to float_to_int() so that function represents
> the driver name. This function will be called by multiple callers in the
> next patch.
> 
> 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/sfh1_1/amd_sfh_desc.c | 22 +++++++++----------
>  .../amd-sfh-hid/sfh1_1/amd_sfh_interface.h    |  1 +
>  2 files changed, 12 insertions(+), 11 deletions(-)
> 
> 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..dbc8c6943ca1 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 amd_sfh_float_to_int(u32 flt32_val)
>  {
>  	int fraction, shift, mantissa, sign, exp, zeropre;
>  
> @@ -200,9 +200,9 @@ static u8 get_input_rep(u8 current_index, int sensor_idx, int report_id,
>  			     OFFSET_SENSOR_DATA_DEFAULT;
>  		memcpy_fromio(&accel_data, sensoraddr, sizeof(struct sfh_accel_data));
>  		get_common_inputs(&acc_input.common_property, report_id);
> -		acc_input.in_accel_x_value = float_to_int(accel_data.acceldata.x) / 100;
> -		acc_input.in_accel_y_value = float_to_int(accel_data.acceldata.y) / 100;
> -		acc_input.in_accel_z_value = float_to_int(accel_data.acceldata.z) / 100;
> +		acc_input.in_accel_x_value = amd_sfh_float_to_int(accel_data.acceldata.x) / 100;
> +		acc_input.in_accel_y_value = amd_sfh_float_to_int(accel_data.acceldata.y) / 100;
> +		acc_input.in_accel_z_value = amd_sfh_float_to_int(accel_data.acceldata.z) / 100;
>  		memcpy(input_report, &acc_input, sizeof(acc_input));
>  		report_size = sizeof(acc_input);
>  		break;
> @@ -211,9 +211,9 @@ static u8 get_input_rep(u8 current_index, int sensor_idx, int report_id,
>  			     OFFSET_SENSOR_DATA_DEFAULT;
>  		memcpy_fromio(&gyro_data, sensoraddr, sizeof(struct sfh_gyro_data));
>  		get_common_inputs(&gyro_input.common_property, report_id);
> -		gyro_input.in_angel_x_value = float_to_int(gyro_data.gyrodata.x) / 1000;
> -		gyro_input.in_angel_y_value = float_to_int(gyro_data.gyrodata.y) / 1000;
> -		gyro_input.in_angel_z_value = float_to_int(gyro_data.gyrodata.z) / 1000;
> +		gyro_input.in_angel_x_value = amd_sfh_float_to_int(gyro_data.gyrodata.x) / 1000;
> +		gyro_input.in_angel_y_value = amd_sfh_float_to_int(gyro_data.gyrodata.y) / 1000;
> +		gyro_input.in_angel_z_value = amd_sfh_float_to_int(gyro_data.gyrodata.z) / 1000;
>  		memcpy(input_report, &gyro_input, sizeof(gyro_input));
>  		report_size = sizeof(gyro_input);
>  		break;
> @@ -222,9 +222,9 @@ static u8 get_input_rep(u8 current_index, int sensor_idx, int report_id,
>  			     OFFSET_SENSOR_DATA_DEFAULT;
>  		memcpy_fromio(&mag_data, sensoraddr, sizeof(struct sfh_mag_data));
>  		get_common_inputs(&magno_input.common_property, report_id);
> -		magno_input.in_magno_x = float_to_int(mag_data.magdata.x) / 100;
> -		magno_input.in_magno_y = float_to_int(mag_data.magdata.y) / 100;
> -		magno_input.in_magno_z = float_to_int(mag_data.magdata.z) / 100;
> +		magno_input.in_magno_x = amd_sfh_float_to_int(mag_data.magdata.x) / 100;
> +		magno_input.in_magno_y = amd_sfh_float_to_int(mag_data.magdata.y) / 100;
> +		magno_input.in_magno_z = amd_sfh_float_to_int(mag_data.magdata.z) / 100;
>  		magno_input.in_magno_accuracy = mag_data.accuracy / 100;
>  		memcpy(input_report, &magno_input, sizeof(magno_input));
>  		report_size = sizeof(magno_input);
> @@ -234,7 +234,7 @@ static u8 get_input_rep(u8 current_index, int sensor_idx, int report_id,
>  			     OFFSET_SENSOR_DATA_DEFAULT;
>  		memcpy_fromio(&als_data, sensoraddr, sizeof(struct sfh_als_data));
>  		get_common_inputs(&als_input.common_property, report_id);
> -		als_input.illuminance_value = float_to_int(als_data.lux);
> +		als_input.illuminance_value = amd_sfh_float_to_int(als_data.lux);
>  		report_size = sizeof(als_input);
>  		memcpy(input_report, &als_input, sizeof(als_input));
>  		break;
> 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..78e22850417a 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
> @@ -151,4 +151,5 @@ struct hpd_status {
>  
>  void sfh_interface_init(struct amd_mp2_dev *mp2);
>  void amd_sfh1_1_set_desc_ops(struct amd_mp2_ops *mp2_ops);
> +int amd_sfh_float_to_int(u32 flt32_val);
>  #endif

Reviewed-by: Ilpo Järvinen <ilpo.jarvinen@linux.intel.com>

-- 
 i.

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

* Re: [PATCH v4 16/17] platform/x86/amd/pmf: Add PMF-AMDSFH interface for HPD
  2023-10-18  7:02 ` [PATCH v4 16/17] platform/x86/amd/pmf: Add PMF-AMDSFH interface for HPD Shyam Sundar S K
@ 2023-10-18  8:29   ` Ilpo Järvinen
  0 siblings, 0 replies; 35+ messages in thread
From: Ilpo Järvinen @ 2023-10-18  8:29 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 Wed, 18 Oct 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_init.c | 11 ++++++++
>  .../amd-sfh-hid/sfh1_1/amd_sfh_interface.c    | 28 +++++++++++++++++++
>  drivers/platform/x86/amd/pmf/Kconfig          |  1 +
>  drivers/platform/x86/amd/pmf/spc.c            | 21 ++++++++++++++
>  include/linux/amd-pmf-io.h                    | 20 ++++++++++++-
>  6 files changed, 85 insertions(+), 1 deletion(-)
> 
> 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_init.c b/drivers/hid/amd-sfh-hid/sfh1_1/amd_sfh_init.c
> index e9c6413af24a..3dc652d41d7d 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..7637da0dec6f 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;

Reverse the logic and early return with -ENODEV. Make the same change to 
the next patch too.

-- 
 i.

> +}
> +
> +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 -EINVAL;
>  }
> +EXPORT_SYMBOL_GPL(amd_get_sfh_info);
> diff --git a/drivers/platform/x86/amd/pmf/Kconfig b/drivers/platform/x86/amd/pmf/Kconfig
> index 7f430de7af44..d368d35a49ac 100644
> --- a/drivers/platform/x86/amd/pmf/Kconfig
> +++ b/drivers/platform/x86/amd/pmf/Kconfig
> @@ -11,6 +11,7 @@ config AMD_PMF
>  	select ACPI_PLATFORM_PROFILE
>  	depends on TEE && AMDTEE
>  	depends on DRM_AMDGPU
> +	depends on AMD_SFH_HID
>  	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/spc.c b/drivers/platform/x86/amd/pmf/spc.c
> index cf4962ef97c2..8bdfb395f316 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 *
>  	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
> @@ -158,6 +159,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 */
> @@ -167,4 +187,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 5f79e66a41b3..76e42552b62c 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
> @@ -32,4 +33,21 @@ struct amd_gpu_pmf_data {
>  int amd_pmf_get_gfx_data(struct amd_gpu_pmf_data *pmf);
>  int amd_pmf_gpu_init(struct amd_gpu_pmf_data *pmf);
>  void amd_pmf_gpu_deinit(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;
> +};
> +
> +int amd_get_sfh_info(struct amd_sfh_info *sfh_info, enum sfh_message_type op);
>  #endif
> 

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

* Re: [PATCH v4 10/17] platform/x86/amd/pmf: Add facility to dump TA inputs
  2023-10-18  7:02 ` [PATCH v4 10/17] platform/x86/amd/pmf: Add facility to dump TA inputs Shyam Sundar S K
@ 2023-10-18  9:00   ` Ilpo Järvinen
  2023-11-17  7:46     ` Shyam Sundar S K
  0 siblings, 1 reply; 35+ messages in thread
From: Ilpo Järvinen @ 2023-10-18  9:00 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 Wed, 18 Oct 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.
> 
> Also, make source_as_str() as non-static function as this helper is
> required outside of sps.c file.
> 
> 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/tee-if.c |  1 +
>  3 files changed, 41 insertions(+)
> 
> diff --git a/drivers/platform/x86/amd/pmf/pmf.h b/drivers/platform/x86/amd/pmf/pmf.h
> index 216a9f795436..593930519039 100644
> --- a/drivers/platform/x86/amd/pmf/pmf.h
> +++ b/drivers/platform/x86/amd/pmf/pmf.h
> @@ -602,6 +602,7 @@ bool is_pprof_balanced(struct amd_pmf_dev *pmf);
>  int amd_pmf_power_slider_update_event(struct amd_pmf_dev *dev);
>  const char *amd_pmf_source_as_str(unsigned int state);
>  
> +const char *amd_pmf_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);
> @@ -632,4 +633,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 bd5061fdfdbe..512e0c66efdc 100644
> --- a/drivers/platform/x86/amd/pmf/spc.c
> +++ b/drivers/platform/x86/amd/pmf/spc.c
> @@ -14,6 +14,43 @@
>  #include <linux/units.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", amd_pmf_source_as_str(in->ev_info.power_source));
> +	dev_dbg(dev->dev, "Battery Percentage : %u\n", in->ev_info.bat_percentage);
> +	dev_dbg(dev->dev, "Designed Battery Capacity : %u\n", in->ev_info.bat_design);
> +	dev_dbg(dev->dev, "Fully Charged Capacity : %u\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 : %u\n", in->ev_info.socket_power);
> +	dev_dbg(dev->dev, "Skin Temperature : %u\n", in->ev_info.skin_temperature);
> +	dev_dbg(dev->dev, "Avg C0 Residency : %u\n", in->ev_info.avg_c0residency);
> +	dev_dbg(dev->dev, "Max C0 Residency : %u\n", in->ev_info.max_c0residency);
> +	dev_dbg(dev->dev, "GFX Busy : %u\n", in->ev_info.gfx_busy);
> +	dev_dbg(dev->dev, "Connected Display Count : %u\n", in->ev_info.monitor_count);
> +	dev_dbg(dev->dev, "LID State : %s\n", in->ev_info.lid_state ? "Close" : "Open");

"open" / "closed" is generic enough that I think it would warrant adding
include/linux/string_choices.h helper for it (it should be lowercase 
there but that difference probably is not an issue for these debug 
prints).

I'd also remove that extra space before :.

-- 
 i.

> +	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/tee-if.c b/drivers/platform/x86/amd/pmf/tee-if.c
> index d48f980fb1db..0eba258f4040 100644
> --- a/drivers/platform/x86/amd/pmf/tee-if.c
> +++ b/drivers/platform/x86/amd/pmf/tee-if.c
> @@ -182,6 +182,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:%u result:%x\n", out->actions_count,
>  			ta_sm->pmf_result);
>  		amd_pmf_apply_policies(dev, out);
> 

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

* Re: [PATCH v4 13/17] platform/x86/amd/pmf: Add PMF-AMDGPU get interface
  2023-10-18  7:02 ` [PATCH v4 13/17] platform/x86/amd/pmf: Add PMF-AMDGPU get interface Shyam Sundar S K
@ 2023-10-18  9:20   ` Ilpo Järvinen
  2023-10-18  9:28     ` Shyam Sundar S K
  0 siblings, 1 reply; 35+ messages in thread
From: Ilpo Järvinen @ 2023-10-18  9:20 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 Wed, 18 Oct 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 | 138 ++++++++++++++++++++++++
>  drivers/platform/x86/amd/pmf/Kconfig    |   1 +
>  drivers/platform/x86/amd/pmf/core.c     |   1 +
>  drivers/platform/x86/amd/pmf/pmf.h      |   3 +
>  drivers/platform/x86/amd/pmf/spc.c      |  13 +++
>  drivers/platform/x86/amd/pmf/tee-if.c   |  26 +++++
>  include/linux/amd-pmf-io.h              |  35 ++++++
>  9 files changed, 220 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 a79d53bdbe13..26ffa1b4fe57 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..ac981848df50
> --- /dev/null
> +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_pmf.c
> @@ -0,0 +1,138 @@
> +/*
> + * 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.

This is MIT, right? Add the required SPDX-License-Identifier line for it
at the top of the file, thank you.

> + *
> + * Author: Shyam Sundar S K <Shyam-sundar.S-k@amd.com>
> + *
> + */

Remove the extra empty line at the end of the comment.

> +
> +#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;
> +	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;
> +	}
> +
> +	mutex_lock(&mode_config->mutex);
> +	drm_connector_list_iter_begin(drm_dev, &iter);
> +	drm_for_each_connector_iter(connector, &iter) {
> +		if (connector->status == connector_status_connected)
> +			pmf->display_count++;
> +		if (connector->status != pmf->con_status[i])
> +			pmf->con_status[i] = connector->status;
> +		if (connector->connector_type != pmf->connector_type[i])
> +			pmf->connector_type[i] = connector->connector_type;
> +
> +		i++;
> +		if (i >= MAX_SUPPORTED)
> +			break;
> +	}
> +	drm_connector_list_iter_end(&iter);
> +	mutex_unlock(&mode_config->mutex);
> +
> +	return 0;
> +}
> +EXPORT_SYMBOL_GPL(amd_pmf_get_gfx_data);
> +
> +static int amd_pmf_gpu_get_cur_state(struct thermal_cooling_device *cooling_dev,
> +				     unsigned long *state)
> +{
> +	struct backlight_device *bd;
> +
> +	if (!acpi_video_backlight_use_native())
> +		return -ENODEV;
> +
> +	bd = backlight_device_get_by_type(BACKLIGHT_RAW);
> +	if (!bd)
> +		return -ENODEV;
> +
> +	*state = backlight_get_brightness(bd);
> +
> +	return 0;
> +}
> +
> +static int amd_pmf_gpu_get_max_state(struct thermal_cooling_device *cooling_dev,
> +				     unsigned long *state)
> +{
> +	struct backlight_device *bd;
> +
> +	if (!acpi_video_backlight_use_native())
> +		return -ENODEV;
> +
> +	bd = backlight_device_get_by_type(BACKLIGHT_RAW);
> +	if (!bd)
> +		return -ENODEV;
> +
> +	if (backlight_is_blank(bd))
> +		*state = 0;
> +	else
> +		*state = bd->props.max_brightness;
> +
> +	return 0;
> +}
> +
> +static const struct thermal_cooling_device_ops bd_cooling_ops = {
> +	.get_max_state = amd_pmf_gpu_get_max_state,
> +	.get_cur_state = amd_pmf_gpu_get_cur_state,
> +};
> +
> +int amd_pmf_gpu_init(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);
> +
> +	if (!(adev->flags & AMD_IS_APU)) {
> +		DRM_ERROR("PMF-AMDGPU interface not supported\n");
> +		return -ENODEV;
> +	}
> +
> +	if (!acpi_video_backlight_use_native())
> +		return -ENODEV;
> +
> +	pmf->raw_bd = backlight_device_get_by_type(BACKLIGHT_RAW);
> +	if (!pmf->raw_bd)
> +		return -ENODEV;
> +
> +	pmf->cooling_dev = thermal_cooling_device_register("pmf_gpu_bd",
> +							   pmf, &bd_cooling_ops);
> +	if (IS_ERR(pmf->cooling_dev))
> +		return -ENODEV;
> +
> +	return 0;
> +}
> +EXPORT_SYMBOL_GPL(amd_pmf_gpu_init);
> +
> +void amd_pmf_gpu_deinit(struct amd_gpu_pmf_data *pmf)
> +{
> +	thermal_cooling_device_unregister(pmf->cooling_dev);
> +}
> +EXPORT_SYMBOL_GPL(amd_pmf_gpu_deinit);
> diff --git a/drivers/platform/x86/amd/pmf/Kconfig b/drivers/platform/x86/amd/pmf/Kconfig
> index f246252bddd8..7f430de7af44 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 TEE && 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 4b8156033fa6..c59ba527ff49 100644
> --- a/drivers/platform/x86/amd/pmf/core.c
> +++ b/drivers/platform/x86/amd/pmf/core.c
> @@ -411,6 +411,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 8712299ad52b..615cd3a31986 100644
> --- a/drivers/platform/x86/amd/pmf/pmf.h
> +++ b/drivers/platform/x86/amd/pmf/pmf.h
> @@ -13,6 +13,7 @@
>  
>  #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
> @@ -228,9 +229,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 512e0c66efdc..cf4962ef97c2 100644
> --- a/drivers/platform/x86/amd/pmf/spc.c
> +++ b/drivers/platform/x86/amd/pmf/spc.c
> @@ -44,6 +44,10 @@ void amd_pmf_dump_ta_inputs(struct amd_pmf_dev *dev, struct ta_pmf_enact_table *
>  	dev_dbg(dev->dev, "Max C0 Residency : %u\n", in->ev_info.max_c0residency);
>  	dev_dbg(dev->dev, "GFX Busy : %u\n", in->ev_info.gfx_busy);
>  	dev_dbg(dev->dev, "Connected Display Count : %u\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");
>  }
> @@ -146,6 +150,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 */
> @@ -154,4 +166,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 2f5fb8623c20..956e66b78605 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"
> @@ -357,6 +358,19 @@ 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) {
> +		/* Found the amdgpu handle from the pci root after walking through the pci bus */

If you insist on having this comment, make it a function comment instead 
(with appropriate modifications into the content of it) but I personally 
don't find it that useful so it could be just dropped as well, IMO.

> +		dev->gfx_data.gpu_dev = 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;
> @@ -446,6 +460,15 @@ 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 */

Useless comment.

> +	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");
> +
> +	if (!amd_pmf_gpu_init(&dev->gfx_data))
> +		dev->gfx_data.gpu_dev_en = true;
> +
>  	dev->prev_data = kzalloc(sizeof(*dev->prev_data), GFP_KERNEL);
>  	if (!dev->prev_data)
>  		return -ENOMEM;
> @@ -461,5 +484,8 @@ 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);
> +	if (dev->gfx_data.gpu_dev_en)
> +		amd_pmf_gpu_deinit(&dev->gfx_data);
> +	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..5f79e66a41b3
> --- /dev/null
> +++ b/include/linux/amd-pmf-io.h
> @@ -0,0 +1,35 @@
> +/* 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 <acpi/video.h>
> +#include <drm/drm_connector.h>
> +#include <linux/backlight.h>
> +#include <linux/thermal.h>
> +
> +#define MAX_SUPPORTED 4
> +
> +/* amdgpu */

Document the structure properly with kerneldoc instead of an unhelpful 
comment like above :-). Please also check if you add any other structs 
into kernel-wide headers that you didn't document yet. Or fields into 
existing structs.

> +struct amd_gpu_pmf_data {
> +	struct pci_dev *gpu_dev;
> +	struct backlight_device *raw_bd;
> +	struct thermal_cooling_device *cooling_dev;
> +	enum drm_connector_status con_status[MAX_SUPPORTED];
> +	int display_count;
> +	int connector_type[MAX_SUPPORTED];
> +	bool gpu_dev_en;
> +};
> +
> +int amd_pmf_get_gfx_data(struct amd_gpu_pmf_data *pmf);
> +int amd_pmf_gpu_init(struct amd_gpu_pmf_data *pmf);
> +void amd_pmf_gpu_deinit(struct amd_gpu_pmf_data *pmf);
> +#endif
> 

-- 
 i.


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

* Re: [PATCH v4 13/17] platform/x86/amd/pmf: Add PMF-AMDGPU get interface
  2023-10-18  9:20   ` Ilpo Järvinen
@ 2023-10-18  9:28     ` Shyam Sundar S K
  2023-10-18  9:37       ` Ilpo Järvinen
  2023-10-18 13:40       ` Christian König
  0 siblings, 2 replies; 35+ messages in thread
From: Shyam Sundar S K @ 2023-10-18  9:28 UTC (permalink / raw)
  To: Ilpo Järvinen
  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 10/18/2023 2:50 PM, Ilpo Järvinen wrote:
> On Wed, 18 Oct 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 | 138 ++++++++++++++++++++++++
>>  drivers/platform/x86/amd/pmf/Kconfig    |   1 +
>>  drivers/platform/x86/amd/pmf/core.c     |   1 +
>>  drivers/platform/x86/amd/pmf/pmf.h      |   3 +
>>  drivers/platform/x86/amd/pmf/spc.c      |  13 +++
>>  drivers/platform/x86/amd/pmf/tee-if.c   |  26 +++++
>>  include/linux/amd-pmf-io.h              |  35 ++++++
>>  9 files changed, 220 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 a79d53bdbe13..26ffa1b4fe57 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..ac981848df50
>> --- /dev/null
>> +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_pmf.c
>> @@ -0,0 +1,138 @@
>> +/*
>> + * 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.
> 
> This is MIT, right? Add the required SPDX-License-Identifier line for it
> at the top of the file, thank you.
> 

all the files in drivers/gpu/drm/amd/amdgpu/* carry the same license
text. So, have retained it to maintain uniformity.

>> + *
>> + * Author: Shyam Sundar S K <Shyam-sundar.S-k@amd.com>
>> + *
>> + */
> 
> Remove the extra empty line at the end of the comment.
> 

I just took the standard template for all the gpu files. Is that OK to
retain the blank line?

If not, I can remove it in the next version.

Rest all remarks I will address.

Thanks,
Shyam

>> +
>> +#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;
>> +	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;
>> +	}
>> +
>> +	mutex_lock(&mode_config->mutex);
>> +	drm_connector_list_iter_begin(drm_dev, &iter);
>> +	drm_for_each_connector_iter(connector, &iter) {
>> +		if (connector->status == connector_status_connected)
>> +			pmf->display_count++;
>> +		if (connector->status != pmf->con_status[i])
>> +			pmf->con_status[i] = connector->status;
>> +		if (connector->connector_type != pmf->connector_type[i])
>> +			pmf->connector_type[i] = connector->connector_type;
>> +
>> +		i++;
>> +		if (i >= MAX_SUPPORTED)
>> +			break;
>> +	}
>> +	drm_connector_list_iter_end(&iter);
>> +	mutex_unlock(&mode_config->mutex);
>> +
>> +	return 0;
>> +}
>> +EXPORT_SYMBOL_GPL(amd_pmf_get_gfx_data);
>> +
>> +static int amd_pmf_gpu_get_cur_state(struct thermal_cooling_device *cooling_dev,
>> +				     unsigned long *state)
>> +{
>> +	struct backlight_device *bd;
>> +
>> +	if (!acpi_video_backlight_use_native())
>> +		return -ENODEV;
>> +
>> +	bd = backlight_device_get_by_type(BACKLIGHT_RAW);
>> +	if (!bd)
>> +		return -ENODEV;
>> +
>> +	*state = backlight_get_brightness(bd);
>> +
>> +	return 0;
>> +}
>> +
>> +static int amd_pmf_gpu_get_max_state(struct thermal_cooling_device *cooling_dev,
>> +				     unsigned long *state)
>> +{
>> +	struct backlight_device *bd;
>> +
>> +	if (!acpi_video_backlight_use_native())
>> +		return -ENODEV;
>> +
>> +	bd = backlight_device_get_by_type(BACKLIGHT_RAW);
>> +	if (!bd)
>> +		return -ENODEV;
>> +
>> +	if (backlight_is_blank(bd))
>> +		*state = 0;
>> +	else
>> +		*state = bd->props.max_brightness;
>> +
>> +	return 0;
>> +}
>> +
>> +static const struct thermal_cooling_device_ops bd_cooling_ops = {
>> +	.get_max_state = amd_pmf_gpu_get_max_state,
>> +	.get_cur_state = amd_pmf_gpu_get_cur_state,
>> +};
>> +
>> +int amd_pmf_gpu_init(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);
>> +
>> +	if (!(adev->flags & AMD_IS_APU)) {
>> +		DRM_ERROR("PMF-AMDGPU interface not supported\n");
>> +		return -ENODEV;
>> +	}
>> +
>> +	if (!acpi_video_backlight_use_native())
>> +		return -ENODEV;
>> +
>> +	pmf->raw_bd = backlight_device_get_by_type(BACKLIGHT_RAW);
>> +	if (!pmf->raw_bd)
>> +		return -ENODEV;
>> +
>> +	pmf->cooling_dev = thermal_cooling_device_register("pmf_gpu_bd",
>> +							   pmf, &bd_cooling_ops);
>> +	if (IS_ERR(pmf->cooling_dev))
>> +		return -ENODEV;
>> +
>> +	return 0;
>> +}
>> +EXPORT_SYMBOL_GPL(amd_pmf_gpu_init);
>> +
>> +void amd_pmf_gpu_deinit(struct amd_gpu_pmf_data *pmf)
>> +{
>> +	thermal_cooling_device_unregister(pmf->cooling_dev);
>> +}
>> +EXPORT_SYMBOL_GPL(amd_pmf_gpu_deinit);
>> diff --git a/drivers/platform/x86/amd/pmf/Kconfig b/drivers/platform/x86/amd/pmf/Kconfig
>> index f246252bddd8..7f430de7af44 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 TEE && 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 4b8156033fa6..c59ba527ff49 100644
>> --- a/drivers/platform/x86/amd/pmf/core.c
>> +++ b/drivers/platform/x86/amd/pmf/core.c
>> @@ -411,6 +411,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 8712299ad52b..615cd3a31986 100644
>> --- a/drivers/platform/x86/amd/pmf/pmf.h
>> +++ b/drivers/platform/x86/amd/pmf/pmf.h
>> @@ -13,6 +13,7 @@
>>  
>>  #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
>> @@ -228,9 +229,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 512e0c66efdc..cf4962ef97c2 100644
>> --- a/drivers/platform/x86/amd/pmf/spc.c
>> +++ b/drivers/platform/x86/amd/pmf/spc.c
>> @@ -44,6 +44,10 @@ void amd_pmf_dump_ta_inputs(struct amd_pmf_dev *dev, struct ta_pmf_enact_table *
>>  	dev_dbg(dev->dev, "Max C0 Residency : %u\n", in->ev_info.max_c0residency);
>>  	dev_dbg(dev->dev, "GFX Busy : %u\n", in->ev_info.gfx_busy);
>>  	dev_dbg(dev->dev, "Connected Display Count : %u\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");
>>  }
>> @@ -146,6 +150,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 */
>> @@ -154,4 +166,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 2f5fb8623c20..956e66b78605 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"
>> @@ -357,6 +358,19 @@ 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) {
>> +		/* Found the amdgpu handle from the pci root after walking through the pci bus */
> 
> If you insist on having this comment, make it a function comment instead 
> (with appropriate modifications into the content of it) but I personally 
> don't find it that useful so it could be just dropped as well, IMO.
> 
>> +		dev->gfx_data.gpu_dev = 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;
>> @@ -446,6 +460,15 @@ 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 */
> 
> Useless comment.
> 
>> +	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");
>> +
>> +	if (!amd_pmf_gpu_init(&dev->gfx_data))
>> +		dev->gfx_data.gpu_dev_en = true;
>> +
>>  	dev->prev_data = kzalloc(sizeof(*dev->prev_data), GFP_KERNEL);
>>  	if (!dev->prev_data)
>>  		return -ENOMEM;
>> @@ -461,5 +484,8 @@ 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);
>> +	if (dev->gfx_data.gpu_dev_en)
>> +		amd_pmf_gpu_deinit(&dev->gfx_data);
>> +	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..5f79e66a41b3
>> --- /dev/null
>> +++ b/include/linux/amd-pmf-io.h
>> @@ -0,0 +1,35 @@
>> +/* 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 <acpi/video.h>
>> +#include <drm/drm_connector.h>
>> +#include <linux/backlight.h>
>> +#include <linux/thermal.h>
>> +
>> +#define MAX_SUPPORTED 4
>> +
>> +/* amdgpu */
> 
> Document the structure properly with kerneldoc instead of an unhelpful 
> comment like above :-). Please also check if you add any other structs 
> into kernel-wide headers that you didn't document yet. Or fields into 
> existing structs.
> 
>> +struct amd_gpu_pmf_data {
>> +	struct pci_dev *gpu_dev;
>> +	struct backlight_device *raw_bd;
>> +	struct thermal_cooling_device *cooling_dev;
>> +	enum drm_connector_status con_status[MAX_SUPPORTED];
>> +	int display_count;
>> +	int connector_type[MAX_SUPPORTED];
>> +	bool gpu_dev_en;
>> +};
>> +
>> +int amd_pmf_get_gfx_data(struct amd_gpu_pmf_data *pmf);
>> +int amd_pmf_gpu_init(struct amd_gpu_pmf_data *pmf);
>> +void amd_pmf_gpu_deinit(struct amd_gpu_pmf_data *pmf);
>> +#endif
>>
> 

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

* Re: [PATCH v4 13/17] platform/x86/amd/pmf: Add PMF-AMDGPU get interface
  2023-10-18  9:28     ` Shyam Sundar S K
@ 2023-10-18  9:37       ` Ilpo Järvinen
  2023-10-18 13:40       ` Christian König
  1 sibling, 0 replies; 35+ messages in thread
From: Ilpo Järvinen @ 2023-10-18  9:37 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: 4635 bytes --]

On Wed, 18 Oct 2023, Shyam Sundar S K wrote:
> On 10/18/2023 2:50 PM, Ilpo Järvinen wrote:
> > On Wed, 18 Oct 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 | 138 ++++++++++++++++++++++++
> >>  drivers/platform/x86/amd/pmf/Kconfig    |   1 +
> >>  drivers/platform/x86/amd/pmf/core.c     |   1 +
> >>  drivers/platform/x86/amd/pmf/pmf.h      |   3 +
> >>  drivers/platform/x86/amd/pmf/spc.c      |  13 +++
> >>  drivers/platform/x86/amd/pmf/tee-if.c   |  26 +++++
> >>  include/linux/amd-pmf-io.h              |  35 ++++++
> >>  9 files changed, 220 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 a79d53bdbe13..26ffa1b4fe57 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..ac981848df50
> >> --- /dev/null
> >> +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_pmf.c
> >> @@ -0,0 +1,138 @@
> >> +/*
> >> + * 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.
> > 
> > This is MIT, right? Add the required SPDX-License-Identifier line for it
> > at the top of the file, thank you.
> > 
> 
> all the files in drivers/gpu/drm/amd/amdgpu/* carry the same license
> text. So, have retained it to maintain uniformity.

What does adding SPDX identifier line at the top of the file take away 
from that? I'd be fine if you want to add the identifier line to all of 
them too to keep them identical.

> >> + *
> >> + * Author: Shyam Sundar S K <Shyam-sundar.S-k@amd.com>
> >> + *
> >> + */
> > 
> > Remove the extra empty line at the end of the comment.
> > 
> 
> I just took the standard template for all the gpu files. Is that OK to
> retain the blank line?
> 
> If not, I can remove it in the next version.

I don't want to fight over a blank line when you insist on keeping it :-).

-- 
 i.

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

* Re: [PATCH v4 12/17] platform/x86/amd/pmf: dump policy binary data
  2023-10-18  7:02 ` [PATCH v4 12/17] platform/x86/amd/pmf: dump policy binary data Shyam Sundar S K
@ 2023-10-18 10:09   ` Ilpo Järvinen
  0 siblings, 0 replies; 35+ messages in thread
From: Ilpo Järvinen @ 2023-10-18 10:09 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: 2148 bytes --]

On Wed, 18 Oct 2023, 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.
> 
> 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/tee-if.c | 9 +++++++++
>  1 file changed, 9 insertions(+)
> 
> diff --git a/drivers/platform/x86/amd/pmf/tee-if.c b/drivers/platform/x86/amd/pmf/tee-if.c
> index 6c4ce22ba518..2f5fb8623c20 100644
> --- a/drivers/platform/x86/amd/pmf/tee-if.c
> +++ b/drivers/platform/x86/amd/pmf/tee-if.c
> @@ -276,6 +276,12 @@ static int amd_pmf_start_policy_engine(struct amd_pmf_dev *dev)
>  }
>  
>  #ifdef CONFIG_AMD_PMF_DEBUG
> +static void amd_pmf_hex_dump_pb(struct amd_pmf_dev *dev)
> +{
> +	print_hex_dump_debug("(pb):  ", DUMP_PREFIX_OFFSET, 16, 1, dev->policy_buf,
> +			     dev->policy_sz, false);
> +}
> +
>  static ssize_t amd_pmf_get_pb_data(struct file *filp, const char __user *buf,
>  				   size_t length, loff_t *pos)
>  {
> @@ -290,6 +296,7 @@ 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;
>  
> +	amd_pmf_hex_dump_pb(dev);
>  	ret = amd_pmf_start_policy_engine(dev);
>  	if (ret)
>  		return -EINVAL;
> @@ -328,6 +335,7 @@ static int amd_pmf_open_pb(struct amd_pmf_dev *dev, struct dentry *debugfs_root)
>  }
>  
>  static void amd_pmf_remove_pb(struct amd_pmf_dev *dev) {}
> +static void amd_pmf_hex_dump_pb(struct amd_pmf_dev *dev) {}
>  #endif
>  
>  static int amd_pmf_get_bios_buffer(struct amd_pmf_dev *dev)
> @@ -342,6 +350,7 @@ static int amd_pmf_get_bios_buffer(struct amd_pmf_dev *dev)
>  
>  	memcpy(dev->policy_buf, dev->policy_base, dev->policy_sz);
>  
> +	amd_pmf_hex_dump_pb(dev);
>  	if (pb_side_load)
>  		amd_pmf_open_pb(dev, dev->dbgfs_dir);

Reviewed-by: Ilpo Järvinen <ilpo.jarvinen@linux.intel.com>

-- 
 i.

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

* Re: [PATCH v4 11/17] platform/x86/amd/pmf: Add capability to sideload of policy binary
  2023-10-18  7:02 ` [PATCH v4 11/17] platform/x86/amd/pmf: Add capability to sideload of policy binary Shyam Sundar S K
@ 2023-10-18 10:21   ` Ilpo Järvinen
  0 siblings, 0 replies; 35+ messages in thread
From: Ilpo Järvinen @ 2023-10-18 10:21 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 Wed, 18 Oct 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 | 67 +++++++++++++++++++++++++++
>  2 files changed, 68 insertions(+)
> 
> diff --git a/drivers/platform/x86/amd/pmf/pmf.h b/drivers/platform/x86/amd/pmf/pmf.h
> index 593930519039..8712299ad52b 100644
> --- a/drivers/platform/x86/amd/pmf/pmf.h
> +++ b/drivers/platform/x86/amd/pmf/pmf.h
> @@ -219,6 +219,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 0eba258f4040..6c4ce22ba518 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"
> @@ -16,9 +17,14 @@
>  
>  /* Policy binary actions sampling frequency (in ms) */
>  static int pb_actions_ms = MSEC_PER_SEC;
> +/* Sideload policy binaries to debug policy failures */
> +static bool pb_side_load;
> +
>  #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)");
> +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,
> @@ -269,6 +275,61 @@ 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,
> +};
> +
> +static 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)

debugfs_create_file() returns ERR_PTR() on errors. I don't actually know 
if NULL even needs to be checked or if it'd return errno in that case 
because the usually custom is to just ignore debugfs_create_file() 
return value.

Why is this function returning int anyway? It's not checked by the caller 
so why bother when all it does is deal with debugfs for which the normal 
approach is to ignore the errors.

-- 
 i.


> +		return -EINVAL;
> +
> +	return 0;
> +}
> +
> +static void amd_pmf_remove_pb(struct amd_pmf_dev *dev)
> +{
> +	debugfs_remove_recursive(dev->esbin);
> +}
> +#else
> +static int amd_pmf_open_pb(struct amd_pmf_dev *dev, struct dentry *debugfs_root)
> +{
> +	return 0;
> +}
> +
> +static void amd_pmf_remove_pb(struct amd_pmf_dev *dev) {}
> +#endif
> +
>  static int amd_pmf_get_bios_buffer(struct amd_pmf_dev *dev)
>  {
>  	dev->policy_buf = kzalloc(dev->policy_sz, GFP_KERNEL);
> @@ -281,6 +342,9 @@ static int amd_pmf_get_bios_buffer(struct amd_pmf_dev *dev)
>  
>  	memcpy(dev->policy_buf, dev->policy_base, dev->policy_sz);
>  
> +	if (pb_side_load)
> +		amd_pmf_open_pb(dev, dev->dbgfs_dir);
> +
>  	return amd_pmf_start_policy_engine(dev);
>  }
>  
> @@ -382,6 +446,9 @@ int amd_pmf_init_smart_pc(struct amd_pmf_dev *dev)
>  
>  void amd_pmf_deinit_smart_pc(struct amd_pmf_dev *dev)
>  {
> +	if (pb_side_load)
> +		amd_pmf_remove_pb(dev);
> +
>  	kfree(dev->prev_data);
>  	kfree(dev->policy_buf);
>  	cancel_delayed_work_sync(&dev->pb_work);
> 

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

* Re: [PATCH v4 13/17] platform/x86/amd/pmf: Add PMF-AMDGPU get interface
  2023-10-18  9:28     ` Shyam Sundar S K
  2023-10-18  9:37       ` Ilpo Järvinen
@ 2023-10-18 13:40       ` Christian König
  2023-10-18 15:47         ` Mario Limonciello
  1 sibling, 1 reply; 35+ messages in thread
From: Christian König @ 2023-10-18 13:40 UTC (permalink / raw)
  To: Shyam Sundar S K, Ilpo Järvinen
  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



Am 18.10.23 um 11:28 schrieb Shyam Sundar S K:
>
> On 10/18/2023 2:50 PM, Ilpo Järvinen wrote:
>> On Wed, 18 Oct 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 | 138 ++++++++++++++++++++++++
>>>   drivers/platform/x86/amd/pmf/Kconfig    |   1 +
>>>   drivers/platform/x86/amd/pmf/core.c     |   1 +
>>>   drivers/platform/x86/amd/pmf/pmf.h      |   3 +
>>>   drivers/platform/x86/amd/pmf/spc.c      |  13 +++
>>>   drivers/platform/x86/amd/pmf/tee-if.c   |  26 +++++
>>>   include/linux/amd-pmf-io.h              |  35 ++++++
>>>   9 files changed, 220 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 a79d53bdbe13..26ffa1b4fe57 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..ac981848df50
>>> --- /dev/null
>>> +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_pmf.c
>>> @@ -0,0 +1,138 @@
>>> +/*
>>> + * 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.
>> This is MIT, right? Add the required SPDX-License-Identifier line for it
>> at the top of the file, thank you.
>>
> all the files in drivers/gpu/drm/amd/amdgpu/* carry the same license
> text. So, have retained it to maintain uniformity.

Please add the SPDX License Identifier for any file you add.

Apart from that the whole approach of attaching this directly to amdgpu 
looks extremely questionable to me.

Regards,
Christian.

>
>>> + *
>>> + * Author: Shyam Sundar S K <Shyam-sundar.S-k@amd.com>
>>> + *
>>> + */
>> Remove the extra empty line at the end of the comment.
>>
> I just took the standard template for all the gpu files. Is that OK to
> retain the blank line?
>
> If not, I can remove it in the next version.
>
> Rest all remarks I will address.
>
> Thanks,
> Shyam
>
>>> +
>>> +#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;
>>> +	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;
>>> +	}
>>> +
>>> +	mutex_lock(&mode_config->mutex);
>>> +	drm_connector_list_iter_begin(drm_dev, &iter);
>>> +	drm_for_each_connector_iter(connector, &iter) {
>>> +		if (connector->status == connector_status_connected)
>>> +			pmf->display_count++;
>>> +		if (connector->status != pmf->con_status[i])
>>> +			pmf->con_status[i] = connector->status;
>>> +		if (connector->connector_type != pmf->connector_type[i])
>>> +			pmf->connector_type[i] = connector->connector_type;
>>> +
>>> +		i++;
>>> +		if (i >= MAX_SUPPORTED)
>>> +			break;
>>> +	}
>>> +	drm_connector_list_iter_end(&iter);
>>> +	mutex_unlock(&mode_config->mutex);
>>> +
>>> +	return 0;
>>> +}
>>> +EXPORT_SYMBOL_GPL(amd_pmf_get_gfx_data);
>>> +
>>> +static int amd_pmf_gpu_get_cur_state(struct thermal_cooling_device *cooling_dev,
>>> +				     unsigned long *state)
>>> +{
>>> +	struct backlight_device *bd;
>>> +
>>> +	if (!acpi_video_backlight_use_native())
>>> +		return -ENODEV;
>>> +
>>> +	bd = backlight_device_get_by_type(BACKLIGHT_RAW);
>>> +	if (!bd)
>>> +		return -ENODEV;
>>> +
>>> +	*state = backlight_get_brightness(bd);
>>> +
>>> +	return 0;
>>> +}
>>> +
>>> +static int amd_pmf_gpu_get_max_state(struct thermal_cooling_device *cooling_dev,
>>> +				     unsigned long *state)
>>> +{
>>> +	struct backlight_device *bd;
>>> +
>>> +	if (!acpi_video_backlight_use_native())
>>> +		return -ENODEV;
>>> +
>>> +	bd = backlight_device_get_by_type(BACKLIGHT_RAW);
>>> +	if (!bd)
>>> +		return -ENODEV;
>>> +
>>> +	if (backlight_is_blank(bd))
>>> +		*state = 0;
>>> +	else
>>> +		*state = bd->props.max_brightness;
>>> +
>>> +	return 0;
>>> +}
>>> +
>>> +static const struct thermal_cooling_device_ops bd_cooling_ops = {
>>> +	.get_max_state = amd_pmf_gpu_get_max_state,
>>> +	.get_cur_state = amd_pmf_gpu_get_cur_state,
>>> +};
>>> +
>>> +int amd_pmf_gpu_init(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);
>>> +
>>> +	if (!(adev->flags & AMD_IS_APU)) {
>>> +		DRM_ERROR("PMF-AMDGPU interface not supported\n");
>>> +		return -ENODEV;
>>> +	}
>>> +
>>> +	if (!acpi_video_backlight_use_native())
>>> +		return -ENODEV;
>>> +
>>> +	pmf->raw_bd = backlight_device_get_by_type(BACKLIGHT_RAW);
>>> +	if (!pmf->raw_bd)
>>> +		return -ENODEV;
>>> +
>>> +	pmf->cooling_dev = thermal_cooling_device_register("pmf_gpu_bd",
>>> +							   pmf, &bd_cooling_ops);
>>> +	if (IS_ERR(pmf->cooling_dev))
>>> +		return -ENODEV;
>>> +
>>> +	return 0;
>>> +}
>>> +EXPORT_SYMBOL_GPL(amd_pmf_gpu_init);
>>> +
>>> +void amd_pmf_gpu_deinit(struct amd_gpu_pmf_data *pmf)
>>> +{
>>> +	thermal_cooling_device_unregister(pmf->cooling_dev);
>>> +}
>>> +EXPORT_SYMBOL_GPL(amd_pmf_gpu_deinit);
>>> diff --git a/drivers/platform/x86/amd/pmf/Kconfig b/drivers/platform/x86/amd/pmf/Kconfig
>>> index f246252bddd8..7f430de7af44 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 TEE && 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 4b8156033fa6..c59ba527ff49 100644
>>> --- a/drivers/platform/x86/amd/pmf/core.c
>>> +++ b/drivers/platform/x86/amd/pmf/core.c
>>> @@ -411,6 +411,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 8712299ad52b..615cd3a31986 100644
>>> --- a/drivers/platform/x86/amd/pmf/pmf.h
>>> +++ b/drivers/platform/x86/amd/pmf/pmf.h
>>> @@ -13,6 +13,7 @@
>>>   
>>>   #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
>>> @@ -228,9 +229,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 512e0c66efdc..cf4962ef97c2 100644
>>> --- a/drivers/platform/x86/amd/pmf/spc.c
>>> +++ b/drivers/platform/x86/amd/pmf/spc.c
>>> @@ -44,6 +44,10 @@ void amd_pmf_dump_ta_inputs(struct amd_pmf_dev *dev, struct ta_pmf_enact_table *
>>>   	dev_dbg(dev->dev, "Max C0 Residency : %u\n", in->ev_info.max_c0residency);
>>>   	dev_dbg(dev->dev, "GFX Busy : %u\n", in->ev_info.gfx_busy);
>>>   	dev_dbg(dev->dev, "Connected Display Count : %u\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");
>>>   }
>>> @@ -146,6 +150,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 */
>>> @@ -154,4 +166,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 2f5fb8623c20..956e66b78605 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"
>>> @@ -357,6 +358,19 @@ 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) {
>>> +		/* Found the amdgpu handle from the pci root after walking through the pci bus */
>> If you insist on having this comment, make it a function comment instead
>> (with appropriate modifications into the content of it) but I personally
>> don't find it that useful so it could be just dropped as well, IMO.
>>
>>> +		dev->gfx_data.gpu_dev = 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;
>>> @@ -446,6 +460,15 @@ 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 */
>> Useless comment.
>>
>>> +	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");
>>> +
>>> +	if (!amd_pmf_gpu_init(&dev->gfx_data))
>>> +		dev->gfx_data.gpu_dev_en = true;
>>> +
>>>   	dev->prev_data = kzalloc(sizeof(*dev->prev_data), GFP_KERNEL);
>>>   	if (!dev->prev_data)
>>>   		return -ENOMEM;
>>> @@ -461,5 +484,8 @@ 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);
>>> +	if (dev->gfx_data.gpu_dev_en)
>>> +		amd_pmf_gpu_deinit(&dev->gfx_data);
>>> +	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..5f79e66a41b3
>>> --- /dev/null
>>> +++ b/include/linux/amd-pmf-io.h
>>> @@ -0,0 +1,35 @@
>>> +/* 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 <acpi/video.h>
>>> +#include <drm/drm_connector.h>
>>> +#include <linux/backlight.h>
>>> +#include <linux/thermal.h>
>>> +
>>> +#define MAX_SUPPORTED 4
>>> +
>>> +/* amdgpu */
>> Document the structure properly with kerneldoc instead of an unhelpful
>> comment like above :-). Please also check if you add any other structs
>> into kernel-wide headers that you didn't document yet. Or fields into
>> existing structs.
>>
>>> +struct amd_gpu_pmf_data {
>>> +	struct pci_dev *gpu_dev;
>>> +	struct backlight_device *raw_bd;
>>> +	struct thermal_cooling_device *cooling_dev;
>>> +	enum drm_connector_status con_status[MAX_SUPPORTED];
>>> +	int display_count;
>>> +	int connector_type[MAX_SUPPORTED];
>>> +	bool gpu_dev_en;
>>> +};
>>> +
>>> +int amd_pmf_get_gfx_data(struct amd_gpu_pmf_data *pmf);
>>> +int amd_pmf_gpu_init(struct amd_gpu_pmf_data *pmf);
>>> +void amd_pmf_gpu_deinit(struct amd_gpu_pmf_data *pmf);
>>> +#endif
>>>


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

* Re: [PATCH v4 13/17] platform/x86/amd/pmf: Add PMF-AMDGPU get interface
  2023-10-18 13:40       ` Christian König
@ 2023-10-18 15:47         ` Mario Limonciello
  2023-10-18 16:07           ` Christian König
  2023-10-18 19:08           ` Hans de Goede
  0 siblings, 2 replies; 35+ messages in thread
From: Mario Limonciello @ 2023-10-18 15:47 UTC (permalink / raw)
  To: Christian König, Shyam Sundar S K, Ilpo Järvinen
  Cc: Xinhui.Pan, Patil.Reddy, basavaraj.natikar, jikos, amd-gfx,
	platform-driver-x86, markgross, Hans de Goede,
	benjamin.tissoires, dri-devel, linux-input, alexander.deucher

On 10/18/2023 08:40, Christian König wrote:
> 
> 
> Am 18.10.23 um 11:28 schrieb Shyam Sundar S K:
>>
>> On 10/18/2023 2:50 PM, Ilpo Järvinen wrote:
>>> On Wed, 18 Oct 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 | 138 
>>>> ++++++++++++++++++++++++
>>>>   drivers/platform/x86/amd/pmf/Kconfig    |   1 +
>>>>   drivers/platform/x86/amd/pmf/core.c     |   1 +
>>>>   drivers/platform/x86/amd/pmf/pmf.h      |   3 +
>>>>   drivers/platform/x86/amd/pmf/spc.c      |  13 +++
>>>>   drivers/platform/x86/amd/pmf/tee-if.c   |  26 +++++
>>>>   include/linux/amd-pmf-io.h              |  35 ++++++
>>>>   9 files changed, 220 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 a79d53bdbe13..26ffa1b4fe57 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..ac981848df50
>>>> --- /dev/null
>>>> +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_pmf.c
>>>> @@ -0,0 +1,138 @@
>>>> +/*
>>>> + * 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.
>>> This is MIT, right? Add the required SPDX-License-Identifier line for it
>>> at the top of the file, thank you.
>>>
>> all the files in drivers/gpu/drm/amd/amdgpu/* carry the same license
>> text. So, have retained it to maintain uniformity.
> 
> Please add the SPDX License Identifier for any file you add.
> 
> Apart from that the whole approach of attaching this directly to amdgpu 
> looks extremely questionable to me.
> 

What's the long term outlook for things that are needed directly from 
amdgpu?  Is there going to be more besides the backlight and the display 
count/type?

At least for the display count I suppose one way that it could be 
"decoupled" from amdgpu is to use drm_for_each_connector_iter to iterate 
all the connectors and then count the connected ones.

> Regards,
> Christian.
> 
>>
>>>> + *
>>>> + * Author: Shyam Sundar S K <Shyam-sundar.S-k@amd.com>
>>>> + *
>>>> + */
>>> Remove the extra empty line at the end of the comment.
>>>
>> I just took the standard template for all the gpu files. Is that OK to
>> retain the blank line?
>>
>> If not, I can remove it in the next version.
>>
>> Rest all remarks I will address.
>>
>> Thanks,
>> Shyam
>>
>>>> +
>>>> +#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;
>>>> +    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;
>>>> +    }
>>>> +
>>>> +    mutex_lock(&mode_config->mutex);
>>>> +    drm_connector_list_iter_begin(drm_dev, &iter);
>>>> +    drm_for_each_connector_iter(connector, &iter) {
>>>> +        if (connector->status == connector_status_connected)
>>>> +            pmf->display_count++;
>>>> +        if (connector->status != pmf->con_status[i])
>>>> +            pmf->con_status[i] = connector->status;
>>>> +        if (connector->connector_type != pmf->connector_type[i])
>>>> +            pmf->connector_type[i] = connector->connector_type;
>>>> +
>>>> +        i++;
>>>> +        if (i >= MAX_SUPPORTED)
>>>> +            break;
>>>> +    }
>>>> +    drm_connector_list_iter_end(&iter);
>>>> +    mutex_unlock(&mode_config->mutex);
>>>> +
>>>> +    return 0;
>>>> +}
>>>> +EXPORT_SYMBOL_GPL(amd_pmf_get_gfx_data);
>>>> +
>>>> +static int amd_pmf_gpu_get_cur_state(struct thermal_cooling_device 
>>>> *cooling_dev,
>>>> +                     unsigned long *state)
>>>> +{
>>>> +    struct backlight_device *bd;
>>>> +
>>>> +    if (!acpi_video_backlight_use_native())
>>>> +        return -ENODEV;
>>>> +
>>>> +    bd = backlight_device_get_by_type(BACKLIGHT_RAW);
>>>> +    if (!bd)
>>>> +        return -ENODEV;
>>>> +
>>>> +    *state = backlight_get_brightness(bd);
>>>> +
>>>> +    return 0;
>>>> +}
>>>> +
>>>> +static int amd_pmf_gpu_get_max_state(struct thermal_cooling_device 
>>>> *cooling_dev,
>>>> +                     unsigned long *state)
>>>> +{
>>>> +    struct backlight_device *bd;
>>>> +
>>>> +    if (!acpi_video_backlight_use_native())
>>>> +        return -ENODEV;
>>>> +
>>>> +    bd = backlight_device_get_by_type(BACKLIGHT_RAW);
>>>> +    if (!bd)
>>>> +        return -ENODEV;
>>>> +
>>>> +    if (backlight_is_blank(bd))
>>>> +        *state = 0;
>>>> +    else
>>>> +        *state = bd->props.max_brightness;
>>>> +
>>>> +    return 0;
>>>> +}
>>>> +
>>>> +static const struct thermal_cooling_device_ops bd_cooling_ops = {
>>>> +    .get_max_state = amd_pmf_gpu_get_max_state,
>>>> +    .get_cur_state = amd_pmf_gpu_get_cur_state,
>>>> +};
>>>> +
>>>> +int amd_pmf_gpu_init(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);
>>>> +
>>>> +    if (!(adev->flags & AMD_IS_APU)) {
>>>> +        DRM_ERROR("PMF-AMDGPU interface not supported\n");
>>>> +        return -ENODEV;
>>>> +    }
>>>> +
>>>> +    if (!acpi_video_backlight_use_native())
>>>> +        return -ENODEV;
>>>> +
>>>> +    pmf->raw_bd = backlight_device_get_by_type(BACKLIGHT_RAW);
>>>> +    if (!pmf->raw_bd)
>>>> +        return -ENODEV;
>>>> +
>>>> +    pmf->cooling_dev = thermal_cooling_device_register("pmf_gpu_bd",
>>>> +                               pmf, &bd_cooling_ops);
>>>> +    if (IS_ERR(pmf->cooling_dev))
>>>> +        return -ENODEV;
>>>> +
>>>> +    return 0;
>>>> +}
>>>> +EXPORT_SYMBOL_GPL(amd_pmf_gpu_init);
>>>> +
>>>> +void amd_pmf_gpu_deinit(struct amd_gpu_pmf_data *pmf)
>>>> +{
>>>> +    thermal_cooling_device_unregister(pmf->cooling_dev);
>>>> +}
>>>> +EXPORT_SYMBOL_GPL(amd_pmf_gpu_deinit);
>>>> diff --git a/drivers/platform/x86/amd/pmf/Kconfig 
>>>> b/drivers/platform/x86/amd/pmf/Kconfig
>>>> index f246252bddd8..7f430de7af44 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 TEE && 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 4b8156033fa6..c59ba527ff49 100644
>>>> --- a/drivers/platform/x86/amd/pmf/core.c
>>>> +++ b/drivers/platform/x86/amd/pmf/core.c
>>>> @@ -411,6 +411,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 8712299ad52b..615cd3a31986 100644
>>>> --- a/drivers/platform/x86/amd/pmf/pmf.h
>>>> +++ b/drivers/platform/x86/amd/pmf/pmf.h
>>>> @@ -13,6 +13,7 @@
>>>>   #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
>>>> @@ -228,9 +229,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 512e0c66efdc..cf4962ef97c2 100644
>>>> --- a/drivers/platform/x86/amd/pmf/spc.c
>>>> +++ b/drivers/platform/x86/amd/pmf/spc.c
>>>> @@ -44,6 +44,10 @@ void amd_pmf_dump_ta_inputs(struct amd_pmf_dev 
>>>> *dev, struct ta_pmf_enact_table *
>>>>       dev_dbg(dev->dev, "Max C0 Residency : %u\n", 
>>>> in->ev_info.max_c0residency);
>>>>       dev_dbg(dev->dev, "GFX Busy : %u\n", in->ev_info.gfx_busy);
>>>>       dev_dbg(dev->dev, "Connected Display Count : %u\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");
>>>>   }
>>>> @@ -146,6 +150,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 */
>>>> @@ -154,4 +166,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 2f5fb8623c20..956e66b78605 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"
>>>> @@ -357,6 +358,19 @@ 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) {
>>>> +        /* Found the amdgpu handle from the pci root after walking 
>>>> through the pci bus */
>>> If you insist on having this comment, make it a function comment instead
>>> (with appropriate modifications into the content of it) but I personally
>>> don't find it that useful so it could be just dropped as well, IMO.
>>>
>>>> +        dev->gfx_data.gpu_dev = 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;
>>>> @@ -446,6 +460,15 @@ 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 */
>>> Useless comment.
>>>
>>>> +    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");
>>>> +
>>>> +    if (!amd_pmf_gpu_init(&dev->gfx_data))
>>>> +        dev->gfx_data.gpu_dev_en = true;
>>>> +
>>>>       dev->prev_data = kzalloc(sizeof(*dev->prev_data), GFP_KERNEL);
>>>>       if (!dev->prev_data)
>>>>           return -ENOMEM;
>>>> @@ -461,5 +484,8 @@ 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);
>>>> +    if (dev->gfx_data.gpu_dev_en)
>>>> +        amd_pmf_gpu_deinit(&dev->gfx_data);
>>>> +    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..5f79e66a41b3
>>>> --- /dev/null
>>>> +++ b/include/linux/amd-pmf-io.h
>>>> @@ -0,0 +1,35 @@
>>>> +/* 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 <acpi/video.h>
>>>> +#include <drm/drm_connector.h>
>>>> +#include <linux/backlight.h>
>>>> +#include <linux/thermal.h>
>>>> +
>>>> +#define MAX_SUPPORTED 4
>>>> +
>>>> +/* amdgpu */
>>> Document the structure properly with kerneldoc instead of an unhelpful
>>> comment like above :-). Please also check if you add any other structs
>>> into kernel-wide headers that you didn't document yet. Or fields into
>>> existing structs.
>>>
>>>> +struct amd_gpu_pmf_data {
>>>> +    struct pci_dev *gpu_dev;
>>>> +    struct backlight_device *raw_bd;
>>>> +    struct thermal_cooling_device *cooling_dev;
>>>> +    enum drm_connector_status con_status[MAX_SUPPORTED];
>>>> +    int display_count;
>>>> +    int connector_type[MAX_SUPPORTED];
>>>> +    bool gpu_dev_en;
>>>> +};
>>>> +
>>>> +int amd_pmf_get_gfx_data(struct amd_gpu_pmf_data *pmf);
>>>> +int amd_pmf_gpu_init(struct amd_gpu_pmf_data *pmf);
>>>> +void amd_pmf_gpu_deinit(struct amd_gpu_pmf_data *pmf);
>>>> +#endif
>>>>
> 


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

* Re: [PATCH v4 13/17] platform/x86/amd/pmf: Add PMF-AMDGPU get interface
  2023-10-18 15:47         ` Mario Limonciello
@ 2023-10-18 16:07           ` Christian König
  2023-10-18 17:05             ` Shyam Sundar S K
  2023-10-18 19:08           ` Hans de Goede
  1 sibling, 1 reply; 35+ messages in thread
From: Christian König @ 2023-10-18 16:07 UTC (permalink / raw)
  To: Mario Limonciello, Shyam Sundar S K, Ilpo Järvinen
  Cc: Xinhui.Pan, Patil.Reddy, basavaraj.natikar, jikos, amd-gfx,
	platform-driver-x86, markgross, Hans de Goede,
	benjamin.tissoires, dri-devel, linux-input, alexander.deucher

Am 18.10.23 um 17:47 schrieb Mario Limonciello:
> On 10/18/2023 08:40, Christian König wrote:
>>
>>
>> Am 18.10.23 um 11:28 schrieb Shyam Sundar S K:
>>>
>>> On 10/18/2023 2:50 PM, Ilpo Järvinen wrote:
>>>> On Wed, 18 Oct 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 | 138 
>>>>> ++++++++++++++++++++++++
>>>>>   drivers/platform/x86/amd/pmf/Kconfig    |   1 +
>>>>>   drivers/platform/x86/amd/pmf/core.c     |   1 +
>>>>>   drivers/platform/x86/amd/pmf/pmf.h      |   3 +
>>>>>   drivers/platform/x86/amd/pmf/spc.c      |  13 +++
>>>>>   drivers/platform/x86/amd/pmf/tee-if.c   |  26 +++++
>>>>>   include/linux/amd-pmf-io.h              |  35 ++++++
>>>>>   9 files changed, 220 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 a79d53bdbe13..26ffa1b4fe57 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..ac981848df50
>>>>> --- /dev/null
>>>>> +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_pmf.c
>>>>> @@ -0,0 +1,138 @@
>>>>> +/*
>>>>> + * 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.
>>>> This is MIT, right? Add the required SPDX-License-Identifier line 
>>>> for it
>>>> at the top of the file, thank you.
>>>>
>>> all the files in drivers/gpu/drm/amd/amdgpu/* carry the same license
>>> text. So, have retained it to maintain uniformity.
>>
>> Please add the SPDX License Identifier for any file you add.
>>
>> Apart from that the whole approach of attaching this directly to 
>> amdgpu looks extremely questionable to me.
>>
>
> What's the long term outlook for things that are needed directly from 
> amdgpu?  Is there going to be more besides the backlight and the 
> display count/type?

Yeah, that goes into the same direction as my concern.

>
> At least for the display count I suppose one way that it could be 
> "decoupled" from amdgpu is to use drm_for_each_connector_iter to 
> iterate all the connectors and then count the connected ones.

And what if the number of connected displays change? How is amdgpu 
supposed to signal events like that?

This whole solution doesn't looks well thought through.

Regards,
Christian.

>
>> Regards,
>> Christian.
>>
>>>
>>>>> + *
>>>>> + * Author: Shyam Sundar S K <Shyam-sundar.S-k@amd.com>
>>>>> + *
>>>>> + */
>>>> Remove the extra empty line at the end of the comment.
>>>>
>>> I just took the standard template for all the gpu files. Is that OK to
>>> retain the blank line?
>>>
>>> If not, I can remove it in the next version.
>>>
>>> Rest all remarks I will address.
>>>
>>> Thanks,
>>> Shyam
>>>
>>>>> +
>>>>> +#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;
>>>>> +    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;
>>>>> +    }
>>>>> +
>>>>> +    mutex_lock(&mode_config->mutex);
>>>>> +    drm_connector_list_iter_begin(drm_dev, &iter);
>>>>> +    drm_for_each_connector_iter(connector, &iter) {
>>>>> +        if (connector->status == connector_status_connected)
>>>>> +            pmf->display_count++;
>>>>> +        if (connector->status != pmf->con_status[i])
>>>>> +            pmf->con_status[i] = connector->status;
>>>>> +        if (connector->connector_type != pmf->connector_type[i])
>>>>> +            pmf->connector_type[i] = connector->connector_type;
>>>>> +
>>>>> +        i++;
>>>>> +        if (i >= MAX_SUPPORTED)
>>>>> +            break;
>>>>> +    }
>>>>> +    drm_connector_list_iter_end(&iter);
>>>>> +    mutex_unlock(&mode_config->mutex);
>>>>> +
>>>>> +    return 0;
>>>>> +}
>>>>> +EXPORT_SYMBOL_GPL(amd_pmf_get_gfx_data);
>>>>> +
>>>>> +static int amd_pmf_gpu_get_cur_state(struct 
>>>>> thermal_cooling_device *cooling_dev,
>>>>> +                     unsigned long *state)
>>>>> +{
>>>>> +    struct backlight_device *bd;
>>>>> +
>>>>> +    if (!acpi_video_backlight_use_native())
>>>>> +        return -ENODEV;
>>>>> +
>>>>> +    bd = backlight_device_get_by_type(BACKLIGHT_RAW);
>>>>> +    if (!bd)
>>>>> +        return -ENODEV;
>>>>> +
>>>>> +    *state = backlight_get_brightness(bd);
>>>>> +
>>>>> +    return 0;
>>>>> +}
>>>>> +
>>>>> +static int amd_pmf_gpu_get_max_state(struct 
>>>>> thermal_cooling_device *cooling_dev,
>>>>> +                     unsigned long *state)
>>>>> +{
>>>>> +    struct backlight_device *bd;
>>>>> +
>>>>> +    if (!acpi_video_backlight_use_native())
>>>>> +        return -ENODEV;
>>>>> +
>>>>> +    bd = backlight_device_get_by_type(BACKLIGHT_RAW);
>>>>> +    if (!bd)
>>>>> +        return -ENODEV;
>>>>> +
>>>>> +    if (backlight_is_blank(bd))
>>>>> +        *state = 0;
>>>>> +    else
>>>>> +        *state = bd->props.max_brightness;
>>>>> +
>>>>> +    return 0;
>>>>> +}
>>>>> +
>>>>> +static const struct thermal_cooling_device_ops bd_cooling_ops = {
>>>>> +    .get_max_state = amd_pmf_gpu_get_max_state,
>>>>> +    .get_cur_state = amd_pmf_gpu_get_cur_state,
>>>>> +};
>>>>> +
>>>>> +int amd_pmf_gpu_init(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);
>>>>> +
>>>>> +    if (!(adev->flags & AMD_IS_APU)) {
>>>>> +        DRM_ERROR("PMF-AMDGPU interface not supported\n");
>>>>> +        return -ENODEV;
>>>>> +    }
>>>>> +
>>>>> +    if (!acpi_video_backlight_use_native())
>>>>> +        return -ENODEV;
>>>>> +
>>>>> +    pmf->raw_bd = backlight_device_get_by_type(BACKLIGHT_RAW);
>>>>> +    if (!pmf->raw_bd)
>>>>> +        return -ENODEV;
>>>>> +
>>>>> +    pmf->cooling_dev = thermal_cooling_device_register("pmf_gpu_bd",
>>>>> +                               pmf, &bd_cooling_ops);
>>>>> +    if (IS_ERR(pmf->cooling_dev))
>>>>> +        return -ENODEV;
>>>>> +
>>>>> +    return 0;
>>>>> +}
>>>>> +EXPORT_SYMBOL_GPL(amd_pmf_gpu_init);
>>>>> +
>>>>> +void amd_pmf_gpu_deinit(struct amd_gpu_pmf_data *pmf)
>>>>> +{
>>>>> + thermal_cooling_device_unregister(pmf->cooling_dev);
>>>>> +}
>>>>> +EXPORT_SYMBOL_GPL(amd_pmf_gpu_deinit);
>>>>> diff --git a/drivers/platform/x86/amd/pmf/Kconfig 
>>>>> b/drivers/platform/x86/amd/pmf/Kconfig
>>>>> index f246252bddd8..7f430de7af44 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 TEE && 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 4b8156033fa6..c59ba527ff49 100644
>>>>> --- a/drivers/platform/x86/amd/pmf/core.c
>>>>> +++ b/drivers/platform/x86/amd/pmf/core.c
>>>>> @@ -411,6 +411,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 8712299ad52b..615cd3a31986 100644
>>>>> --- a/drivers/platform/x86/amd/pmf/pmf.h
>>>>> +++ b/drivers/platform/x86/amd/pmf/pmf.h
>>>>> @@ -13,6 +13,7 @@
>>>>>   #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
>>>>> @@ -228,9 +229,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 512e0c66efdc..cf4962ef97c2 100644
>>>>> --- a/drivers/platform/x86/amd/pmf/spc.c
>>>>> +++ b/drivers/platform/x86/amd/pmf/spc.c
>>>>> @@ -44,6 +44,10 @@ void amd_pmf_dump_ta_inputs(struct amd_pmf_dev 
>>>>> *dev, struct ta_pmf_enact_table *
>>>>>       dev_dbg(dev->dev, "Max C0 Residency : %u\n", 
>>>>> in->ev_info.max_c0residency);
>>>>>       dev_dbg(dev->dev, "GFX Busy : %u\n", in->ev_info.gfx_busy);
>>>>>       dev_dbg(dev->dev, "Connected Display Count : %u\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");
>>>>>   }
>>>>> @@ -146,6 +150,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 */
>>>>> @@ -154,4 +166,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 2f5fb8623c20..956e66b78605 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"
>>>>> @@ -357,6 +358,19 @@ 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) {
>>>>> +        /* Found the amdgpu handle from the pci root after 
>>>>> walking through the pci bus */
>>>> If you insist on having this comment, make it a function comment 
>>>> instead
>>>> (with appropriate modifications into the content of it) but I 
>>>> personally
>>>> don't find it that useful so it could be just dropped as well, IMO.
>>>>
>>>>> +        dev->gfx_data.gpu_dev = 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;
>>>>> @@ -446,6 +460,15 @@ 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 */
>>>> Useless comment.
>>>>
>>>>> + 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");
>>>>> +
>>>>> +    if (!amd_pmf_gpu_init(&dev->gfx_data))
>>>>> +        dev->gfx_data.gpu_dev_en = true;
>>>>> +
>>>>>       dev->prev_data = kzalloc(sizeof(*dev->prev_data), GFP_KERNEL);
>>>>>       if (!dev->prev_data)
>>>>>           return -ENOMEM;
>>>>> @@ -461,5 +484,8 @@ 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);
>>>>> +    if (dev->gfx_data.gpu_dev_en)
>>>>> +        amd_pmf_gpu_deinit(&dev->gfx_data);
>>>>> +    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..5f79e66a41b3
>>>>> --- /dev/null
>>>>> +++ b/include/linux/amd-pmf-io.h
>>>>> @@ -0,0 +1,35 @@
>>>>> +/* 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 <acpi/video.h>
>>>>> +#include <drm/drm_connector.h>
>>>>> +#include <linux/backlight.h>
>>>>> +#include <linux/thermal.h>
>>>>> +
>>>>> +#define MAX_SUPPORTED 4
>>>>> +
>>>>> +/* amdgpu */
>>>> Document the structure properly with kerneldoc instead of an unhelpful
>>>> comment like above :-). Please also check if you add any other structs
>>>> into kernel-wide headers that you didn't document yet. Or fields into
>>>> existing structs.
>>>>
>>>>> +struct amd_gpu_pmf_data {
>>>>> +    struct pci_dev *gpu_dev;
>>>>> +    struct backlight_device *raw_bd;
>>>>> +    struct thermal_cooling_device *cooling_dev;
>>>>> +    enum drm_connector_status con_status[MAX_SUPPORTED];
>>>>> +    int display_count;
>>>>> +    int connector_type[MAX_SUPPORTED];
>>>>> +    bool gpu_dev_en;
>>>>> +};
>>>>> +
>>>>> +int amd_pmf_get_gfx_data(struct amd_gpu_pmf_data *pmf);
>>>>> +int amd_pmf_gpu_init(struct amd_gpu_pmf_data *pmf);
>>>>> +void amd_pmf_gpu_deinit(struct amd_gpu_pmf_data *pmf);
>>>>> +#endif
>>>>>
>>
>


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

* Re: [PATCH v4 13/17] platform/x86/amd/pmf: Add PMF-AMDGPU get interface
  2023-10-18 16:07           ` Christian König
@ 2023-10-18 17:05             ` Shyam Sundar S K
  2023-10-19  9:01               ` Christian König
  0 siblings, 1 reply; 35+ messages in thread
From: Shyam Sundar S K @ 2023-10-18 17:05 UTC (permalink / raw)
  To: Christian König, Mario Limonciello, Ilpo Järvinen
  Cc: Xinhui.Pan, Patil.Reddy, basavaraj.natikar, jikos, amd-gfx,
	platform-driver-x86, markgross, Hans de Goede,
	benjamin.tissoires, dri-devel, linux-input, alexander.deucher



On 10/18/2023 9:37 PM, Christian König wrote:
> Am 18.10.23 um 17:47 schrieb Mario Limonciello:
>> On 10/18/2023 08:40, Christian König wrote:
>>>
>>>
>>> Am 18.10.23 um 11:28 schrieb Shyam Sundar S K:
>>>>
>>>> On 10/18/2023 2:50 PM, Ilpo Järvinen wrote:
>>>>> On Wed, 18 Oct 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 | 138
>>>>>> ++++++++++++++++++++++++
>>>>>>   drivers/platform/x86/amd/pmf/Kconfig    |   1 +
>>>>>>   drivers/platform/x86/amd/pmf/core.c     |   1 +
>>>>>>   drivers/platform/x86/amd/pmf/pmf.h      |   3 +
>>>>>>   drivers/platform/x86/amd/pmf/spc.c      |  13 +++
>>>>>>   drivers/platform/x86/amd/pmf/tee-if.c   |  26 +++++
>>>>>>   include/linux/amd-pmf-io.h              |  35 ++++++
>>>>>>   9 files changed, 220 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 a79d53bdbe13..26ffa1b4fe57 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..ac981848df50
>>>>>> --- /dev/null
>>>>>> +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_pmf.c
>>>>>> @@ -0,0 +1,138 @@
>>>>>> +/*
>>>>>> + * 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.
>>>>> This is MIT, right? Add the required SPDX-License-Identifier line
>>>>> for it
>>>>> at the top of the file, thank you.
>>>>>
>>>> all the files in drivers/gpu/drm/amd/amdgpu/* carry the same license
>>>> text. So, have retained it to maintain uniformity.
>>>
>>> Please add the SPDX License Identifier for any file you add.

OK. I thought to keep it same like the other files. I will change this
to SPDX in the next revision.

>>>
>>> Apart from that the whole approach of attaching this directly to
>>> amdgpu looks extremely questionable to me.
>>>
>>
>> What's the long term outlook for things that are needed directly
>> from amdgpu?  Is there going to be more besides the backlight and
>> the display count/type?
> 
> Yeah, that goes into the same direction as my concern.

PMF is an APU only feature and will need inputs from multiple
subsystems (in this case its GPU) to send changing system information
to PMF TA (Trusted Application, running on ASP/PSP) as input.

Its not only about the display count/type and backlight, there are
many others things in pipe like the GPU engine running time,
utilization percentage etc, that guide the TA to make better decisions.

This series is only targeted to build the initial plubming with the
subsystems inside the kernel and later keep adding changes to get more
information from other subsystems.

that is the reason you see that, this patch proposes amd-pmf-io.h as
the interface to talk to other subsystems. For the initial path, I
have opted to get information from SFH and GPU drivers. But this is
meant to grow in future.

> 
>>
>> At least for the display count I suppose one way that it could be
>> "decoupled" from amdgpu is to use drm_for_each_connector_iter to
>> iterate all the connectors and then count the connected ones.
> 
> And what if the number of connected displays change? How is amdgpu
> supposed to signal events like that?

PMF driver polls for the information based on a configurable sampling
frequency.

you can look at amd_pmf_get_gpu_info(), that gets called from
amd_pmf_populate_ta_inputs() in spc.c in this proposed series.

Thanks,
Shyam

> 
> This whole solution doesn't looks well thought through.
> 
> Regards,
> Christian.
> 
>>
>>> Regards,
>>> Christian.
>>>
>>>>
>>>>>> + *
>>>>>> + * Author: Shyam Sundar S K <Shyam-sundar.S-k@amd.com>
>>>>>> + *
>>>>>> + */
>>>>> Remove the extra empty line at the end of the comment.
>>>>>
>>>> I just took the standard template for all the gpu files. Is that
>>>> OK to
>>>> retain the blank line?
>>>>
>>>> If not, I can remove it in the next version.
>>>>
>>>> Rest all remarks I will address.
>>>>
>>>> Thanks,
>>>> Shyam
>>>>
>>>>>> +
>>>>>> +#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;
>>>>>> +    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;
>>>>>> +    }
>>>>>> +
>>>>>> +    mutex_lock(&mode_config->mutex);
>>>>>> +    drm_connector_list_iter_begin(drm_dev, &iter);
>>>>>> +    drm_for_each_connector_iter(connector, &iter) {
>>>>>> +        if (connector->status == connector_status_connected)
>>>>>> +            pmf->display_count++;
>>>>>> +        if (connector->status != pmf->con_status[i])
>>>>>> +            pmf->con_status[i] = connector->status;
>>>>>> +        if (connector->connector_type != pmf->connector_type[i])
>>>>>> +            pmf->connector_type[i] = connector->connector_type;
>>>>>> +
>>>>>> +        i++;
>>>>>> +        if (i >= MAX_SUPPORTED)
>>>>>> +            break;
>>>>>> +    }
>>>>>> +    drm_connector_list_iter_end(&iter);
>>>>>> +    mutex_unlock(&mode_config->mutex);
>>>>>> +
>>>>>> +    return 0;
>>>>>> +}
>>>>>> +EXPORT_SYMBOL_GPL(amd_pmf_get_gfx_data);
>>>>>> +
>>>>>> +static int amd_pmf_gpu_get_cur_state(struct
>>>>>> thermal_cooling_device *cooling_dev,
>>>>>> +                     unsigned long *state)
>>>>>> +{
>>>>>> +    struct backlight_device *bd;
>>>>>> +
>>>>>> +    if (!acpi_video_backlight_use_native())
>>>>>> +        return -ENODEV;
>>>>>> +
>>>>>> +    bd = backlight_device_get_by_type(BACKLIGHT_RAW);
>>>>>> +    if (!bd)
>>>>>> +        return -ENODEV;
>>>>>> +
>>>>>> +    *state = backlight_get_brightness(bd);
>>>>>> +
>>>>>> +    return 0;
>>>>>> +}
>>>>>> +
>>>>>> +static int amd_pmf_gpu_get_max_state(struct
>>>>>> thermal_cooling_device *cooling_dev,
>>>>>> +                     unsigned long *state)
>>>>>> +{
>>>>>> +    struct backlight_device *bd;
>>>>>> +
>>>>>> +    if (!acpi_video_backlight_use_native())
>>>>>> +        return -ENODEV;
>>>>>> +
>>>>>> +    bd = backlight_device_get_by_type(BACKLIGHT_RAW);
>>>>>> +    if (!bd)
>>>>>> +        return -ENODEV;
>>>>>> +
>>>>>> +    if (backlight_is_blank(bd))
>>>>>> +        *state = 0;
>>>>>> +    else
>>>>>> +        *state = bd->props.max_brightness;
>>>>>> +
>>>>>> +    return 0;
>>>>>> +}
>>>>>> +
>>>>>> +static const struct thermal_cooling_device_ops bd_cooling_ops = {
>>>>>> +    .get_max_state = amd_pmf_gpu_get_max_state,
>>>>>> +    .get_cur_state = amd_pmf_gpu_get_cur_state,
>>>>>> +};
>>>>>> +
>>>>>> +int amd_pmf_gpu_init(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);
>>>>>> +
>>>>>> +    if (!(adev->flags & AMD_IS_APU)) {
>>>>>> +        DRM_ERROR("PMF-AMDGPU interface not supported\n");
>>>>>> +        return -ENODEV;
>>>>>> +    }
>>>>>> +
>>>>>> +    if (!acpi_video_backlight_use_native())
>>>>>> +        return -ENODEV;
>>>>>> +
>>>>>> +    pmf->raw_bd = backlight_device_get_by_type(BACKLIGHT_RAW);
>>>>>> +    if (!pmf->raw_bd)
>>>>>> +        return -ENODEV;
>>>>>> +
>>>>>> +    pmf->cooling_dev =
>>>>>> thermal_cooling_device_register("pmf_gpu_bd",
>>>>>> +                               pmf, &bd_cooling_ops);
>>>>>> +    if (IS_ERR(pmf->cooling_dev))
>>>>>> +        return -ENODEV;
>>>>>> +
>>>>>> +    return 0;
>>>>>> +}
>>>>>> +EXPORT_SYMBOL_GPL(amd_pmf_gpu_init);
>>>>>> +
>>>>>> +void amd_pmf_gpu_deinit(struct amd_gpu_pmf_data *pmf)
>>>>>> +{
>>>>>> + thermal_cooling_device_unregister(pmf->cooling_dev);
>>>>>> +}
>>>>>> +EXPORT_SYMBOL_GPL(amd_pmf_gpu_deinit);
>>>>>> diff --git a/drivers/platform/x86/amd/pmf/Kconfig
>>>>>> b/drivers/platform/x86/amd/pmf/Kconfig
>>>>>> index f246252bddd8..7f430de7af44 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 TEE && 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 4b8156033fa6..c59ba527ff49 100644
>>>>>> --- a/drivers/platform/x86/amd/pmf/core.c
>>>>>> +++ b/drivers/platform/x86/amd/pmf/core.c
>>>>>> @@ -411,6 +411,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 8712299ad52b..615cd3a31986 100644
>>>>>> --- a/drivers/platform/x86/amd/pmf/pmf.h
>>>>>> +++ b/drivers/platform/x86/amd/pmf/pmf.h
>>>>>> @@ -13,6 +13,7 @@
>>>>>>   #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
>>>>>> @@ -228,9 +229,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 512e0c66efdc..cf4962ef97c2 100644
>>>>>> --- a/drivers/platform/x86/amd/pmf/spc.c
>>>>>> +++ b/drivers/platform/x86/amd/pmf/spc.c
>>>>>> @@ -44,6 +44,10 @@ void amd_pmf_dump_ta_inputs(struct
>>>>>> amd_pmf_dev *dev, struct ta_pmf_enact_table *
>>>>>>       dev_dbg(dev->dev, "Max C0 Residency : %u\n",
>>>>>> in->ev_info.max_c0residency);
>>>>>>       dev_dbg(dev->dev, "GFX Busy : %u\n", in->ev_info.gfx_busy);
>>>>>>       dev_dbg(dev->dev, "Connected Display Count : %u\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");
>>>>>>   }
>>>>>> @@ -146,6 +150,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 */
>>>>>> @@ -154,4 +166,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 2f5fb8623c20..956e66b78605 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"
>>>>>> @@ -357,6 +358,19 @@ 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) {
>>>>>> +        /* Found the amdgpu handle from the pci root after
>>>>>> walking through the pci bus */
>>>>> If you insist on having this comment, make it a function comment
>>>>> instead
>>>>> (with appropriate modifications into the content of it) but I
>>>>> personally
>>>>> don't find it that useful so it could be just dropped as well, IMO.
>>>>>
>>>>>> +        dev->gfx_data.gpu_dev = 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;
>>>>>> @@ -446,6 +460,15 @@ 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 */
>>>>> Useless comment.
>>>>>
>>>>>> + 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");
>>>>>> +
>>>>>> +    if (!amd_pmf_gpu_init(&dev->gfx_data))
>>>>>> +        dev->gfx_data.gpu_dev_en = true;
>>>>>> +
>>>>>>       dev->prev_data = kzalloc(sizeof(*dev->prev_data),
>>>>>> GFP_KERNEL);
>>>>>>       if (!dev->prev_data)
>>>>>>           return -ENOMEM;
>>>>>> @@ -461,5 +484,8 @@ 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);
>>>>>> +    if (dev->gfx_data.gpu_dev_en)
>>>>>> +        amd_pmf_gpu_deinit(&dev->gfx_data);
>>>>>> +    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..5f79e66a41b3
>>>>>> --- /dev/null
>>>>>> +++ b/include/linux/amd-pmf-io.h
>>>>>> @@ -0,0 +1,35 @@
>>>>>> +/* 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 <acpi/video.h>
>>>>>> +#include <drm/drm_connector.h>
>>>>>> +#include <linux/backlight.h>
>>>>>> +#include <linux/thermal.h>
>>>>>> +
>>>>>> +#define MAX_SUPPORTED 4
>>>>>> +
>>>>>> +/* amdgpu */
>>>>> Document the structure properly with kerneldoc instead of an
>>>>> unhelpful
>>>>> comment like above :-). Please also check if you add any other
>>>>> structs
>>>>> into kernel-wide headers that you didn't document yet. Or fields
>>>>> into
>>>>> existing structs.
>>>>>
>>>>>> +struct amd_gpu_pmf_data {
>>>>>> +    struct pci_dev *gpu_dev;
>>>>>> +    struct backlight_device *raw_bd;
>>>>>> +    struct thermal_cooling_device *cooling_dev;
>>>>>> +    enum drm_connector_status con_status[MAX_SUPPORTED];
>>>>>> +    int display_count;
>>>>>> +    int connector_type[MAX_SUPPORTED];
>>>>>> +    bool gpu_dev_en;
>>>>>> +};
>>>>>> +
>>>>>> +int amd_pmf_get_gfx_data(struct amd_gpu_pmf_data *pmf);
>>>>>> +int amd_pmf_gpu_init(struct amd_gpu_pmf_data *pmf);
>>>>>> +void amd_pmf_gpu_deinit(struct amd_gpu_pmf_data *pmf);
>>>>>> +#endif
>>>>>>
>>>
>>
> 

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

* Re: [PATCH v4 13/17] platform/x86/amd/pmf: Add PMF-AMDGPU get interface
  2023-10-18 15:47         ` Mario Limonciello
  2023-10-18 16:07           ` Christian König
@ 2023-10-18 19:08           ` Hans de Goede
  2023-11-17  8:04             ` Shyam Sundar S K
  1 sibling, 1 reply; 35+ messages in thread
From: Hans de Goede @ 2023-10-18 19:08 UTC (permalink / raw)
  To: Mario Limonciello, Christian König, Shyam Sundar S K,
	Ilpo Järvinen
  Cc: Xinhui.Pan, Patil.Reddy, basavaraj.natikar, jikos, amd-gfx,
	platform-driver-x86, markgross, benjamin.tissoires, dri-devel,
	linux-input, alexander.deucher

Hi,

I was not following this at first, so my apologies for
jumping in in the middle of the thread:


<snip>

>>>>> +static int amd_pmf_gpu_get_cur_state(struct thermal_cooling_device *cooling_dev,
>>>>> +                     unsigned long *state)
>>>>> +{
>>>>> +    struct backlight_device *bd;
>>>>> +
>>>>> +    if (!acpi_video_backlight_use_native())
>>>>> +        return -ENODEV;
>>>>> +
>>>>> +    bd = backlight_device_get_by_type(BACKLIGHT_RAW);
>>>>> +    if (!bd)
>>>>> +        return -ENODEV;
>>>>> +
>>>>> +    *state = backlight_get_brightness(bd);
>>>>> +
>>>>> +    return 0;
>>>>> +}
>>>>> +
>>>>> +static int amd_pmf_gpu_get_max_state(struct thermal_cooling_device *cooling_dev,
>>>>> +                     unsigned long *state)
>>>>> +{
>>>>> +    struct backlight_device *bd;
>>>>> +
>>>>> +    if (!acpi_video_backlight_use_native())
>>>>> +        return -ENODEV;
>>>>> +
>>>>> +    bd = backlight_device_get_by_type(BACKLIGHT_RAW);
>>>>> +    if (!bd)
>>>>> +        return -ENODEV;
>>>>> +
>>>>> +    if (backlight_is_blank(bd))
>>>>> +        *state = 0;
>>>>> +    else
>>>>> +        *state = bd->props.max_brightness;
>>>>> +
>>>>> +    return 0;
>>>>> +}
>>>>> +
>>>>> +static const struct thermal_cooling_device_ops bd_cooling_ops = {
>>>>> +    .get_max_state = amd_pmf_gpu_get_max_state,
>>>>> +    .get_cur_state = amd_pmf_gpu_get_cur_state,
>>>>> +};

So first of all, good to see that this is using the
thermal_cooling_device APIs now, that is great thank you.

But the whole idea behind using the thermal_cooling_device APIs
is that amdgpu exports the cooling_device itself, rather then have
the AMD PMF code export it. Now the AMD PMF code is still poking
at the backlight_device itself, while the idea was to delegate
this to the GPU driver.

Actually seeing all the acpi_video_backlight_use_native()
checks here, I wonder why only have this work with native backlight
control. One step better would be to add thermal_cooling_device
support to the backlight core in:
drivers/video/backlight/backlight.c

Then it will work with any backlight control provider!



Last but not least this code MUST not call
acpi_video_backlight_use_native()

No code other then native GPU drivers must ever call
acpi_video_backlight_use_native(). This special function
not only checks if the native backlight control is the
one which the detection code in drivers/acpi/video_detect.c
has selected, it also signals to video_detect.c that
native GPU backlight control is available.

So by calling this in the AMD PMF code you are now
telling video_detect.c that native GPU backlight control
is available on all systems where AMD PMF runs.

As I already said I really believe the whole cooling
device should be registered somewhere else. But if you
do end up sticking with this then you MUST replace
the acpi_video_backlight_use_native() calls with:

	if (acpi_video_get_backlight_type() == acpi_backlight_native) {...}

Regards,

Hans




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

* Re: [PATCH v4 13/17] platform/x86/amd/pmf: Add PMF-AMDGPU get interface
  2023-10-18 17:05             ` Shyam Sundar S K
@ 2023-10-19  9:01               ` Christian König
  2023-11-17  8:00                 ` Shyam Sundar S K
  0 siblings, 1 reply; 35+ messages in thread
From: Christian König @ 2023-10-19  9:01 UTC (permalink / raw)
  To: Shyam Sundar S K, Mario Limonciello, Ilpo Järvinen,
	Daniel Vetter, Dave Airlie
  Cc: Xinhui.Pan, Patil.Reddy, basavaraj.natikar, jikos, amd-gfx,
	platform-driver-x86, markgross, Hans de Goede,
	benjamin.tissoires, dri-devel, linux-input, alexander.deucher

Am 18.10.23 um 19:05 schrieb Shyam Sundar S K:
>
> On 10/18/2023 9:37 PM, Christian König wrote:
>> Am 18.10.23 um 17:47 schrieb Mario Limonciello:
>>> On 10/18/2023 08:40, Christian König wrote:
>>>>
>>>> Am 18.10.23 um 11:28 schrieb Shyam Sundar S K:
>>>>> On 10/18/2023 2:50 PM, Ilpo Järvinen wrote:
>>>>>> On Wed, 18 Oct 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 | 138
>>>>>>> ++++++++++++++++++++++++
>>>>>>>    drivers/platform/x86/amd/pmf/Kconfig    |   1 +
>>>>>>>    drivers/platform/x86/amd/pmf/core.c     |   1 +
>>>>>>>    drivers/platform/x86/amd/pmf/pmf.h      |   3 +
>>>>>>>    drivers/platform/x86/amd/pmf/spc.c      |  13 +++
>>>>>>>    drivers/platform/x86/amd/pmf/tee-if.c   |  26 +++++
>>>>>>>    include/linux/amd-pmf-io.h              |  35 ++++++
>>>>>>>    9 files changed, 220 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 a79d53bdbe13..26ffa1b4fe57 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..ac981848df50
>>>>>>> --- /dev/null
>>>>>>> +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_pmf.c
>>>>>>> @@ -0,0 +1,138 @@
>>>>>>> +/*
>>>>>>> + * 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.
>>>>>> This is MIT, right? Add the required SPDX-License-Identifier line
>>>>>> for it
>>>>>> at the top of the file, thank you.
>>>>>>
>>>>> all the files in drivers/gpu/drm/amd/amdgpu/* carry the same license
>>>>> text. So, have retained it to maintain uniformity.
>>>> Please add the SPDX License Identifier for any file you add.
> OK. I thought to keep it same like the other files. I will change this
> to SPDX in the next revision.
>
>>>> Apart from that the whole approach of attaching this directly to
>>>> amdgpu looks extremely questionable to me.
>>>>
>>> What's the long term outlook for things that are needed directly
>>> from amdgpu?  Is there going to be more besides the backlight and
>>> the display count/type?
>> Yeah, that goes into the same direction as my concern.
> PMF is an APU only feature and will need inputs from multiple
> subsystems (in this case its GPU) to send changing system information
> to PMF TA (Trusted Application, running on ASP/PSP) as input.
>
> Its not only about the display count/type and backlight, there are
> many others things in pipe like the GPU engine running time,
> utilization percentage etc, that guide the TA to make better decisions.
>
> This series is only targeted to build the initial plubming with the
> subsystems inside the kernel and later keep adding changes to get more
> information from other subsystems.

Yeah, and that's what I strongly disagree on. Don't come up with such an 
approach without consulting with upstream maintainers first.

What you propose here is a system wide framework for improving power 
management, that's fine. The problem is that we already have something 
very similar in the thermal framework.

See for example the Intel solution here 
https://docs.kernel.org/driver-api/thermal/intel_dptf.html

 From the general design the job of the amdgpu driver is to drive the 
display hardware. So this should in general be completely decoupled from 
this driver. As Mario suggested as well you can iterate over the 
connected displays independently. Same thing for the backlight.

When it comes to hardware state like GPU engine utilization then we 
don't have that inside amdgpu either.

Regards,
Christian.

>
> that is the reason you see that, this patch proposes amd-pmf-io.h as
> the interface to talk to other subsystems. For the initial path, I
> have opted to get information from SFH and GPU drivers. But this is
> meant to grow in future.
>
>>> At least for the display count I suppose one way that it could be
>>> "decoupled" from amdgpu is to use drm_for_each_connector_iter to
>>> iterate all the connectors and then count the connected ones.
>> And what if the number of connected displays change? How is amdgpu
>> supposed to signal events like that?
> PMF driver polls for the information based on a configurable sampling
> frequency.
>
> you can look at amd_pmf_get_gpu_info(), that gets called from
> amd_pmf_populate_ta_inputs() in spc.c in this proposed series.
>
> Thanks,
> Shyam
>
>> This whole solution doesn't looks well thought through.
>>
>> Regards,
>> Christian.
>>
>>>> Regards,
>>>> Christian.
>>>>
>>>>>>> + *
>>>>>>> + * Author: Shyam Sundar S K <Shyam-sundar.S-k@amd.com>
>>>>>>> + *
>>>>>>> + */
>>>>>> Remove the extra empty line at the end of the comment.
>>>>>>
>>>>> I just took the standard template for all the gpu files. Is that
>>>>> OK to
>>>>> retain the blank line?
>>>>>
>>>>> If not, I can remove it in the next version.
>>>>>
>>>>> Rest all remarks I will address.
>>>>>
>>>>> Thanks,
>>>>> Shyam
>>>>>
>>>>>>> +
>>>>>>> +#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;
>>>>>>> +    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;
>>>>>>> +    }
>>>>>>> +
>>>>>>> +    mutex_lock(&mode_config->mutex);
>>>>>>> +    drm_connector_list_iter_begin(drm_dev, &iter);
>>>>>>> +    drm_for_each_connector_iter(connector, &iter) {
>>>>>>> +        if (connector->status == connector_status_connected)
>>>>>>> +            pmf->display_count++;
>>>>>>> +        if (connector->status != pmf->con_status[i])
>>>>>>> +            pmf->con_status[i] = connector->status;
>>>>>>> +        if (connector->connector_type != pmf->connector_type[i])
>>>>>>> +            pmf->connector_type[i] = connector->connector_type;
>>>>>>> +
>>>>>>> +        i++;
>>>>>>> +        if (i >= MAX_SUPPORTED)
>>>>>>> +            break;
>>>>>>> +    }
>>>>>>> +    drm_connector_list_iter_end(&iter);
>>>>>>> +    mutex_unlock(&mode_config->mutex);
>>>>>>> +
>>>>>>> +    return 0;
>>>>>>> +}
>>>>>>> +EXPORT_SYMBOL_GPL(amd_pmf_get_gfx_data);
>>>>>>> +
>>>>>>> +static int amd_pmf_gpu_get_cur_state(struct
>>>>>>> thermal_cooling_device *cooling_dev,
>>>>>>> +                     unsigned long *state)
>>>>>>> +{
>>>>>>> +    struct backlight_device *bd;
>>>>>>> +
>>>>>>> +    if (!acpi_video_backlight_use_native())
>>>>>>> +        return -ENODEV;
>>>>>>> +
>>>>>>> +    bd = backlight_device_get_by_type(BACKLIGHT_RAW);
>>>>>>> +    if (!bd)
>>>>>>> +        return -ENODEV;
>>>>>>> +
>>>>>>> +    *state = backlight_get_brightness(bd);
>>>>>>> +
>>>>>>> +    return 0;
>>>>>>> +}
>>>>>>> +
>>>>>>> +static int amd_pmf_gpu_get_max_state(struct
>>>>>>> thermal_cooling_device *cooling_dev,
>>>>>>> +                     unsigned long *state)
>>>>>>> +{
>>>>>>> +    struct backlight_device *bd;
>>>>>>> +
>>>>>>> +    if (!acpi_video_backlight_use_native())
>>>>>>> +        return -ENODEV;
>>>>>>> +
>>>>>>> +    bd = backlight_device_get_by_type(BACKLIGHT_RAW);
>>>>>>> +    if (!bd)
>>>>>>> +        return -ENODEV;
>>>>>>> +
>>>>>>> +    if (backlight_is_blank(bd))
>>>>>>> +        *state = 0;
>>>>>>> +    else
>>>>>>> +        *state = bd->props.max_brightness;
>>>>>>> +
>>>>>>> +    return 0;
>>>>>>> +}
>>>>>>> +
>>>>>>> +static const struct thermal_cooling_device_ops bd_cooling_ops = {
>>>>>>> +    .get_max_state = amd_pmf_gpu_get_max_state,
>>>>>>> +    .get_cur_state = amd_pmf_gpu_get_cur_state,
>>>>>>> +};
>>>>>>> +
>>>>>>> +int amd_pmf_gpu_init(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);
>>>>>>> +
>>>>>>> +    if (!(adev->flags & AMD_IS_APU)) {
>>>>>>> +        DRM_ERROR("PMF-AMDGPU interface not supported\n");
>>>>>>> +        return -ENODEV;
>>>>>>> +    }
>>>>>>> +
>>>>>>> +    if (!acpi_video_backlight_use_native())
>>>>>>> +        return -ENODEV;
>>>>>>> +
>>>>>>> +    pmf->raw_bd = backlight_device_get_by_type(BACKLIGHT_RAW);
>>>>>>> +    if (!pmf->raw_bd)
>>>>>>> +        return -ENODEV;
>>>>>>> +
>>>>>>> +    pmf->cooling_dev =
>>>>>>> thermal_cooling_device_register("pmf_gpu_bd",
>>>>>>> +                               pmf, &bd_cooling_ops);
>>>>>>> +    if (IS_ERR(pmf->cooling_dev))
>>>>>>> +        return -ENODEV;
>>>>>>> +
>>>>>>> +    return 0;
>>>>>>> +}
>>>>>>> +EXPORT_SYMBOL_GPL(amd_pmf_gpu_init);
>>>>>>> +
>>>>>>> +void amd_pmf_gpu_deinit(struct amd_gpu_pmf_data *pmf)
>>>>>>> +{
>>>>>>> + thermal_cooling_device_unregister(pmf->cooling_dev);
>>>>>>> +}
>>>>>>> +EXPORT_SYMBOL_GPL(amd_pmf_gpu_deinit);
>>>>>>> diff --git a/drivers/platform/x86/amd/pmf/Kconfig
>>>>>>> b/drivers/platform/x86/amd/pmf/Kconfig
>>>>>>> index f246252bddd8..7f430de7af44 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 TEE && 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 4b8156033fa6..c59ba527ff49 100644
>>>>>>> --- a/drivers/platform/x86/amd/pmf/core.c
>>>>>>> +++ b/drivers/platform/x86/amd/pmf/core.c
>>>>>>> @@ -411,6 +411,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 8712299ad52b..615cd3a31986 100644
>>>>>>> --- a/drivers/platform/x86/amd/pmf/pmf.h
>>>>>>> +++ b/drivers/platform/x86/amd/pmf/pmf.h
>>>>>>> @@ -13,6 +13,7 @@
>>>>>>>    #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
>>>>>>> @@ -228,9 +229,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 512e0c66efdc..cf4962ef97c2 100644
>>>>>>> --- a/drivers/platform/x86/amd/pmf/spc.c
>>>>>>> +++ b/drivers/platform/x86/amd/pmf/spc.c
>>>>>>> @@ -44,6 +44,10 @@ void amd_pmf_dump_ta_inputs(struct
>>>>>>> amd_pmf_dev *dev, struct ta_pmf_enact_table *
>>>>>>>        dev_dbg(dev->dev, "Max C0 Residency : %u\n",
>>>>>>> in->ev_info.max_c0residency);
>>>>>>>        dev_dbg(dev->dev, "GFX Busy : %u\n", in->ev_info.gfx_busy);
>>>>>>>        dev_dbg(dev->dev, "Connected Display Count : %u\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");
>>>>>>>    }
>>>>>>> @@ -146,6 +150,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 */
>>>>>>> @@ -154,4 +166,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 2f5fb8623c20..956e66b78605 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"
>>>>>>> @@ -357,6 +358,19 @@ 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) {
>>>>>>> +        /* Found the amdgpu handle from the pci root after
>>>>>>> walking through the pci bus */
>>>>>> If you insist on having this comment, make it a function comment
>>>>>> instead
>>>>>> (with appropriate modifications into the content of it) but I
>>>>>> personally
>>>>>> don't find it that useful so it could be just dropped as well, IMO.
>>>>>>
>>>>>>> +        dev->gfx_data.gpu_dev = 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;
>>>>>>> @@ -446,6 +460,15 @@ 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 */
>>>>>> Useless comment.
>>>>>>
>>>>>>> + 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");
>>>>>>> +
>>>>>>> +    if (!amd_pmf_gpu_init(&dev->gfx_data))
>>>>>>> +        dev->gfx_data.gpu_dev_en = true;
>>>>>>> +
>>>>>>>        dev->prev_data = kzalloc(sizeof(*dev->prev_data),
>>>>>>> GFP_KERNEL);
>>>>>>>        if (!dev->prev_data)
>>>>>>>            return -ENOMEM;
>>>>>>> @@ -461,5 +484,8 @@ 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);
>>>>>>> +    if (dev->gfx_data.gpu_dev_en)
>>>>>>> +        amd_pmf_gpu_deinit(&dev->gfx_data);
>>>>>>> +    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..5f79e66a41b3
>>>>>>> --- /dev/null
>>>>>>> +++ b/include/linux/amd-pmf-io.h
>>>>>>> @@ -0,0 +1,35 @@
>>>>>>> +/* 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 <acpi/video.h>
>>>>>>> +#include <drm/drm_connector.h>
>>>>>>> +#include <linux/backlight.h>
>>>>>>> +#include <linux/thermal.h>
>>>>>>> +
>>>>>>> +#define MAX_SUPPORTED 4
>>>>>>> +
>>>>>>> +/* amdgpu */
>>>>>> Document the structure properly with kerneldoc instead of an
>>>>>> unhelpful
>>>>>> comment like above :-). Please also check if you add any other
>>>>>> structs
>>>>>> into kernel-wide headers that you didn't document yet. Or fields
>>>>>> into
>>>>>> existing structs.
>>>>>>
>>>>>>> +struct amd_gpu_pmf_data {
>>>>>>> +    struct pci_dev *gpu_dev;
>>>>>>> +    struct backlight_device *raw_bd;
>>>>>>> +    struct thermal_cooling_device *cooling_dev;
>>>>>>> +    enum drm_connector_status con_status[MAX_SUPPORTED];
>>>>>>> +    int display_count;
>>>>>>> +    int connector_type[MAX_SUPPORTED];
>>>>>>> +    bool gpu_dev_en;
>>>>>>> +};
>>>>>>> +
>>>>>>> +int amd_pmf_get_gfx_data(struct amd_gpu_pmf_data *pmf);
>>>>>>> +int amd_pmf_gpu_init(struct amd_gpu_pmf_data *pmf);
>>>>>>> +void amd_pmf_gpu_deinit(struct amd_gpu_pmf_data *pmf);
>>>>>>> +#endif
>>>>>>>


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

* Re: [PATCH v4 10/17] platform/x86/amd/pmf: Add facility to dump TA inputs
  2023-10-18  9:00   ` Ilpo Järvinen
@ 2023-11-17  7:46     ` Shyam Sundar S K
  0 siblings, 0 replies; 35+ messages in thread
From: Shyam Sundar S K @ 2023-11-17  7:46 UTC (permalink / raw)
  To: Ilpo Järvinen
  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

Hi Ilpo,

Apologies for the long delay.

On 10/18/2023 2:30 PM, Ilpo Järvinen wrote:
> On Wed, 18 Oct 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.
>>
>> Also, make source_as_str() as non-static function as this helper is
>> required outside of sps.c file.
>>
>> 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/tee-if.c |  1 +
>>  3 files changed, 41 insertions(+)
>>
>> diff --git a/drivers/platform/x86/amd/pmf/pmf.h b/drivers/platform/x86/amd/pmf/pmf.h
>> index 216a9f795436..593930519039 100644
>> --- a/drivers/platform/x86/amd/pmf/pmf.h
>> +++ b/drivers/platform/x86/amd/pmf/pmf.h
>> @@ -602,6 +602,7 @@ bool is_pprof_balanced(struct amd_pmf_dev *pmf);
>>  int amd_pmf_power_slider_update_event(struct amd_pmf_dev *dev);
>>  const char *amd_pmf_source_as_str(unsigned int state);
>>  
>> +const char *amd_pmf_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);
>> @@ -632,4 +633,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 bd5061fdfdbe..512e0c66efdc 100644
>> --- a/drivers/platform/x86/amd/pmf/spc.c
>> +++ b/drivers/platform/x86/amd/pmf/spc.c
>> @@ -14,6 +14,43 @@
>>  #include <linux/units.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", amd_pmf_source_as_str(in->ev_info.power_source));
>> +	dev_dbg(dev->dev, "Battery Percentage : %u\n", in->ev_info.bat_percentage);
>> +	dev_dbg(dev->dev, "Designed Battery Capacity : %u\n", in->ev_info.bat_design);
>> +	dev_dbg(dev->dev, "Fully Charged Capacity : %u\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 : %u\n", in->ev_info.socket_power);
>> +	dev_dbg(dev->dev, "Skin Temperature : %u\n", in->ev_info.skin_temperature);
>> +	dev_dbg(dev->dev, "Avg C0 Residency : %u\n", in->ev_info.avg_c0residency);
>> +	dev_dbg(dev->dev, "Max C0 Residency : %u\n", in->ev_info.max_c0residency);
>> +	dev_dbg(dev->dev, "GFX Busy : %u\n", in->ev_info.gfx_busy);
>> +	dev_dbg(dev->dev, "Connected Display Count : %u\n", in->ev_info.monitor_count);
>> +	dev_dbg(dev->dev, "LID State : %s\n", in->ev_info.lid_state ? "Close" : "Open");
> 
> "open" / "closed" is generic enough that I think it would warrant adding
> include/linux/string_choices.h helper for it (it should be lowercase 
> there but that difference probably is not an issue for these debug 
> prints).
> 
> I'd also remove that extra space before :.
> 

Seems like string_choices.h does not have helper for open/close. So
did not include this change in the next revision. But I have addressed
all your other remarks in v4.

Thanks,
Shyam

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

* Re: [PATCH v4 13/17] platform/x86/amd/pmf: Add PMF-AMDGPU get interface
  2023-10-19  9:01               ` Christian König
@ 2023-11-17  8:00                 ` Shyam Sundar S K
  0 siblings, 0 replies; 35+ messages in thread
From: Shyam Sundar S K @ 2023-11-17  8:00 UTC (permalink / raw)
  To: Christian König, Mario Limonciello, Ilpo Järvinen,
	Daniel Vetter, Dave Airlie
  Cc: Xinhui.Pan, basavaraj.natikar, jikos, amd-gfx,
	platform-driver-x86, markgross, Hans de Goede,
	benjamin.tissoires, dri-devel, Patil.Reddy, linux-input,
	alexander.deucher



On 10/19/2023 2:31 PM, Christian König wrote:
> Am 18.10.23 um 19:05 schrieb Shyam Sundar S K:
>>
>> On 10/18/2023 9:37 PM, Christian König wrote:
>>> Am 18.10.23 um 17:47 schrieb Mario Limonciello:
>>>> On 10/18/2023 08:40, Christian König wrote:
>>>>>
>>>>> Am 18.10.23 um 11:28 schrieb Shyam Sundar S K:
>>>>>> On 10/18/2023 2:50 PM, Ilpo Järvinen wrote:
>>>>>>> On Wed, 18 Oct 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 | 138
>>>>>>>> ++++++++++++++++++++++++
>>>>>>>>    drivers/platform/x86/amd/pmf/Kconfig    |   1 +
>>>>>>>>    drivers/platform/x86/amd/pmf/core.c     |   1 +
>>>>>>>>    drivers/platform/x86/amd/pmf/pmf.h      |   3 +
>>>>>>>>    drivers/platform/x86/amd/pmf/spc.c      |  13 +++
>>>>>>>>    drivers/platform/x86/amd/pmf/tee-if.c   |  26 +++++
>>>>>>>>    include/linux/amd-pmf-io.h              |  35 ++++++
>>>>>>>>    9 files changed, 220 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 a79d53bdbe13..26ffa1b4fe57 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..ac981848df50
>>>>>>>> --- /dev/null
>>>>>>>> +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_pmf.c
>>>>>>>> @@ -0,0 +1,138 @@
>>>>>>>> +/*
>>>>>>>> + * 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.
>>>>>>> This is MIT, right? Add the required SPDX-License-Identifier line
>>>>>>> for it
>>>>>>> at the top of the file, thank you.
>>>>>>>
>>>>>> all the files in drivers/gpu/drm/amd/amdgpu/* carry the same
>>>>>> license
>>>>>> text. So, have retained it to maintain uniformity.
>>>>> Please add the SPDX License Identifier for any file you add.
>> OK. I thought to keep it same like the other files. I will change this
>> to SPDX in the next revision.
>>
>>>>> Apart from that the whole approach of attaching this directly to
>>>>> amdgpu looks extremely questionable to me.
>>>>>
>>>> What's the long term outlook for things that are needed directly
>>>> from amdgpu?  Is there going to be more besides the backlight and
>>>> the display count/type?
>>> Yeah, that goes into the same direction as my concern.
>> PMF is an APU only feature and will need inputs from multiple
>> subsystems (in this case its GPU) to send changing system information
>> to PMF TA (Trusted Application, running on ASP/PSP) as input.
>>
>> Its not only about the display count/type and backlight, there are
>> many others things in pipe like the GPU engine running time,
>> utilization percentage etc, that guide the TA to make better decisions.
>>
>> This series is only targeted to build the initial plubming with the
>> subsystems inside the kernel and later keep adding changes to get more
>> information from other subsystems.
> 
> Yeah, and that's what I strongly disagree on. Don't come up with such
> an approach without consulting with upstream maintainers first.

PMF is there since sometime and this is an additional feature, so you
should presume that its being consulted.

> 
> What you propose here is a system wide framework for improving power
> management, that's fine. The problem is that we already have something
> very similar in the thermal framework.
> 
> See for example the Intel solution here
> https://docs.kernel.org/driver-api/thermal/intel_dptf.html
> 
> From the general design the job of the amdgpu driver is to drive the
> display hardware. So this should in general be completely decoupled
> from this driver. As Mario suggested as well you can iterate over the
> connected displays independently. Same thing for the backlight.

Well. Same should be case even with PMF driver as well. It should
provide overall interfaces for OEMs and ecosystem partners.

So, PMF should not have the DRM related changes IMHO and should have
an interface defined to talk to AMDGPU.

> 
> When it comes to hardware state like GPU engine utilization then we
> don't have that inside amdgpu either.

I spent sometime to get the stats for GPU utilization and other
information required to be passed to PMF TA, but the results were not
really favourable (maybe these could be issues in the PMF-TA as well).

So for now, I think it makes sense to have the DRM related code
changes within the PMF driver. But once we have other inputs from the
GPU/DRM subsystem ready, IMO GPU driver should provide these inputs
back to PMF driver.

Let me know if you have a different opinion on this.

Thanks,
Shyam

> 
> Regards,
> Christian.
> 
>>
>> that is the reason you see that, this patch proposes amd-pmf-io.h as
>> the interface to talk to other subsystems. For the initial path, I
>> have opted to get information from SFH and GPU drivers. But this is
>> meant to grow in future.
>>
>>>> At least for the display count I suppose one way that it could be
>>>> "decoupled" from amdgpu is to use drm_for_each_connector_iter to
>>>> iterate all the connectors and then count the connected ones.
>>> And what if the number of connected displays change? How is amdgpu
>>> supposed to signal events like that?
>> PMF driver polls for the information based on a configurable sampling
>> frequency.
>>
>> you can look at amd_pmf_get_gpu_info(), that gets called from
>> amd_pmf_populate_ta_inputs() in spc.c in this proposed series.
>>
>> Thanks,
>> Shyam
>>
>>> This whole solution doesn't looks well thought through.
>>>
>>> Regards,
>>> Christian.
>>>
>>>>> Regards,
>>>>> Christian.
>>>>>
>>>>>>>> + *
>>>>>>>> + * Author: Shyam Sundar S K <Shyam-sundar.S-k@amd.com>
>>>>>>>> + *
>>>>>>>> + */
>>>>>>> Remove the extra empty line at the end of the comment.
>>>>>>>
>>>>>> I just took the standard template for all the gpu files. Is that
>>>>>> OK to
>>>>>> retain the blank line?
>>>>>>
>>>>>> If not, I can remove it in the next version.
>>>>>>
>>>>>> Rest all remarks I will address.
>>>>>>
>>>>>> Thanks,
>>>>>> Shyam
>>>>>>
>>>>>>>> +
>>>>>>>> +#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;
>>>>>>>> +    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;
>>>>>>>> +    }
>>>>>>>> +
>>>>>>>> +    mutex_lock(&mode_config->mutex);
>>>>>>>> +    drm_connector_list_iter_begin(drm_dev, &iter);
>>>>>>>> +    drm_for_each_connector_iter(connector, &iter) {
>>>>>>>> +        if (connector->status == connector_status_connected)
>>>>>>>> +            pmf->display_count++;
>>>>>>>> +        if (connector->status != pmf->con_status[i])
>>>>>>>> +            pmf->con_status[i] = connector->status;
>>>>>>>> +        if (connector->connector_type != pmf->connector_type[i])
>>>>>>>> +            pmf->connector_type[i] = connector->connector_type;
>>>>>>>> +
>>>>>>>> +        i++;
>>>>>>>> +        if (i >= MAX_SUPPORTED)
>>>>>>>> +            break;
>>>>>>>> +    }
>>>>>>>> +    drm_connector_list_iter_end(&iter);
>>>>>>>> +    mutex_unlock(&mode_config->mutex);
>>>>>>>> +
>>>>>>>> +    return 0;
>>>>>>>> +}
>>>>>>>> +EXPORT_SYMBOL_GPL(amd_pmf_get_gfx_data);
>>>>>>>> +
>>>>>>>> +static int amd_pmf_gpu_get_cur_state(struct
>>>>>>>> thermal_cooling_device *cooling_dev,
>>>>>>>> +                     unsigned long *state)
>>>>>>>> +{
>>>>>>>> +    struct backlight_device *bd;
>>>>>>>> +
>>>>>>>> +    if (!acpi_video_backlight_use_native())
>>>>>>>> +        return -ENODEV;
>>>>>>>> +
>>>>>>>> +    bd = backlight_device_get_by_type(BACKLIGHT_RAW);
>>>>>>>> +    if (!bd)
>>>>>>>> +        return -ENODEV;
>>>>>>>> +
>>>>>>>> +    *state = backlight_get_brightness(bd);
>>>>>>>> +
>>>>>>>> +    return 0;
>>>>>>>> +}
>>>>>>>> +
>>>>>>>> +static int amd_pmf_gpu_get_max_state(struct
>>>>>>>> thermal_cooling_device *cooling_dev,
>>>>>>>> +                     unsigned long *state)
>>>>>>>> +{
>>>>>>>> +    struct backlight_device *bd;
>>>>>>>> +
>>>>>>>> +    if (!acpi_video_backlight_use_native())
>>>>>>>> +        return -ENODEV;
>>>>>>>> +
>>>>>>>> +    bd = backlight_device_get_by_type(BACKLIGHT_RAW);
>>>>>>>> +    if (!bd)
>>>>>>>> +        return -ENODEV;
>>>>>>>> +
>>>>>>>> +    if (backlight_is_blank(bd))
>>>>>>>> +        *state = 0;
>>>>>>>> +    else
>>>>>>>> +        *state = bd->props.max_brightness;
>>>>>>>> +
>>>>>>>> +    return 0;
>>>>>>>> +}
>>>>>>>> +
>>>>>>>> +static const struct thermal_cooling_device_ops bd_cooling_ops
>>>>>>>> = {
>>>>>>>> +    .get_max_state = amd_pmf_gpu_get_max_state,
>>>>>>>> +    .get_cur_state = amd_pmf_gpu_get_cur_state,
>>>>>>>> +};
>>>>>>>> +
>>>>>>>> +int amd_pmf_gpu_init(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);
>>>>>>>> +
>>>>>>>> +    if (!(adev->flags & AMD_IS_APU)) {
>>>>>>>> +        DRM_ERROR("PMF-AMDGPU interface not supported\n");
>>>>>>>> +        return -ENODEV;
>>>>>>>> +    }
>>>>>>>> +
>>>>>>>> +    if (!acpi_video_backlight_use_native())
>>>>>>>> +        return -ENODEV;
>>>>>>>> +
>>>>>>>> +    pmf->raw_bd = backlight_device_get_by_type(BACKLIGHT_RAW);
>>>>>>>> +    if (!pmf->raw_bd)
>>>>>>>> +        return -ENODEV;
>>>>>>>> +
>>>>>>>> +    pmf->cooling_dev =
>>>>>>>> thermal_cooling_device_register("pmf_gpu_bd",
>>>>>>>> +                               pmf, &bd_cooling_ops);
>>>>>>>> +    if (IS_ERR(pmf->cooling_dev))
>>>>>>>> +        return -ENODEV;
>>>>>>>> +
>>>>>>>> +    return 0;
>>>>>>>> +}
>>>>>>>> +EXPORT_SYMBOL_GPL(amd_pmf_gpu_init);
>>>>>>>> +
>>>>>>>> +void amd_pmf_gpu_deinit(struct amd_gpu_pmf_data *pmf)
>>>>>>>> +{
>>>>>>>> + thermal_cooling_device_unregister(pmf->cooling_dev);
>>>>>>>> +}
>>>>>>>> +EXPORT_SYMBOL_GPL(amd_pmf_gpu_deinit);
>>>>>>>> diff --git a/drivers/platform/x86/amd/pmf/Kconfig
>>>>>>>> b/drivers/platform/x86/amd/pmf/Kconfig
>>>>>>>> index f246252bddd8..7f430de7af44 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 TEE && 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 4b8156033fa6..c59ba527ff49 100644
>>>>>>>> --- a/drivers/platform/x86/amd/pmf/core.c
>>>>>>>> +++ b/drivers/platform/x86/amd/pmf/core.c
>>>>>>>> @@ -411,6 +411,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 8712299ad52b..615cd3a31986 100644
>>>>>>>> --- a/drivers/platform/x86/amd/pmf/pmf.h
>>>>>>>> +++ b/drivers/platform/x86/amd/pmf/pmf.h
>>>>>>>> @@ -13,6 +13,7 @@
>>>>>>>>    #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
>>>>>>>> @@ -228,9 +229,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 512e0c66efdc..cf4962ef97c2 100644
>>>>>>>> --- a/drivers/platform/x86/amd/pmf/spc.c
>>>>>>>> +++ b/drivers/platform/x86/amd/pmf/spc.c
>>>>>>>> @@ -44,6 +44,10 @@ void amd_pmf_dump_ta_inputs(struct
>>>>>>>> amd_pmf_dev *dev, struct ta_pmf_enact_table *
>>>>>>>>        dev_dbg(dev->dev, "Max C0 Residency : %u\n",
>>>>>>>> in->ev_info.max_c0residency);
>>>>>>>>        dev_dbg(dev->dev, "GFX Busy : %u\n",
>>>>>>>> in->ev_info.gfx_busy);
>>>>>>>>        dev_dbg(dev->dev, "Connected Display Count : %u\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");
>>>>>>>>    }
>>>>>>>> @@ -146,6 +150,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 */
>>>>>>>> @@ -154,4 +166,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 2f5fb8623c20..956e66b78605 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"
>>>>>>>> @@ -357,6 +358,19 @@ 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) {
>>>>>>>> +        /* Found the amdgpu handle from the pci root after
>>>>>>>> walking through the pci bus */
>>>>>>> If you insist on having this comment, make it a function comment
>>>>>>> instead
>>>>>>> (with appropriate modifications into the content of it) but I
>>>>>>> personally
>>>>>>> don't find it that useful so it could be just dropped as well,
>>>>>>> IMO.
>>>>>>>
>>>>>>>> +        dev->gfx_data.gpu_dev = 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;
>>>>>>>> @@ -446,6 +460,15 @@ 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 */
>>>>>>> Useless comment.
>>>>>>>
>>>>>>>> + 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");
>>>>>>>> +
>>>>>>>> +    if (!amd_pmf_gpu_init(&dev->gfx_data))
>>>>>>>> +        dev->gfx_data.gpu_dev_en = true;
>>>>>>>> +
>>>>>>>>        dev->prev_data = kzalloc(sizeof(*dev->prev_data),
>>>>>>>> GFP_KERNEL);
>>>>>>>>        if (!dev->prev_data)
>>>>>>>>            return -ENOMEM;
>>>>>>>> @@ -461,5 +484,8 @@ 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);
>>>>>>>> +    if (dev->gfx_data.gpu_dev_en)
>>>>>>>> +        amd_pmf_gpu_deinit(&dev->gfx_data);
>>>>>>>> +    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..5f79e66a41b3
>>>>>>>> --- /dev/null
>>>>>>>> +++ b/include/linux/amd-pmf-io.h
>>>>>>>> @@ -0,0 +1,35 @@
>>>>>>>> +/* 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 <acpi/video.h>
>>>>>>>> +#include <drm/drm_connector.h>
>>>>>>>> +#include <linux/backlight.h>
>>>>>>>> +#include <linux/thermal.h>
>>>>>>>> +
>>>>>>>> +#define MAX_SUPPORTED 4
>>>>>>>> +
>>>>>>>> +/* amdgpu */
>>>>>>> Document the structure properly with kerneldoc instead of an
>>>>>>> unhelpful
>>>>>>> comment like above :-). Please also check if you add any other
>>>>>>> structs
>>>>>>> into kernel-wide headers that you didn't document yet. Or fields
>>>>>>> into
>>>>>>> existing structs.
>>>>>>>
>>>>>>>> +struct amd_gpu_pmf_data {
>>>>>>>> +    struct pci_dev *gpu_dev;
>>>>>>>> +    struct backlight_device *raw_bd;
>>>>>>>> +    struct thermal_cooling_device *cooling_dev;
>>>>>>>> +    enum drm_connector_status con_status[MAX_SUPPORTED];
>>>>>>>> +    int display_count;
>>>>>>>> +    int connector_type[MAX_SUPPORTED];
>>>>>>>> +    bool gpu_dev_en;
>>>>>>>> +};
>>>>>>>> +
>>>>>>>> +int amd_pmf_get_gfx_data(struct amd_gpu_pmf_data *pmf);
>>>>>>>> +int amd_pmf_gpu_init(struct amd_gpu_pmf_data *pmf);
>>>>>>>> +void amd_pmf_gpu_deinit(struct amd_gpu_pmf_data *pmf);
>>>>>>>> +#endif
>>>>>>>>
> 

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

* Re: [PATCH v4 13/17] platform/x86/amd/pmf: Add PMF-AMDGPU get interface
  2023-10-18 19:08           ` Hans de Goede
@ 2023-11-17  8:04             ` Shyam Sundar S K
  0 siblings, 0 replies; 35+ messages in thread
From: Shyam Sundar S K @ 2023-11-17  8:04 UTC (permalink / raw)
  To: Hans de Goede, Mario Limonciello, Christian König,
	Ilpo Järvinen
  Cc: Xinhui.Pan, Patil.Reddy, basavaraj.natikar, jikos, amd-gfx,
	platform-driver-x86, markgross, benjamin.tissoires, dri-devel,
	linux-input, alexander.deucher

Hi Hans,

Apologies for the long delay.

On 10/19/2023 12:38 AM, Hans de Goede wrote:
> Hi,
> 
> I was not following this at first, so my apologies for
> jumping in in the middle of the thread:
> 
> 
> <snip>
> 
>>>>>> +static int amd_pmf_gpu_get_cur_state(struct thermal_cooling_device *cooling_dev,
>>>>>> +                     unsigned long *state)
>>>>>> +{
>>>>>> +    struct backlight_device *bd;
>>>>>> +
>>>>>> +    if (!acpi_video_backlight_use_native())
>>>>>> +        return -ENODEV;
>>>>>> +
>>>>>> +    bd = backlight_device_get_by_type(BACKLIGHT_RAW);
>>>>>> +    if (!bd)
>>>>>> +        return -ENODEV;
>>>>>> +
>>>>>> +    *state = backlight_get_brightness(bd);
>>>>>> +
>>>>>> +    return 0;
>>>>>> +}
>>>>>> +
>>>>>> +static int amd_pmf_gpu_get_max_state(struct thermal_cooling_device *cooling_dev,
>>>>>> +                     unsigned long *state)
>>>>>> +{
>>>>>> +    struct backlight_device *bd;
>>>>>> +
>>>>>> +    if (!acpi_video_backlight_use_native())
>>>>>> +        return -ENODEV;
>>>>>> +
>>>>>> +    bd = backlight_device_get_by_type(BACKLIGHT_RAW);
>>>>>> +    if (!bd)
>>>>>> +        return -ENODEV;
>>>>>> +
>>>>>> +    if (backlight_is_blank(bd))
>>>>>> +        *state = 0;
>>>>>> +    else
>>>>>> +        *state = bd->props.max_brightness;
>>>>>> +
>>>>>> +    return 0;
>>>>>> +}
>>>>>> +
>>>>>> +static const struct thermal_cooling_device_ops bd_cooling_ops = {
>>>>>> +    .get_max_state = amd_pmf_gpu_get_max_state,
>>>>>> +    .get_cur_state = amd_pmf_gpu_get_cur_state,
>>>>>> +};
> 
> So first of all, good to see that this is using the
> thermal_cooling_device APIs now, that is great thank you.
> 
> But the whole idea behind using the thermal_cooling_device APIs
> is that amdgpu exports the cooling_device itself, rather then have
> the AMD PMF code export it. Now the AMD PMF code is still poking
> at the backlight_device itself, while the idea was to delegate
> this to the GPU driver.
> 
> Actually seeing all the acpi_video_backlight_use_native()
> checks here, I wonder why only have this work with native backlight
> control. One step better would be to add thermal_cooling_device
> support to the backlight core in:
> drivers/video/backlight/backlight.c
> 
> Then it will work with any backlight control provider!
> 
> 
> 
> Last but not least this code MUST not call
> acpi_video_backlight_use_native()
> 
> No code other then native GPU drivers must ever call
> acpi_video_backlight_use_native(). This special function
> not only checks if the native backlight control is the
> one which the detection code in drivers/acpi/video_detect.c
> has selected, it also signals to video_detect.c that
> native GPU backlight control is available.
> 
> So by calling this in the AMD PMF code you are now
> telling video_detect.c that native GPU backlight control
> is available on all systems where AMD PMF runs.
> 
> As I already said I really believe the whole cooling
> device should be registered somewhere else. But if you
> do end up sticking with this then you MUST replace
> the acpi_video_backlight_use_native() calls with:
> 
> 	if (acpi_video_get_backlight_type() == acpi_backlight_native) {...}

Thank you very much for your detailed feedback. This helped.

I have moved the code from amdgpu to PMF driver which has changes for
DRM. This also has changed w.r.t thermal device change what you suggested.

I have used the checks where ever appropriate:
acpi_video_get_backlight_type() == acpi_backlight_native

Kindly take a look at v5 submission.

Thanks,
Shyam

> 
> Regards,
> 
> Hans
> 
> 
> 

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

end of thread, other threads:[~2023-11-17  8:04 UTC | newest]

Thread overview: 35+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2023-10-18  7:02 [PATCH v4 00/17] Introduce PMF Smart PC Solution Builder Feature Shyam Sundar S K
2023-10-18  7:02 ` [PATCH v4 01/17] platform/x86/amd/pmf: Add PMF TEE interface Shyam Sundar S K
2023-10-18  7:02 ` [PATCH v4 02/17] platform/x86/amd/pmf: Add support for PMF-TA interaction Shyam Sundar S K
2023-10-18  7:02 ` [PATCH v4 03/17] platform/x86/amd/pmf: Change return type of amd_pmf_set_dram_addr() Shyam Sundar S K
2023-10-18  7:02 ` [PATCH v4 04/17] platform/x86/amd/pmf: Add support for PMF Policy Binary Shyam Sundar S K
2023-10-18  7:02 ` [PATCH v4 05/17] platform/x86/amd/pmf: change amd_pmf_init_features() call sequence Shyam Sundar S K
2023-10-18  7:02 ` [PATCH v4 06/17] platform/x86/amd/pmf: Add support to get inputs from other subsystems Shyam Sundar S K
2023-10-18  7:02 ` [PATCH v4 07/17] platform/x86/amd/pmf: Add support update p3t limit Shyam Sundar S K
2023-10-18  7:02 ` [PATCH v4 08/17] platform/x86/amd/pmf: Add support to update system state Shyam Sundar S K
2023-10-18  7:02 ` [PATCH v4 09/17] platform/x86/amd/pmf: Make source_as_str() as non-static Shyam Sundar S K
2023-10-18  7:02 ` [PATCH v4 10/17] platform/x86/amd/pmf: Add facility to dump TA inputs Shyam Sundar S K
2023-10-18  9:00   ` Ilpo Järvinen
2023-11-17  7:46     ` Shyam Sundar S K
2023-10-18  7:02 ` [PATCH v4 11/17] platform/x86/amd/pmf: Add capability to sideload of policy binary Shyam Sundar S K
2023-10-18 10:21   ` Ilpo Järvinen
2023-10-18  7:02 ` [PATCH v4 12/17] platform/x86/amd/pmf: dump policy binary data Shyam Sundar S K
2023-10-18 10:09   ` Ilpo Järvinen
2023-10-18  7:02 ` [PATCH v4 13/17] platform/x86/amd/pmf: Add PMF-AMDGPU get interface Shyam Sundar S K
2023-10-18  9:20   ` Ilpo Järvinen
2023-10-18  9:28     ` Shyam Sundar S K
2023-10-18  9:37       ` Ilpo Järvinen
2023-10-18 13:40       ` Christian König
2023-10-18 15:47         ` Mario Limonciello
2023-10-18 16:07           ` Christian König
2023-10-18 17:05             ` Shyam Sundar S K
2023-10-19  9:01               ` Christian König
2023-11-17  8:00                 ` Shyam Sundar S K
2023-10-18 19:08           ` Hans de Goede
2023-11-17  8:04             ` Shyam Sundar S K
2023-10-18  7:02 ` [PATCH v4 14/17] platform/x86/amd/pmf: Add PMF-AMDGPU set interface Shyam Sundar S K
2023-10-18  7:02 ` [PATCH v4 15/17] HID: amd_sfh: rename float_to_int() to amd_sfh_float_to_int() Shyam Sundar S K
2023-10-18  8:15   ` Ilpo Järvinen
2023-10-18  7:02 ` [PATCH v4 16/17] platform/x86/amd/pmf: Add PMF-AMDSFH interface for HPD Shyam Sundar S K
2023-10-18  8:29   ` Ilpo Järvinen
2023-10-18  7:02 ` [PATCH v4 17/17] platform/x86/amd/pmf: Add PMF-AMDSFH interface for ALS 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).