mbox series

[v2,00/16] Introduce PMF Smart PC Solution Builder Feature

Message ID 20230930083715.2050863-1-Shyam-sundar.S-k@amd.com
Headers show
Series Introduce PMF Smart PC Solution Builder Feature | expand

Message

Shyam Sundar S K Sept. 30, 2023, 8:36 a.m. UTC
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.

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 (13):
  platform/x86/amd/pmf: Add PMF TEE interface
  platform/x86/amd/pmf: Add support 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: 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             |  25 +
 drivers/gpu/drm/amd/amdgpu/Makefile           |   2 +
 drivers/gpu/drm/amd/amdgpu/amdgpu.h           |   1 +
 drivers/gpu/drm/amd/amdgpu/amdgpu_pmf.c       | 154 ++++++
 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           |  52 +-
 drivers/platform/x86/amd/pmf/pmf.h            | 201 +++++++
 drivers/platform/x86/amd/pmf/spc.c            | 197 +++++++
 drivers/platform/x86/amd/pmf/sps.c            |   2 +-
 drivers/platform/x86/amd/pmf/tee-if.c         | 515 ++++++++++++++++++
 include/linux/amd-pmf-io.h                    |  55 ++
 19 files changed, 1317 insertions(+), 25 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

Comments

Ilpo Järvinen Oct. 4, 2023, 10:50 a.m. UTC | #1
On Sat, 30 Sep 2023, Shyam Sundar S K wrote:

> AMD PMF driver loads the PMF TA (Trusted Application) into the AMD
> ASP's (AMD Security Processor) TEE (Trusted Execution Environment).
> 
> PMF Trusted Application is a secured firmware placed under
> /lib/firmware/amdtee gets loaded only when the TEE environment is
> initialized. Add the initial code path to build these pipes.
> 
> Reviewed-by: Mario Limonciello <mario.limonciello@amd.com>
> Signed-off-by: Shyam Sundar S K <Shyam-sundar.S-k@amd.com>
> ---
>  drivers/platform/x86/amd/pmf/Makefile |   3 +-
>  drivers/platform/x86/amd/pmf/core.c   |  11 ++-
>  drivers/platform/x86/amd/pmf/pmf.h    |  16 ++++
>  drivers/platform/x86/amd/pmf/tee-if.c | 112 ++++++++++++++++++++++++++
>  4 files changed, 138 insertions(+), 4 deletions(-)
>  create mode 100644 drivers/platform/x86/amd/pmf/tee-if.c
> 
> diff --git a/drivers/platform/x86/amd/pmf/Makefile b/drivers/platform/x86/amd/pmf/Makefile
> index fdededf54392..d2746ee7369f 100644
> --- a/drivers/platform/x86/amd/pmf/Makefile
> +++ b/drivers/platform/x86/amd/pmf/Makefile
> @@ -6,4 +6,5 @@
>  
>  obj-$(CONFIG_AMD_PMF) += amd-pmf.o
>  amd-pmf-objs := core.o acpi.o sps.o \
> -		auto-mode.o cnqf.o
> +		auto-mode.o cnqf.o \
> +		tee-if.o
> diff --git a/drivers/platform/x86/amd/pmf/core.c b/drivers/platform/x86/amd/pmf/core.c
> index 78ed3ee22555..68f1389dda3e 100644
> --- a/drivers/platform/x86/amd/pmf/core.c
> +++ b/drivers/platform/x86/amd/pmf/core.c
> @@ -309,8 +309,11 @@ static void amd_pmf_init_features(struct amd_pmf_dev *dev)
>  		dev_dbg(dev->dev, "SPS enabled and Platform Profiles registered\n");
>  	}
>  
> -	/* Enable Auto Mode */
> -	if (is_apmf_func_supported(dev, APMF_FUNC_AUTO_MODE)) {
> +	if (amd_pmf_init_smart_pc(dev)) {
> +		/* Enable Smart PC Solution builder */
> +		dev_dbg(dev->dev, "Smart PC Solution Enabled\n");
> +	} else if (is_apmf_func_supported(dev, APMF_FUNC_AUTO_MODE)) {
> +		/* Enable Auto Mode */

I'm pretty certain neither of these two comments add any information to 
what's readily visible from the code itself so they can be dropped.

>  		amd_pmf_init_auto_mode(dev);
>  		dev_dbg(dev->dev, "Auto Mode Init done\n");
>  	} else if (is_apmf_func_supported(dev, APMF_FUNC_DYN_SLIDER_AC) ||
> @@ -330,7 +333,9 @@ static void amd_pmf_deinit_features(struct amd_pmf_dev *dev)
>  		amd_pmf_deinit_sps(dev);
>  	}
>  
> -	if (is_apmf_func_supported(dev, APMF_FUNC_AUTO_MODE)) {
> +	if (dev->smart_pc_enabled) {
> +		amd_pmf_deinit_smart_pc(dev);
> +	} else if (is_apmf_func_supported(dev, APMF_FUNC_AUTO_MODE)) {
>  		amd_pmf_deinit_auto_mode(dev);
>  	} else if (is_apmf_func_supported(dev, APMF_FUNC_DYN_SLIDER_AC) ||
>  			  is_apmf_func_supported(dev, APMF_FUNC_DYN_SLIDER_DC)) {
> diff --git a/drivers/platform/x86/amd/pmf/pmf.h b/drivers/platform/x86/amd/pmf/pmf.h
> index deba88e6e4c8..02460c2a31ea 100644
> --- a/drivers/platform/x86/amd/pmf/pmf.h
> +++ b/drivers/platform/x86/amd/pmf/pmf.h
> @@ -179,6 +179,12 @@ struct amd_pmf_dev {
>  	bool cnqf_enabled;
>  	bool cnqf_supported;
>  	struct notifier_block pwr_src_notifier;
> +	/* Smart PC solution builder */
> +	struct tee_context *tee_ctx;
> +	struct tee_shm *fw_shm_pool;
> +	u32 session_id;
> +	void *shbuf;
> +	bool smart_pc_enabled;
>  };
>  
>  struct apmf_sps_prop_granular {
> @@ -389,6 +395,13 @@ struct apmf_dyn_slider_output {
>  	struct apmf_cnqf_power_set ps[APMF_CNQF_MAX];
>  } __packed;
>  
> +struct ta_pmf_shared_memory {
> +	int command_id;
> +	int resp_id;
> +	u32 pmf_result;
> +	u32 if_version;
> +};
> +
>  /* Core Layer */
>  int apmf_acpi_init(struct amd_pmf_dev *pmf_dev);
>  void apmf_acpi_deinit(struct amd_pmf_dev *pmf_dev);
> @@ -433,4 +446,7 @@ void amd_pmf_deinit_cnqf(struct amd_pmf_dev *dev);
>  int amd_pmf_trans_cnqf(struct amd_pmf_dev *dev, int socket_power, ktime_t time_lapsed_ms);
>  extern const struct attribute_group cnqf_feature_attribute_group;
>  
> +/* Smart PC builder Layer*/

Missing space.

> +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..4db80ca59a11
> --- /dev/null
> +++ b/drivers/platform/x86/amd/pmf/tee-if.c
> @@ -0,0 +1,112 @@
> +// 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, ret:%#x\n", sess_arg.ret, rc);

Print normal -Exx error codes as %d, not %x (rc). I don't know what would 
be best to do with sess_arg.ret, TEEC_ERROR_* look like errnos (negative 
values) manually converted into u32.

> +		rc = -EINVAL;

If rc < 0, I think you should just pass the error code on.

> +	} else {
> +		*id = sess_arg.session;
> +	}
> +
> +	return rc;
> +}
> +
> +static int amd_pmf_tee_init(struct amd_pmf_dev *dev)
> +{
> +	int ret;
> +	u32 size;
> +
> +	/* Open context with TEE driver */

Too obvious comment to stay, it's what the code already says on the next 
line so there's little point to repeat something this obvious in the 
comments.

> +	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);
> +	}
> +
> +	/* Open session with PMF Trusted App */

Remove this one too.

> +	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)
> +{
> +	/* Free the shared memory pool */
> +	tee_shm_free(dev->fw_shm_pool);
> +
> +	/* close the existing session with PMF TA*/

Missing space.

> +	tee_client_close_session(dev->tee_ctx, dev->session_id);
> +
> +	/* close the context with TEE driver */
> +	tee_client_close_context(dev->tee_ctx);
> +}
> +
> +int amd_pmf_init_smart_pc(struct amd_pmf_dev *dev)
> +{
> +	return amd_pmf_tee_init(dev);
> +}
> +
> +void amd_pmf_deinit_smart_pc(struct amd_pmf_dev *dev)
> +{
> +	amd_pmf_tee_deinit(dev);
> +}
>
Ilpo Järvinen Oct. 4, 2023, 11:03 a.m. UTC | #2
On Sat, 30 Sep 2023, Shyam Sundar S K wrote:

> 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.
> 
> 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 | 26 ++++++++++++++++++--------
>  drivers/platform/x86/amd/pmf/pmf.h  |  1 +
>  2 files changed, 19 insertions(+), 8 deletions(-)
> 
> diff --git a/drivers/platform/x86/amd/pmf/core.c b/drivers/platform/x86/amd/pmf/core.c
> index 68f1389dda3e..678dce4fea08 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
> @@ -287,9 +293,13 @@ int amd_pmf_init_metrics_table(struct amd_pmf_dev *dev)
>  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);

Won't this now leak the previous ->buf?

> +		if (ret)
> +			return ret;
> +	}
>  
>  	return 0;
>  }
> diff --git a/drivers/platform/x86/amd/pmf/pmf.h b/drivers/platform/x86/amd/pmf/pmf.h
> index e0837799f521..3930b8ed8333 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);
>
Ilpo Järvinen Oct. 4, 2023, 12:27 p.m. UTC | #3
On Sat, 30 Sep 2023, Shyam Sundar S K wrote:

> PMF driver sends constant inputs to TA which its gets via the other
> subsystems in the kernel. To debug certain TA issues knowing what inputs
> being sent to TA becomes critical. Add debug facility to the driver which
> can isolate Smart PC and TA related issues.
> 
> 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/sps.c    |  2 +-
>  drivers/platform/x86/amd/pmf/tee-if.c |  1 +
>  4 files changed, 42 insertions(+), 1 deletion(-)
> 
> diff --git a/drivers/platform/x86/amd/pmf/pmf.h b/drivers/platform/x86/amd/pmf/pmf.h
> index 34778192432e..2ad5ece47601 100644
> --- a/drivers/platform/x86/amd/pmf/pmf.h
> +++ b/drivers/platform/x86/amd/pmf/pmf.h
> @@ -595,6 +595,7 @@ int apmf_get_static_slider_granular(struct amd_pmf_dev *pdev,
>  bool is_pprof_balanced(struct amd_pmf_dev *pmf);
>  int amd_pmf_power_slider_update_event(struct amd_pmf_dev *dev);
>  
> +const char *source_as_str(unsigned int state);

Too generic name, add prefix to the name.
Shyam Sundar S K Oct. 9, 2023, 4:58 a.m. UTC | #4
On 10/4/2023 4:20 PM, Ilpo Järvinen wrote:
> On Sat, 30 Sep 2023, Shyam Sundar S K wrote:
> 
>> AMD PMF driver loads the PMF TA (Trusted Application) into the AMD
>> ASP's (AMD Security Processor) TEE (Trusted Execution Environment).
>>
>> PMF Trusted Application is a secured firmware placed under
>> /lib/firmware/amdtee gets loaded only when the TEE environment is
>> initialized. Add the initial code path to build these pipes.
>>
>> Reviewed-by: Mario Limonciello <mario.limonciello@amd.com>
>> Signed-off-by: Shyam Sundar S K <Shyam-sundar.S-k@amd.com>
>> ---
>>  drivers/platform/x86/amd/pmf/Makefile |   3 +-
>>  drivers/platform/x86/amd/pmf/core.c   |  11 ++-
>>  drivers/platform/x86/amd/pmf/pmf.h    |  16 ++++
>>  drivers/platform/x86/amd/pmf/tee-if.c | 112 ++++++++++++++++++++++++++
>>  4 files changed, 138 insertions(+), 4 deletions(-)
>>  create mode 100644 drivers/platform/x86/amd/pmf/tee-if.c
>>
>> diff --git a/drivers/platform/x86/amd/pmf/Makefile b/drivers/platform/x86/amd/pmf/Makefile
>> index fdededf54392..d2746ee7369f 100644
>> --- a/drivers/platform/x86/amd/pmf/Makefile
>> +++ b/drivers/platform/x86/amd/pmf/Makefile
>> @@ -6,4 +6,5 @@
>>  
>>  obj-$(CONFIG_AMD_PMF) += amd-pmf.o
>>  amd-pmf-objs := core.o acpi.o sps.o \
>> -		auto-mode.o cnqf.o
>> +		auto-mode.o cnqf.o \
>> +		tee-if.o
>> diff --git a/drivers/platform/x86/amd/pmf/core.c b/drivers/platform/x86/amd/pmf/core.c
>> index 78ed3ee22555..68f1389dda3e 100644
>> --- a/drivers/platform/x86/amd/pmf/core.c
>> +++ b/drivers/platform/x86/amd/pmf/core.c
>> @@ -309,8 +309,11 @@ static void amd_pmf_init_features(struct amd_pmf_dev *dev)
>>  		dev_dbg(dev->dev, "SPS enabled and Platform Profiles registered\n");
>>  	}
>>  
>> -	/* Enable Auto Mode */
>> -	if (is_apmf_func_supported(dev, APMF_FUNC_AUTO_MODE)) {
>> +	if (amd_pmf_init_smart_pc(dev)) {
>> +		/* Enable Smart PC Solution builder */
>> +		dev_dbg(dev->dev, "Smart PC Solution Enabled\n");
>> +	} else if (is_apmf_func_supported(dev, APMF_FUNC_AUTO_MODE)) {
>> +		/* Enable Auto Mode */
> 
> I'm pretty certain neither of these two comments add any information to 
> what's readily visible from the code itself so they can be dropped.
> 
>>  		amd_pmf_init_auto_mode(dev);
>>  		dev_dbg(dev->dev, "Auto Mode Init done\n");
>>  	} else if (is_apmf_func_supported(dev, APMF_FUNC_DYN_SLIDER_AC) ||
>> @@ -330,7 +333,9 @@ static void amd_pmf_deinit_features(struct amd_pmf_dev *dev)
>>  		amd_pmf_deinit_sps(dev);
>>  	}
>>  
>> -	if (is_apmf_func_supported(dev, APMF_FUNC_AUTO_MODE)) {
>> +	if (dev->smart_pc_enabled) {
>> +		amd_pmf_deinit_smart_pc(dev);
>> +	} else if (is_apmf_func_supported(dev, APMF_FUNC_AUTO_MODE)) {
>>  		amd_pmf_deinit_auto_mode(dev);
>>  	} else if (is_apmf_func_supported(dev, APMF_FUNC_DYN_SLIDER_AC) ||
>>  			  is_apmf_func_supported(dev, APMF_FUNC_DYN_SLIDER_DC)) {
>> diff --git a/drivers/platform/x86/amd/pmf/pmf.h b/drivers/platform/x86/amd/pmf/pmf.h
>> index deba88e6e4c8..02460c2a31ea 100644
>> --- a/drivers/platform/x86/amd/pmf/pmf.h
>> +++ b/drivers/platform/x86/amd/pmf/pmf.h
>> @@ -179,6 +179,12 @@ struct amd_pmf_dev {
>>  	bool cnqf_enabled;
>>  	bool cnqf_supported;
>>  	struct notifier_block pwr_src_notifier;
>> +	/* Smart PC solution builder */
>> +	struct tee_context *tee_ctx;
>> +	struct tee_shm *fw_shm_pool;
>> +	u32 session_id;
>> +	void *shbuf;
>> +	bool smart_pc_enabled;
>>  };
>>  
>>  struct apmf_sps_prop_granular {
>> @@ -389,6 +395,13 @@ struct apmf_dyn_slider_output {
>>  	struct apmf_cnqf_power_set ps[APMF_CNQF_MAX];
>>  } __packed;
>>  
>> +struct ta_pmf_shared_memory {
>> +	int command_id;
>> +	int resp_id;
>> +	u32 pmf_result;
>> +	u32 if_version;
>> +};
>> +
>>  /* Core Layer */
>>  int apmf_acpi_init(struct amd_pmf_dev *pmf_dev);
>>  void apmf_acpi_deinit(struct amd_pmf_dev *pmf_dev);
>> @@ -433,4 +446,7 @@ void amd_pmf_deinit_cnqf(struct amd_pmf_dev *dev);
>>  int amd_pmf_trans_cnqf(struct amd_pmf_dev *dev, int socket_power, ktime_t time_lapsed_ms);
>>  extern const struct attribute_group cnqf_feature_attribute_group;
>>  
>> +/* Smart PC builder Layer*/
> 
> Missing space.
> 
>> +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..4db80ca59a11
>> --- /dev/null
>> +++ b/drivers/platform/x86/amd/pmf/tee-if.c
>> @@ -0,0 +1,112 @@
>> +// 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, ret:%#x\n", sess_arg.ret, rc);
> 
> Print normal -Exx error codes as %d, not %x (rc). I don't know what would 
> be best to do with sess_arg.ret, TEEC_ERROR_* look like errnos (negative 
> values) manually converted into u32.

in drivers/tee/amdtee/amdtee_private.h, all the TEEC_* are hex. So
sess_arg.ret can remain %x? rc I have changed to %d.

Rest all I will address in v3.

Thanks,
Shyam
> 
>> +		rc = -EINVAL;
> 
> If rc < 0, I think you should just pass the error code on.
> 
>> +	} else {
>> +		*id = sess_arg.session;
>> +	}
>> +
>> +	return rc;
>> +}
>> +
>> +static int amd_pmf_tee_init(struct amd_pmf_dev *dev)
>> +{
>> +	int ret;
>> +	u32 size;
>> +
>> +	/* Open context with TEE driver */
> 
> Too obvious comment to stay, it's what the code already says on the next 
> line so there's little point to repeat something this obvious in the 
> comments.
> 
>> +	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);
>> +	}
>> +
>> +	/* Open session with PMF Trusted App */
> 
> Remove this one too.
> 
>> +	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)
>> +{
>> +	/* Free the shared memory pool */
>> +	tee_shm_free(dev->fw_shm_pool);
>> +
>> +	/* close the existing session with PMF TA*/
> 
> Missing space.
> 
>> +	tee_client_close_session(dev->tee_ctx, dev->session_id);
>> +
>> +	/* close the context with TEE driver */
>> +	tee_client_close_context(dev->tee_ctx);
>> +}
>> +
>> +int amd_pmf_init_smart_pc(struct amd_pmf_dev *dev)
>> +{
>> +	return amd_pmf_tee_init(dev);
>> +}
>> +
>> +void amd_pmf_deinit_smart_pc(struct amd_pmf_dev *dev)
>> +{
>> +	amd_pmf_tee_deinit(dev);
>> +}
>>
>
Ilpo Järvinen Oct. 9, 2023, 10:29 a.m. UTC | #5
On Mon, 9 Oct 2023, Shyam Sundar S K wrote:

> 
> 
> On 10/4/2023 4:20 PM, Ilpo Järvinen wrote:
> > On Sat, 30 Sep 2023, Shyam Sundar S K wrote:
> > 
> >> AMD PMF driver loads the PMF TA (Trusted Application) into the AMD
> >> ASP's (AMD Security Processor) TEE (Trusted Execution Environment).
> >>
> >> PMF Trusted Application is a secured firmware placed under
> >> /lib/firmware/amdtee gets loaded only when the TEE environment is
> >> initialized. Add the initial code path to build these pipes.
> >>
> >> Reviewed-by: Mario Limonciello <mario.limonciello@amd.com>
> >> Signed-off-by: Shyam Sundar S K <Shyam-sundar.S-k@amd.com>
> >> ---
> >>  drivers/platform/x86/amd/pmf/Makefile |   3 +-
> >>  drivers/platform/x86/amd/pmf/core.c   |  11 ++-
> >>  drivers/platform/x86/amd/pmf/pmf.h    |  16 ++++
> >>  drivers/platform/x86/amd/pmf/tee-if.c | 112 ++++++++++++++++++++++++++
> >>  4 files changed, 138 insertions(+), 4 deletions(-)
> >>  create mode 100644 drivers/platform/x86/amd/pmf/tee-if.c
> >>
> >> diff --git a/drivers/platform/x86/amd/pmf/Makefile b/drivers/platform/x86/amd/pmf/Makefile
> >> index fdededf54392..d2746ee7369f 100644
> >> --- a/drivers/platform/x86/amd/pmf/Makefile
> >> +++ b/drivers/platform/x86/amd/pmf/Makefile
> >> @@ -6,4 +6,5 @@
> >>  
> >>  obj-$(CONFIG_AMD_PMF) += amd-pmf.o
> >>  amd-pmf-objs := core.o acpi.o sps.o \
> >> -		auto-mode.o cnqf.o
> >> +		auto-mode.o cnqf.o \
> >> +		tee-if.o
> >> diff --git a/drivers/platform/x86/amd/pmf/core.c b/drivers/platform/x86/amd/pmf/core.c
> >> index 78ed3ee22555..68f1389dda3e 100644
> >> --- a/drivers/platform/x86/amd/pmf/core.c
> >> +++ b/drivers/platform/x86/amd/pmf/core.c
> >> @@ -309,8 +309,11 @@ static void amd_pmf_init_features(struct amd_pmf_dev *dev)
> >>  		dev_dbg(dev->dev, "SPS enabled and Platform Profiles registered\n");
> >>  	}
> >>  
> >> -	/* Enable Auto Mode */
> >> -	if (is_apmf_func_supported(dev, APMF_FUNC_AUTO_MODE)) {
> >> +	if (amd_pmf_init_smart_pc(dev)) {
> >> +		/* Enable Smart PC Solution builder */
> >> +		dev_dbg(dev->dev, "Smart PC Solution Enabled\n");
> >> +	} else if (is_apmf_func_supported(dev, APMF_FUNC_AUTO_MODE)) {
> >> +		/* Enable Auto Mode */
> > 
> > I'm pretty certain neither of these two comments add any information to 
> > what's readily visible from the code itself so they can be dropped.
> > 
> >>  		amd_pmf_init_auto_mode(dev);
> >>  		dev_dbg(dev->dev, "Auto Mode Init done\n");
> >>  	} else if (is_apmf_func_supported(dev, APMF_FUNC_DYN_SLIDER_AC) ||
> >> @@ -330,7 +333,9 @@ static void amd_pmf_deinit_features(struct amd_pmf_dev *dev)
> >>  		amd_pmf_deinit_sps(dev);
> >>  	}
> >>  
> >> -	if (is_apmf_func_supported(dev, APMF_FUNC_AUTO_MODE)) {
> >> +	if (dev->smart_pc_enabled) {
> >> +		amd_pmf_deinit_smart_pc(dev);
> >> +	} else if (is_apmf_func_supported(dev, APMF_FUNC_AUTO_MODE)) {
> >>  		amd_pmf_deinit_auto_mode(dev);
> >>  	} else if (is_apmf_func_supported(dev, APMF_FUNC_DYN_SLIDER_AC) ||
> >>  			  is_apmf_func_supported(dev, APMF_FUNC_DYN_SLIDER_DC)) {
> >> diff --git a/drivers/platform/x86/amd/pmf/pmf.h b/drivers/platform/x86/amd/pmf/pmf.h
> >> index deba88e6e4c8..02460c2a31ea 100644
> >> --- a/drivers/platform/x86/amd/pmf/pmf.h
> >> +++ b/drivers/platform/x86/amd/pmf/pmf.h
> >> @@ -179,6 +179,12 @@ struct amd_pmf_dev {
> >>  	bool cnqf_enabled;
> >>  	bool cnqf_supported;
> >>  	struct notifier_block pwr_src_notifier;
> >> +	/* Smart PC solution builder */
> >> +	struct tee_context *tee_ctx;
> >> +	struct tee_shm *fw_shm_pool;
> >> +	u32 session_id;
> >> +	void *shbuf;
> >> +	bool smart_pc_enabled;
> >>  };
> >>  
> >>  struct apmf_sps_prop_granular {
> >> @@ -389,6 +395,13 @@ struct apmf_dyn_slider_output {
> >>  	struct apmf_cnqf_power_set ps[APMF_CNQF_MAX];
> >>  } __packed;
> >>  
> >> +struct ta_pmf_shared_memory {
> >> +	int command_id;
> >> +	int resp_id;
> >> +	u32 pmf_result;
> >> +	u32 if_version;
> >> +};
> >> +
> >>  /* Core Layer */
> >>  int apmf_acpi_init(struct amd_pmf_dev *pmf_dev);
> >>  void apmf_acpi_deinit(struct amd_pmf_dev *pmf_dev);
> >> @@ -433,4 +446,7 @@ void amd_pmf_deinit_cnqf(struct amd_pmf_dev *dev);
> >>  int amd_pmf_trans_cnqf(struct amd_pmf_dev *dev, int socket_power, ktime_t time_lapsed_ms);
> >>  extern const struct attribute_group cnqf_feature_attribute_group;
> >>  
> >> +/* Smart PC builder Layer*/
> > 
> > Missing space.
> > 
> >> +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..4db80ca59a11
> >> --- /dev/null
> >> +++ b/drivers/platform/x86/amd/pmf/tee-if.c
> >> @@ -0,0 +1,112 @@
> >> +// 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, ret:%#x\n", sess_arg.ret, rc);
> > 
> > Print normal -Exx error codes as %d, not %x (rc). I don't know what would 
> > be best to do with sess_arg.ret, TEEC_ERROR_* look like errnos (negative 
> > values) manually converted into u32.
> 
> in drivers/tee/amdtee/amdtee_private.h, all the TEEC_* are hex. So
> sess_arg.ret can remain %x?

Sure, you can leave it to %x.