Re: [PATCH v2 02/16] platform/x86/amd/pmf: Add support PMF-TA interaction

2023-10-04 Thread Ilpo Järvinen
On Sat, 30 Sep 2023, Shyam Sundar S K wrote:

> PMF TA (Trusted Application) loads via the TEE environment into the
> AMD ASP.
> 
> PMF-TA supports two commands:
> 1) Init: Initialize the TA with the PMF Smart PC policy binary and
> start the policy engine. A policy is a combination of inputs and
> outputs, where;
>  - the inputs are the changing dynamics of the system like the user
>behaviour, system heuristics etc.
>  - the outputs, which are the actions to be set on the system which
>lead to better power management and enhanced user experience.
> 
> PMF driver acts as a central manager in this case to supply the
> inputs required to the TA (either by getting the information from
> the other kernel subsystems or from userland)
> 
> 2) Enact: Enact the output actions from the TA. The action could be
> applying a new thermal limit to boost/throttle the power limits or
> change system behavior.
> 
> Reviewed-by: Mario Limonciello 
> Signed-off-by: Shyam Sundar S K 
> ---
>  drivers/platform/x86/amd/pmf/pmf.h| 10 +++
>  drivers/platform/x86/amd/pmf/tee-if.c | 97 ++-
>  2 files changed, 106 insertions(+), 1 deletion(-)
> 
> diff --git a/drivers/platform/x86/amd/pmf/pmf.h 
> b/drivers/platform/x86/amd/pmf/pmf.h
> index 02460c2a31ea..e0837799f521 100644
> --- a/drivers/platform/x86/amd/pmf/pmf.h
> +++ b/drivers/platform/x86/amd/pmf/pmf.h
> @@ -59,6 +59,9 @@
>  #define ARG_NONE 0
>  #define AVG_SAMPLE_SIZE 3
>  
> +/* TA macros */
> +#define PMF_TA_IF_VERSION_MAJOR  1
> +
>  /* AMD PMF BIOS interfaces */
>  struct apmf_verify_interface {
>   u16 size;
> @@ -184,6 +187,7 @@ struct amd_pmf_dev {
>   struct tee_shm *fw_shm_pool;
>   u32 session_id;
>   void *shbuf;
> + struct delayed_work pb_work;
>   bool smart_pc_enabled;
>  };
>  
> @@ -395,6 +399,12 @@ struct apmf_dyn_slider_output {
>   struct apmf_cnqf_power_set ps[APMF_CNQF_MAX];
>  } __packed;
>  
> +/* cmd ids for TA communication */
> +enum ta_pmf_command {
> + TA_PMF_COMMAND_POLICY_BUILDER_INITIALIZE,
> + TA_PMF_COMMAND_POLICY_BUILDER_ENACT_POLICIES,
> +};
> +
>  struct ta_pmf_shared_memory {
>   int command_id;
>   int resp_id;
> diff --git a/drivers/platform/x86/amd/pmf/tee-if.c 
> b/drivers/platform/x86/amd/pmf/tee-if.c
> index 4db80ca59a11..1b3985cd7c08 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_PARAM4
> +
> +/* Policy binary actions sampling frequency (in ms) */
> +static int pb_actions_ms = 1000;
> +#ifdef CONFIG_AMD_PMF_DEBUG
> +module_param(pb_actions_ms, int, 0644);
> +MODULE_PARM_DESC(pb_actions_ms, "Policy binary actions sampling frequency 
> (default = 1000ms)");
> +#endif
> +
>  static const uuid_t amd_pmf_ta_uuid = UUID_INIT(0x6fd93b77, 0x3fb8, 0x524d,
>   0xb1, 0x2d, 0xc5, 0x29, 0xb1, 
> 0x3d, 0x85, 0x43);
>  
> +static void amd_pmf_prepare_args(struct amd_pmf_dev *dev, int cmd,
> +  struct tee_ioctl_invoke_arg *arg,
> +  struct tee_param *param)
> +{
> + memset(arg, 0, sizeof(*arg));
> + memset(param, 0, MAX_TEE_PARAM * sizeof(*param));
> +
> + arg->func = cmd;
> + arg->session = dev->session_id;
> + arg->num_params = MAX_TEE_PARAM;
> +
> + /* Fill invoke cmd params */
> + param[0].u.memref.size = sizeof(struct ta_pmf_shared_memory);
> + param[0].attr = TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INOUT;
> + param[0].u.memref.shm = dev->fw_shm_pool;
> + param[0].u.memref.shm_offs = 0;
> +}
> +
> +static int amd_pmf_invoke_cmd_enact(struct amd_pmf_dev *dev)
> +{
> + struct ta_pmf_shared_memory *ta_sm = NULL;
> + struct tee_param param[MAX_TEE_PARAM];
> + struct tee_ioctl_invoke_arg arg;
> + int ret = 0;
> +
> + if (!dev->tee_ctx)
> + return -ENODEV;
> +
> + ta_sm = (struct ta_pmf_shared_memory *)dev->shbuf;

Don't cast from void * to a typed pointer, it's unnecessary as compiler 
will handle that for you.

> + memset(ta_sm, 0, sizeof(struct ta_pmf_shared_memory));

sizeof(*ta_sm) to be on the safer side of things.

> + 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:%x\n", 
> arg.ret, ret);

-Exx code should be printed as %x

> + return -EINVAL;

This overrides the original error code if ret < 0.

> + }
> +
> + 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

Re: [PATCH v2 02/16] platform/x86/amd/pmf: Add support PMF-TA interaction

2023-10-04 Thread Ilpo Järvinen
On Sat, 30 Sep 2023, Shyam Sundar S K wrote:

> PMF TA (Trusted Application) loads via the TEE environment into the
> AMD ASP.
> 
> PMF-TA supports two commands:
> 1) Init: Initialize the TA with the PMF Smart PC policy binary and
> start the policy engine. A policy is a combination of inputs and
> outputs, where;
>  - the inputs are the changing dynamics of the system like the user
>behaviour, system heuristics etc.
>  - the outputs, which are the actions to be set on the system which
>lead to better power management and enhanced user experience.
> 
> PMF driver acts as a central manager in this case to supply the
> inputs required to the TA (either by getting the information from
> the other kernel subsystems or from userland)
> 
> 2) Enact: Enact the output actions from the TA. The action could be
> applying a new thermal limit to boost/throttle the power limits or
> change system behavior.
> 
> Reviewed-by: Mario Limonciello 
> Signed-off-by: Shyam Sundar S K 
> ---
>  drivers/platform/x86/amd/pmf/pmf.h| 10 +++
>  drivers/platform/x86/amd/pmf/tee-if.c | 97 ++-
>  2 files changed, 106 insertions(+), 1 deletion(-)
> 
> diff --git a/drivers/platform/x86/amd/pmf/pmf.h 
> b/drivers/platform/x86/amd/pmf/pmf.h
> index 02460c2a31ea..e0837799f521 100644
> --- a/drivers/platform/x86/amd/pmf/pmf.h
> +++ b/drivers/platform/x86/amd/pmf/pmf.h
> @@ -59,6 +59,9 @@
>  #define ARG_NONE 0
>  #define AVG_SAMPLE_SIZE 3
>  
> +/* TA macros */
> +#define PMF_TA_IF_VERSION_MAJOR  1
> +
>  /* AMD PMF BIOS interfaces */
>  struct apmf_verify_interface {
>   u16 size;
> @@ -184,6 +187,7 @@ struct amd_pmf_dev {
>   struct tee_shm *fw_shm_pool;
>   u32 session_id;
>   void *shbuf;
> + struct delayed_work pb_work;
>   bool smart_pc_enabled;
>  };
>  
> @@ -395,6 +399,12 @@ struct apmf_dyn_slider_output {
>   struct apmf_cnqf_power_set ps[APMF_CNQF_MAX];
>  } __packed;
>  
> +/* cmd ids for TA communication */
> +enum ta_pmf_command {
> + TA_PMF_COMMAND_POLICY_BUILDER_INITIALIZE,
> + TA_PMF_COMMAND_POLICY_BUILDER_ENACT_POLICIES,
> +};
> +
>  struct ta_pmf_shared_memory {
>   int command_id;
>   int resp_id;
> diff --git a/drivers/platform/x86/amd/pmf/tee-if.c 
> b/drivers/platform/x86/amd/pmf/tee-if.c
> index 4db80ca59a11..1b3985cd7c08 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_PARAM4
> +
> +/* Policy binary actions sampling frequency (in ms) */
> +static int pb_actions_ms = 1000;

MSEC_PER_SEC (from #include , don't include the vdso one).

> +#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

-- 
 i.



Re: [PATCH v2 06/16] platform/x86/amd/pmf: Add support to get inputs from other subsystems

2023-10-04 Thread Ilpo Järvinen
On Sat, 30 Sep 2023, Shyam Sundar S K wrote:

> PMF driver sends changing inputs from each subystem to TA for evaluating
> the conditions in the policy binary.
> 
> Add initial support of plumbing in the PMF driver for Smart PC to get
> information from other subsystems in the kernel.
> 
> Signed-off-by: Shyam Sundar S K 
> ---
>  drivers/platform/x86/amd/pmf/Makefile |   2 +-
>  drivers/platform/x86/amd/pmf/pmf.h|  18 
>  drivers/platform/x86/amd/pmf/spc.c| 119 ++
>  drivers/platform/x86/amd/pmf/tee-if.c |   3 +
>  4 files changed, 141 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 6f4b6f4ecee4..60b11455dadf 100644
> --- a/drivers/platform/x86/amd/pmf/pmf.h
> +++ b/drivers/platform/x86/amd/pmf/pmf.h
> @@ -149,6 +149,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 {
> @@ -595,4 +610,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 ..3113bde051d9
> --- /dev/null
> +++ b/drivers/platform/x86/amd/pmf/spc.c
> @@ -0,0 +1,119 @@
> +// 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 
> + *  Patil Rajesh Reddy 
> + */
> +
> +#include 
> +#include 
> +#include 
> +#include "pmf.h"
> +
> +static void amd_pmf_get_smu_info(struct amd_pmf_dev *dev, struct 
> ta_pmf_enact_table *in)
> +{
> + u16 max, avg = 0;
> + int i;
> +
> + memset(dev->buf, 0, sizeof(dev->m_table));
> + amd_pmf_send_cmd(dev, SET_TRANSFER_TABLE, 0, 7, NULL);
> + memcpy(&dev->m_table, dev->buf, sizeof(dev->m_table));
> +
> + in->ev_info.socket_power = dev->m_table.apu_power + 
> dev->m_table.dgpu_power;
> + in->ev_info.skin_temperature = dev->m_table.skin_temp;
> +
> + /* get the avg C0 residency of all the cores */
> + for (i = 0; i < ARRAY_SIZE(dev->m_table.avg_core_c0residency); i++)
> + avg += dev->m_table.avg_core_c0residency[i];
> +
> + /* get the max C0 residency of all the cores */
> + max = dev->m_table.avg_core_c0residency[0];
> + for (i = 1; i < ARRAY_SIZE(dev->m_table.avg_core_c0residency); i++) {
> + if (dev->m_table.avg_core_c0residency[i] > max)
> + max = dev->m_table.avg_core_c0residency[i];
> + }

My comments weren't either answered adequately or changes made here.
Please check the v1 comments. I hope it's not because you feel hurry to 
get the next version out...

I'm still unsure if the u16 thing can overflow because I don't know what's 
the max value for avg_core_c0residency[i].

> +
> + in->ev_info.avg_c0residency = avg / 
> ARRAY_SIZE(dev->m_table.avg_core_c0residency);
> + in->ev_info.max_c0residency = max;
> + in->ev_info.gfx_busy = dev->m_table.avg_gfx_activity;
> +}
> +
> +static const char * const pmf_battery_supply_name[] = {
> + "BATT",
> + "BAT0",
> +};
> +
> +static int get_battery_prop(enum power_supply_property prop)
> +{
> + union power_supply_propval value;
> + struct power_supply *psy;
> + int i, ret = -EINVAL;
> +
> + for (i = 0; i < ARRAY_SIZE(pmf_battery_supply_name); i++) {
> + psy = power_supply_get_by_name(pmf_battery_supply_name[i]);
> + if (!psy)
> + continue;
> +
> + 

Re: [PATCH v2 12/16] platform/x86/amd/pmf: Add PMF-AMDGPU get interface

2023-10-04 Thread Ilpo Järvinen
On Sat, 30 Sep 2023, Shyam Sundar S K wrote:

> In order to provide GPU inputs to TA for the Smart PC solution to work, we
> need to have interface between the PMF driver and the AMDGPU driver.
> 
> Add the initial code path for get interface from AMDGPU.
> 
> Co-developed-by: Mario Limonciello 
> Signed-off-by: Mario Limonciello 
> Signed-off-by: Shyam Sundar S K 

> @@ -355,6 +356,21 @@ 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) {
> + /* get the amdgpu handle from the pci root after walking 
> through the pci bus */

I can see from the code that you assign to amdgpu handle so this comment 
added no information.

It doesn't really answer at all why you're doing this second step. Based 
on the give parameters to pci_get_device(), it looks as if you're asking 
for the same device you already have in pdev to be searched to you.

> + dev->gfx_data.gpu_dev = pci_get_device(pdev->vendor, 
> pdev->device, NULL);
> + if (dev->gfx_data.gpu_dev) {
> + pci_dev_put(pdev);
> + return 1; /* stop walking */
> + }
> + }
> + return 0; /* continue walking */
> +}
> +
>  static int amd_pmf_amdtee_ta_match(struct tee_ioctl_version_data *ver, const 
> void *data)
>  {
>   return ver->impl_id == TEE_IMPL_ID_AMDTEE;
> @@ -451,6 +467,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;
> +


-- 
 i.



Re: [PATCH v2 03/16] platform/x86/amd/pmf: Change return type of amd_pmf_set_dram_addr()

2023-10-04 Thread Ilpo Järvinen
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 
> Signed-off-by: Shyam Sundar S K 
> ---
>  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);
> 

-- 
 i.



Re: [PATCH v2 04/16] platform/x86/amd/pmf: Add support for PMF Policy Binary

2023-10-04 Thread Ilpo Järvinen
On Sat, 30 Sep 2023, Shyam Sundar S K wrote:

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

Re: [PATCH v2 11/16] platform/x86/amd/pmf: dump policy binary data

2023-10-04 Thread Ilpo Järvinen
On Sat, 30 Sep 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.
> 
> Signed-off-by: Shyam Sundar S K 
> ---
>  drivers/platform/x86/amd/pmf/tee-if.c | 7 +++
>  1 file changed, 7 insertions(+)
> 
> diff --git a/drivers/platform/x86/amd/pmf/tee-if.c 
> b/drivers/platform/x86/amd/pmf/tee-if.c
> index 01f974b55a6a..d16bdecfd43a 100644
> --- a/drivers/platform/x86/amd/pmf/tee-if.c
> +++ b/drivers/platform/x86/amd/pmf/tee-if.c
> @@ -290,6 +290,9 @@ static ssize_t amd_pmf_get_pb_data(struct file *filp, 
> const char __user *buf,
>   if (copy_from_user(dev->policy_buf, buf, dev->policy_sz))
>   return -EFAULT;
>  
> + print_hex_dump_debug("(pb):  ", DUMP_PREFIX_OFFSET, 16, 1, 
> dev->policy_buf,
> +  dev->policy_sz, false);
> +
>   ret = amd_pmf_start_policy_engine(dev);
>   if (ret)
>   return -EINVAL;
> @@ -341,6 +344,10 @@ static int amd_pmf_get_bios_buffer(struct amd_pmf_dev 
> *dev)
>   return -ENOMEM;
>  
>   memcpy(dev->policy_buf, dev->policy_base, dev->policy_sz);
> +#ifdef CONFIG_AMD_PMF_DEBUG
> + print_hex_dump_debug("(pb):  ", DUMP_PREFIX_OFFSET, 16, 1, 
> dev->policy_buf,
> +  dev->policy_sz, false);
> +#endif

Create a wrapper for print_hex_dump_debug into #ifdef and #else blocks for 
this too so you don't need the ifdef here.

-- 
 i.



Re: [PATCH v2 09/16] platform/x86/amd/pmf: Add facility to dump TA inputs

2023-10-04 Thread Ilpo Järvinen
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 
> Signed-off-by: Shyam Sundar S K 
> ---
>  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.

-- 
 i.

>  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);
> @@ -625,4 +626,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 3113bde051d9..3aee78629cce 100644
> --- a/drivers/platform/x86/amd/pmf/spc.c
> +++ b/drivers/platform/x86/amd/pmf/spc.c
> @@ -14,6 +14,43 @@
>  #include 
>  #include "pmf.h"
>  
> +#ifdef CONFIG_AMD_PMF_DEBUG
> +static const char *ta_slider_as_str(unsigned int state)
> +{
> + switch (state) {
> + case TA_BEST_PERFORMANCE:
> + return "PERFORMANCE";
> + case TA_BETTER_PERFORMANCE:
> + return "BALANCED";
> + case TA_BEST_BATTERY:
> + return "POWER_SAVER";
> + default:
> + return "Unknown TA Slider State";
> + }
> +}
> +
> +void amd_pmf_dump_ta_inputs(struct amd_pmf_dev *dev, struct 
> ta_pmf_enact_table *in)
> +{
> + dev_dbg(dev->dev, " TA inputs START \n");
> + dev_dbg(dev->dev, "Slider State : %s\n", 
> ta_slider_as_str(in->ev_info.power_slider));
> + dev_dbg(dev->dev, "Power Source : %s\n", 
> source_as_str(in->ev_info.power_source));
> + dev_dbg(dev->dev, "Battery Percentage : %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/sps.c 
> b/drivers/platform/x86/amd/pmf/sps.c
> index a70e67749be3..13e36b52dfe8 100644
> --- a/drivers/platform/x86/amd/pmf/sps.c
> +++ b/drivers/platform/x86/amd/pmf/sps.c
> @@ -27,7 +27,7 @@ static const char *slider_as_str(unsigned int state)
>   }
>  }
>  
> -static const char *source_as_str(unsigned int state)
> +const char *source_as_str(unsigned int state)
>  {
>   switch (state) {
>   case POWER_SOURCE_AC:
> diff --git a/drivers/platform/x86/amd/pmf/tee-if.c 
> b/drivers/platform/x86/amd/pmf/tee-if.c
> index 961011530c1b..b0711b2f8c8f 100644
> --- a/drivers/platform/x86/amd/pmf/tee-if.c
> +++ b/drivers/platform/x86/amd/pmf/tee-if.c
> @@ -187,6 +187,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(de

Re: [PATCH v2 08/16] platform/x86/amd/pmf: Add support to update system state

2023-10-04 Thread Ilpo Järvinen
On Sat, 30 Sep 2023, Shyam Sundar S K wrote:

> PMF driver based on the output actions from the TA can request to update
> the system states like entering s0i3, lock screen etc. by generating
> an uevent. Based on the udev rules set in the userspace the event id
> matching the uevent shall get updated accordingly using the systemctl.
> 
> Sample udev rules under Documentation/admin-guide/pmf.rst.
> 
> Reported-by: kernel test robot 
> Closes: 
> https://lore.kernel.org/oe-kbuild-all/202309260515.5xbr6n0g-...@intel.com/

Please don't put lkp tags for patches that are still under development 
(even if the email you get misleadingly instructs you to). Only use them 
when you fix code that's already in tree based on LKP's report.

> Signed-off-by: Shyam Sundar S K 
> ---
>  Documentation/admin-guide/index.rst   |  1 +
>  Documentation/admin-guide/pmf.rst | 25 
>  drivers/platform/x86/amd/pmf/pmf.h|  9 ++
>  drivers/platform/x86/amd/pmf/tee-if.c | 41 ++-
>  4 files changed, 75 insertions(+), 1 deletion(-)
>  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 ..90072add511e
> --- /dev/null
> +++ b/Documentation/admin-guide/pmf.rst
> @@ -0,0 +1,25 @@
> +.. SPDX-License-Identifier: GPL-2.0
> +
> +Set udev rules for PMF Smart PC Builder
> +---
> +
> +AMD PMF(Platform Management Framework) Smart PC Solution builder has to set 
> the system states
> +like S0i3, Screen lock, hibernate etc, based on the output actions provided 
> by the PMF
> +TA (Trusted Application).
> +
> +In order for this to work the PMF driver generates a uevent for userspace to 
> react to. Below are
> +sample udev rules that can facilitate this experience when a machine has PMF 
> Smart PC solution builder
> +enabled.
> +
> +Please add the following line(s) to
> +``/etc/udev/rules.d/99-local.rules``::
> +
> +DRIVERS=="amd-pmf", ACTION=="change", ENV{EVENT_ID}=="1", 
> RUN+="/usr/bin/systemctl suspend"
> +DRIVERS=="amd-pmf", ACTION=="change", ENV{EVENT_ID}=="2", 
> RUN+="/usr/bin/systemctl hibernate"
> +DRIVERS=="amd-pmf", ACTION=="change", ENV{EVENT_ID}=="3", 
> RUN+="/bin/loginctl lock-sessions"
> +
> +EVENT_ID values:
> +1= Put the system to S0i3/S2Idle
> +2= Put the system to hibernate
> +3= Lock the screen
> +
> diff --git a/drivers/platform/x86/amd/pmf/pmf.h 
> b/drivers/platform/x86/amd/pmf/pmf.h
> index d5e410c41e81..34778192432e 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 */
> @@ -439,6 +440,13 @@ struct apmf_dyn_slider_output {
>  } __packed;
>  
>  /* Smart PC - TA internals */
> +enum system_state {
> + SYSTEM_STATE__S0i3 = 1,
> + SYSTEM_STATE__S4,
> + SYSTEM_STATE__SCREEN_LOCK,
> + SYSTEM_STATE__MAX
> +};
> +
>  enum ta_slider {
>   TA_BEST_BATTERY, /* Best Battery */
>   TA_BETTER_BATTERY, /* Better Battery */
> @@ -470,6 +478,7 @@ enum ta_pmf_error_type {
>  };
>  
>  struct pmf_action_table {
> + enum system_state system_state;
>   unsigned long spl; /* in mW */
>   unsigned long sppt; /* in mW */
>   unsigned long sppt_apuonly; /* in mW */
> diff --git a/drivers/platform/x86/amd/pmf/tee-if.c 
> b/drivers/platform/x86/amd/pmf/tee-if.c
> index 315e3d2eacdf..961011530c1b 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";
> + }
> +}
> +
>  

Re: [PATCH v2 01/16] platform/x86/amd/pmf: Add PMF TEE interface

2023-10-04 Thread Ilpo Järvinen
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 
> Signed-off-by: Shyam Sundar S K 
> ---
>  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 */
>   amd_pmf_init_auto_mode(dev);
>   dev_dbg(dev->dev, "Auto Mode Init done\n");
>   } else if (is_apmf_func_supported(dev, APMF_FUNC_DYN_SLIDER_AC) ||
> @@ -330,7 +333,9 @@ static void amd_pmf_deinit_features(struct amd_pmf_dev 
> *dev)
>   amd_pmf_deinit_sps(dev);
>   }
>  
> - if (is_apmf_func_supported(dev, APMF_FUNC_AUTO_MODE)) {
> + if (dev->smart_pc_enabled) {
> + amd_pmf_deinit_smart_pc(dev);
> + } else if (is_apmf_func_supported(dev, APMF_FUNC_AUTO_MODE)) {
>   amd_pmf_deinit_auto_mode(dev);
>   } else if (is_apmf_func_supported(dev, APMF_FUNC_DYN_SLIDER_AC) ||
> is_apmf_func_supported(dev, APMF_FUNC_DYN_SLIDER_DC)) 
> {
> diff --git a/drivers/platform/x86/amd/pmf/pmf.h 
> b/drivers/platform/x86/amd/pmf/pmf.h
> index deba88e6e4c8..02460c2a31ea 100644
> --- a/drivers/platform/x86/amd/pmf/pmf.h
> +++ b/drivers/platform/x86/amd/pmf/pmf.h
> @@ -179,6 +179,12 @@ struct amd_pmf_dev {
>   bool cnqf_enabled;
>   bool cnqf_supported;
>   struct notifier_block pwr_src_notifier;
> + /* Smart PC solution builder */
> + struct tee_context *tee_ctx;
> + struct tee_shm *fw_shm_pool;
> + u32 session_id;
> + void *shbuf;
> + bool smart_pc_enabled;
>  };
>  
>  struct apmf_sps_prop_granular {
> @@ -389,6 +395,13 @@ struct apmf_dyn_slider_output {
>   struct apmf_cnqf_power_set ps[APMF_CNQF_MAX];
>  } __packed;
>  
> +struct ta_pmf_shared_memory {
> + int command_id;
> + int resp_id;
> + u32 pmf_result;
> + u32 if_version;
> +};
> +
>  /* Core Layer */
>  int apmf_acpi_init(struct amd_pmf_dev *pmf_dev);
>  void apmf_acpi_deinit(struct amd_pmf_dev *pmf_dev);
> @@ -433,4 +446,7 @@ void amd_pmf_deinit_cnqf(struct amd_pmf_dev *dev);
>  int amd_pmf_trans_cnqf(struct amd_pmf_dev *dev, int socket_power, ktime_t 
> time_lapsed_ms);
>  extern const struct attribute_group cnqf_feature_attribute_group;
>  
> +/* Smart PC builder Layer*/
> +int amd_pmf_init_smart_pc(struct amd_pmf_dev *dev);
> +void amd_pmf_deinit_smart_pc(struct amd_pmf_dev *dev);
>  #endif /* PMF_H */
> diff --git a/drivers/platform/x86/amd/pmf/tee-if.c 
> b/drivers/platform/x86/amd/pmf/tee-if.c
> new file mode 100644
> index ..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 
> + */
> +
> +#include 
> +#include 
> +#include "pmf.h"
> +
> +#define MAX_TEE_PARAM4
> +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)
> 

Re: [PATCH v2 01/16] platform/x86/amd/pmf: Add PMF TEE interface

2023-10-04 Thread Ilpo Järvinen
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 
> Signed-off-by: Shyam Sundar S K 
> ---
>  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 ..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 
> + */
> +
> +#include 
> +#include 
> +#include "pmf.h"
> +
> +#define MAX_TEE_PARAM4
> +static const uuid_t amd_pmf_ta_uuid = UUID_INIT(0x6fd93b77, 0x3fb8, 0x524d,
> +  

Re: [PATCH v2 04/16] platform/x86/amd/pmf: Add support for PMF Policy Binary

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

> >> diff --git a/drivers/platform/x86/amd/pmf/core.c 
> >> b/drivers/platform/x86/amd/pmf/core.c
> >> index 678dce4fea08..787f25511191 100644
> >> --- a/drivers/platform/x86/amd/pmf/core.c
> >> +++ b/drivers/platform/x86/amd/pmf/core.c
> >> @@ -384,6 +384,18 @@ static int amd_pmf_probe(struct platform_device *pdev)
> >>return -ENOMEM;
> >>  
> >>dev->dev = &pdev->dev;
> >> +  err = apmf_check_smart_pc(dev);
> >> +  if (!err) {
> >> +  /* in order for Smart PC solution to work it has a hard 
> >> dependency
> >> +   * on the amdtee driver to be loaded first even before the PMF 
> >> driver
> >> +   * loads. PMF ASL has a _CRS method that advertises the 
> >> existence
> >> +   * of Smart PC bit. If this information is present, use this to
> >> +   * explicitly probe the amdtee driver, so that "tee" plumbing 
> >> is done
> >> +   * before the PMF Smart PC init happens.
> >> +   */
> > 
> > But please follow no-text on /* line formatting for multiline comments. 
> > Also start with a capital letter.
> > 
> > 
> >> +  if (request_module(&

Re: [PATCH v2 06/16] platform/x86/amd/pmf: Add support to get inputs from other subsystems

2023-10-09 Thread Ilpo Järvinen
On Mon, 9 Oct 2023, Shyam Sundar S K wrote:
> On 10/4/2023 5:44 PM, Ilpo Järvinen wrote:
> > On Sat, 30 Sep 2023, Shyam Sundar S K wrote:
> > 
> >> PMF driver sends changing inputs from each subystem to TA for evaluating
> >> the conditions in the policy binary.
> >>
> >> Add initial support of plumbing in the PMF driver for Smart PC to get
> >> information from other subsystems in the kernel.
> >>
> >> Signed-off-by: Shyam Sundar S K 

> >> diff --git a/drivers/platform/x86/amd/pmf/spc.c 
> >> b/drivers/platform/x86/amd/pmf/spc.c
> >> new file mode 100644
> >> index ..3113bde051d9
> >> --- /dev/null
> >> +++ b/drivers/platform/x86/amd/pmf/spc.c
> >> @@ -0,0 +1,119 @@
> >> +// 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 
> >> + *  Patil Rajesh Reddy 
> >> + */
> >> +
> >> +#include 
> >> +#include 
> >> +#include 
> >> +#include "pmf.h"
> >> +
> >> +static void amd_pmf_get_smu_info(struct amd_pmf_dev *dev, struct 
> >> ta_pmf_enact_table *in)
> >> +{
> >> +  u16 max, avg = 0;
> >> +  int i;
> >> +
> >> +  memset(dev->buf, 0, sizeof(dev->m_table));
> >> +  amd_pmf_send_cmd(dev, SET_TRANSFER_TABLE, 0, 7, NULL);
> >> +  memcpy(&dev->m_table, dev->buf, sizeof(dev->m_table));
> >> +
> >> +  in->ev_info.socket_power = dev->m_table.apu_power + 
> >> dev->m_table.dgpu_power;
> >> +  in->ev_info.skin_temperature = dev->m_table.skin_temp;
> >> +
> >> +  /* get the avg C0 residency of all the cores */
> >> +  for (i = 0; i < ARRAY_SIZE(dev->m_table.avg_core_c0residency); i++)
> >> +  avg += dev->m_table.avg_core_c0residency[i];
> >> +
> >> +  /* get the max C0 residency of all the cores */
> >> +  max = dev->m_table.avg_core_c0residency[0];
> >> +  for (i = 1; i < ARRAY_SIZE(dev->m_table.avg_core_c0residency); i++) {
> >> +  if (dev->m_table.avg_core_c0residency[i] > max)
> >> +  max = dev->m_table.avg_core_c0residency[i];
> >> +  }
> > 
> > My comments weren't either answered adequately or changes made here.
> > Please check the v1 comments. I hope it's not because you feel hurry to 
> > get the next version out...
> > 
> > I'm still unsure if the u16 thing can overflow because I don't know what's 
> > the max value for avg_core_c0residency[i].
> 
> the highest value for avg_core_c0residency[i] is merely a small number
> and hence I retained the avg variable as u16. Not sure if there a
> 'real' case where it can overflow.

Okay, if you think it's fine, no problem with it then (not that there's 
a big advantage having it as u16 instead of e.g. unsigned int).

> Sorry, I missed to merge both into a single for loop. I will address
> this in v3.

Thanks.

-- 
 i.


Re: [PATCH v2 01/16] platform/x86/amd/pmf: Add PMF TEE interface

2023-10-09 Thread Ilpo Järvinen
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 
> >> Signed-off-by: Shyam Sundar S K 
> >> ---
> >>  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

Re: [PATCH v2 12/16] platform/x86/amd/pmf: Add PMF-AMDGPU get interface

2023-10-09 Thread Ilpo Järvinen
On Mon, 9 Oct 2023, Shyam Sundar S K wrote:
> On 10/4/2023 6:19 PM, Ilpo Järvinen wrote:
> > On Sat, 30 Sep 2023, Shyam Sundar S K wrote:
> > 
> >> In order to provide GPU inputs to TA for the Smart PC solution to work, we
> >> need to have interface between the PMF driver and the AMDGPU driver.
> >>
> >> Add the initial code path for get interface from AMDGPU.
> >>
> >> Co-developed-by: Mario Limonciello 
> >> Signed-off-by: Mario Limonciello 
> >> Signed-off-by: Shyam Sundar S K 
> > 
> >> @@ -355,6 +356,21 @@ 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) {
> >> +  /* get the amdgpu handle from the pci root after walking 
> >> through the pci bus */
> > 
> > I can see from the code that you assign to amdgpu handle so this comment 
> > added no information.
> > 
> > It doesn't really answer at all why you're doing this second step. Based 
> > on the give parameters to pci_get_device(), it looks as if you're asking 
> > for the same device you already have in pdev to be searched to you.
> 
> Not sure if I understand you remark completely.
> 
> amd_pmf_get_gpu_handle() is a callback function for pci_walk_bus
> (which is done below).
> 
> What I am trying to do here is to get the PCI handle for the GPU
> device by walking the PCI bus.
> 
> I think the 'pdev' here refers to the pci root, using that root we
> walk the entire tree and only stop walking when we find a handle to
> GPU device.

Not exactly what happens, in amd_pmf_get_gpu_handle() pdev changes on each 
call so I don't know why you stated it is refering to the "pci root".

> Do you want me to change the "pdev" parameter to be renamed as "root" ?

No, please don't do that, it would be misleading.

> Am I missing something?

I meant that at some point of the walk through the PCI devices, you have 
a PCI device pdev with ->vendor PCI_VENDOR_ID_AMD when that if condition 
above matched. Please explain why you need to do another lookup with 
pci_get_device() at that point (with the same ->vendor and ->device as 
shown below)?

> >> +  dev->gfx_data.gpu_dev = pci_get_device(pdev->vendor, 
> >> pdev->device, NULL);
> >> +  if (dev->gfx_data.gpu_dev) {
> >> +  pci_dev_put(pdev);
> >> +  return 1; /* stop walking */
> >> +  }
> >> +  }
> >> +  return 0; /* continue walking */


-- 
 i.


Re: [PATCH v3 11/16] platform/x86/amd/pmf: dump policy binary data

2023-10-10 Thread Ilpo Järvinen
On Tue, 10 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.
> 
> Signed-off-by: Shyam Sundar S K 
> ---
>  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 994daf945795..e4386f503ad0 100644
> --- a/drivers/platform/x86/amd/pmf/tee-if.c
> +++ b/drivers/platform/x86/amd/pmf/tee-if.c
> @@ -275,6 +275,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);
> +}
> +

You forgot to add the empty version of amd_pmf_hex_dump_pb function into 
#else part (so the compile fails if CONFIG_AMD_PMF_DEBUG is not set).

>  static ssize_t amd_pmf_get_pb_data(struct file *filp, const char __user *buf,
>  size_t length, loff_t *pos)
>  {
> @@ -289,6 +295,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;
> @@ -327,6 +334,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)
> @@ -341,6 +349,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);
>  
> 

-- 
 i.



Re: [PATCH v3 11/16] platform/x86/amd/pmf: dump policy binary data

2023-10-10 Thread Ilpo Järvinen
On Tue, 10 Oct 2023, Shyam Sundar S K wrote:
> On 10/10/2023 6:38 PM, Ilpo Järvinen wrote:
> > On Tue, 10 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.
> >>
> >> Signed-off-by: Shyam Sundar S K 
> >> ---
> >>  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 994daf945795..e4386f503ad0 100644
> >> --- a/drivers/platform/x86/amd/pmf/tee-if.c
> >> +++ b/drivers/platform/x86/amd/pmf/tee-if.c
> >> @@ -275,6 +275,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);
> >> +}
> >> +
> > 
> > You forgot to add the empty version of amd_pmf_hex_dump_pb function into 
> > #else part (so the compile fails if CONFIG_AMD_PMF_DEBUG is not set).
> > 
> 
> It's there (see below). I have just grouped the functions that come
> under #ifdef CONFIG_AMD_PMF_DEBUG and #else so that's more readable.
> 
> >>  static ssize_t amd_pmf_get_pb_data(struct file *filp, const char __user 
> >> *buf,
> >>   size_t length, loff_t *pos)
> >>  {
> >> @@ -289,6 +295,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;
> >> @@ -327,6 +334,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) {}
> 
> Here is the empty amd_pmf_hex_dump_pb().

Ah, sorry. I was confused by the intermediate change.

-- 
 i.


Re: [PATCH v3 06/16] platform/x86/amd/pmf: Add support to get inputs from other subsystems

2023-10-13 Thread Ilpo Järvinen
On Tue, 10 Oct 2023, Shyam Sundar S K wrote:

> PMF driver sends changing inputs from each subystem to TA for evaluating
> the conditions in the policy binary.
> 
> Add initial support of plumbing in the PMF driver for Smart PC to get
> information from other subsystems in the kernel.
> 
> Signed-off-by: Shyam Sundar S K 
> ---
>  drivers/platform/x86/amd/pmf/Makefile |   2 +-
>  drivers/platform/x86/amd/pmf/pmf.h|  18 
>  drivers/platform/x86/amd/pmf/spc.c| 119 ++
>  drivers/platform/x86/amd/pmf/tee-if.c |   3 +
>  4 files changed, 141 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 51c0e17f7720..88ee3c705913 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 {
> @@ -596,4 +611,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 ..91a7f1da911c
> --- /dev/null
> +++ b/drivers/platform/x86/amd/pmf/spc.c
> @@ -0,0 +1,119 @@
> +// 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 
> + *  Patil Rajesh Reddy 
> + */
> +
> +#include 
> +#include 
> +#include 
> +#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];
> + }
> +
> + in->ev_info.avg_c0residency = avg / 
> ARRAY_SIZE(dev->m_table.avg_core_c0residency);

Not saying the current is wrong and the difference might be 
insignificantly small... But you might want to consider using 
DIV_ROUND_CLOSEST() instead of the truncating divide (I'm not sure which 
is the best here so I leave it up to you).

> + 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 = -EINVAL;

Unnecessary to initialize ret here.

> + 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);
> +  

Re: [PATCH v12 8/9] drm/amd/pm: enable Wifi RFI mitigation feature support for SMU13.0.0

2023-10-17 Thread Ilpo Järvinen
On Tue, 17 Oct 2023, Ma Jun wrote:

> From: Evan Quan 
> 
> Fulfill the SMU13.0.0 support for Wifi RFI mitigation feature.
> 
> Signed-off-by: Evan Quan 
> Reviewed-by: Mario Limonciello 
> Signed-off-by: Ma Jun 
> --
> v10->v11:
>   - downgrade the prompt level on message failure(Lijo)
> ---
>  drivers/gpu/drm/amd/pm/swsmu/inc/amdgpu_smu.h |  3 +
>  drivers/gpu/drm/amd/pm/swsmu/inc/smu_types.h  |  3 +-
>  drivers/gpu/drm/amd/pm/swsmu/inc/smu_v13_0.h  |  3 +
>  .../gpu/drm/amd/pm/swsmu/smu13/smu_v13_0.c|  9 +++
>  .../drm/amd/pm/swsmu/smu13/smu_v13_0_0_ppt.c  | 60 +++
>  5 files changed, 77 insertions(+), 1 deletion(-)
> 
> diff --git a/drivers/gpu/drm/amd/pm/swsmu/inc/amdgpu_smu.h 
> b/drivers/gpu/drm/amd/pm/swsmu/inc/amdgpu_smu.h
> index d396a18fe0f3..6f88c352b53e 100644
> --- a/drivers/gpu/drm/amd/pm/swsmu/inc/amdgpu_smu.h
> +++ b/drivers/gpu/drm/amd/pm/swsmu/inc/amdgpu_smu.h
> @@ -325,6 +325,7 @@ enum smu_table_id
>   SMU_TABLE_PACE,
>   SMU_TABLE_ECCINFO,
>   SMU_TABLE_COMBO_PPTABLE,
> + SMU_TABLE_WIFIBAND,
>   SMU_TABLE_COUNT,
>  };
>  
> @@ -1501,6 +1502,8 @@ enum smu_baco_seq {
>__dst_size);  \
>  })
>  
> +#define HZ_IN_MHZ100U

Don't add generic conversion constants like this into driver specific 
code. Use the one from include/linux/units.h, 

> +
>  #if !defined(SWSMU_CODE_LAYER_L2) && !defined(SWSMU_CODE_LAYER_L3) && 
> !defined(SWSMU_CODE_LAYER_L4)
>  int smu_get_power_limit(void *handle,
>   uint32_t *limit,
> diff --git a/drivers/gpu/drm/amd/pm/swsmu/inc/smu_types.h 
> b/drivers/gpu/drm/amd/pm/swsmu/inc/smu_types.h
> index 297b70b9388f..5bbb60289a79 100644
> --- a/drivers/gpu/drm/amd/pm/swsmu/inc/smu_types.h
> +++ b/drivers/gpu/drm/amd/pm/swsmu/inc/smu_types.h
> @@ -245,7 +245,8 @@
>   __SMU_DUMMY_MAP(AllowGpo),  \
>   __SMU_DUMMY_MAP(Mode2Reset),\
>   __SMU_DUMMY_MAP(RequestI2cTransaction), \
> - __SMU_DUMMY_MAP(GetMetricsTable),
> + __SMU_DUMMY_MAP(GetMetricsTable), \
> + __SMU_DUMMY_MAP(EnableUCLKShadow),
>  
>  #undef __SMU_DUMMY_MAP
>  #define __SMU_DUMMY_MAP(type)SMU_MSG_##type
> diff --git a/drivers/gpu/drm/amd/pm/swsmu/inc/smu_v13_0.h 
> b/drivers/gpu/drm/amd/pm/swsmu/inc/smu_v13_0.h
> index 355c156d871a..dd70b56aa71e 100644
> --- a/drivers/gpu/drm/amd/pm/swsmu/inc/smu_v13_0.h
> +++ b/drivers/gpu/drm/amd/pm/swsmu/inc/smu_v13_0.h
> @@ -299,5 +299,8 @@ int smu_v13_0_update_pcie_parameters(struct smu_context 
> *smu,
>uint32_t pcie_gen_cap,
>uint32_t pcie_width_cap);
>  
> +int smu_v13_0_enable_uclk_shadow(struct smu_context *smu,
> +  bool enablement);
> +
>  #endif
>  #endif
> diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0.c 
> b/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0.c
> index 9b62b45ebb7f..6a5cb582aa92 100644
> --- a/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0.c
> +++ b/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0.c
> @@ -2472,3 +2472,12 @@ int smu_v13_0_update_pcie_parameters(struct 
> smu_context *smu,
>  
>   return 0;
>  }
> +
> +int smu_v13_0_enable_uclk_shadow(struct smu_context *smu,
> +  bool enablement)
> +{
> + return smu_cmn_send_smc_msg_with_param(smu,
> +SMU_MSG_EnableUCLKShadow,
> +enablement,
> +NULL);
> +}
> diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_0_ppt.c 
> b/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_0_ppt.c
> index 0fb6be11a0cc..08ab19559c7b 100644
> --- a/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_0_ppt.c
> +++ b/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_0_ppt.c
> @@ -154,6 +154,7 @@ static struct cmn2asic_msg_mapping 
> smu_v13_0_0_message_map[SMU_MSG_MAX_COUNT] =
>   MSG_MAP(AllowGpo,   PPSMC_MSG_SetGpoAllow,  
>  0),
>   MSG_MAP(AllowIHHostInterrupt,   PPSMC_MSG_AllowIHHostInterrupt, 
>   0),
>   MSG_MAP(ReenableAcDcInterrupt,  
> PPSMC_MSG_ReenableAcDcInterrupt,   0),
> + MSG_MAP(EnableUCLKShadow,   PPSMC_MSG_EnableUCLKShadow, 
>0),
>  };
>  
>  static struct cmn2asic_mapping smu_v13_0_0_clk_map[SMU_CLK_COUNT] = {
> @@ -237,6 +238,7 @@ static struct cmn2asic_mapping 
> smu_v13_0_0_table_map[SMU_TABLE_COUNT] = {
>   TAB_MAP(I2C_COMMANDS),
>   TAB_MAP(ECCINFO),
>   TAB_MAP(OVERDRIVE),
> + TAB_MAP(WIFIBAND),
>  };
>  
>  static struct cmn2asic_mapping 
> smu_v13_0_0_pwr_src_map[SMU_POWER_SOURCE_COUNT] = {
> @@ -496,6 +498,9 @@ static int smu_v13_0_0_tables_init(struct smu_context 
> *smu)
>   PAGE_SIZE, AMDGPU_GEM_DOMAIN_VRAM);
>   SMU_TABLE_INIT(tables, SMU_TABLE_ECCINFO, sizeof(EccInfoTable_t),
>   PAGE_SIZE, AMDGPU_GEM_DOMAIN_VRAM)

Re: [PATCH v12 6/9] drm/amd/pm: setup the framework to support Wifi RFI mitigation feature

2023-10-17 Thread Ilpo Järvinen
On Tue, 17 Oct 2023, Ma Jun wrote:

> From: Evan Quan 
> 
> With WBRF feature supported, as a driver responding to the frequencies,
> amdgpu driver is able to do shadow pstate switching to mitigate possible
> interference(between its (G-)DDR memory clocks and local radio module
> frequency bands used by Wifi 6/6e/7).
> 
> Signed-off-by: Evan Quan 
> Reviewed-by: Mario Limonciello 
> Signed-off-by: Ma Jun 
> --
> v1->v2:
>   - update the prompt for feature support(Lijo)
> v8->v9:
>   - update parameter document for smu_wbrf_event_handler(Simon)
> v9->v10:
> v10->v11:
>  - correct the logics for wbrf range sorting(Lijo)
> ---
>  drivers/gpu/drm/amd/amdgpu/amdgpu.h   |   2 +
>  drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c   |  17 ++
>  drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c | 195 ++
>  drivers/gpu/drm/amd/pm/swsmu/inc/amdgpu_smu.h |  23 +++
>  drivers/gpu/drm/amd/pm/swsmu/smu_internal.h   |   3 +
>  5 files changed, 240 insertions(+)
> 
> diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu.h 
> b/drivers/gpu/drm/amd/amdgpu/amdgpu.h
> index 6dc950c1b689..11a19384df56 100644
> --- a/drivers/gpu/drm/amd/amdgpu/amdgpu.h
> +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu.h
> @@ -247,6 +247,8 @@ extern int amdgpu_sg_display;
>  
>  extern int amdgpu_user_partt_mode;
>  
> +extern int amdgpu_wbrf;
> +
>  #define AMDGPU_VM_MAX_NUM_CTX4096
>  #define AMDGPU_SG_THRESHOLD  (256*1024*1024)
>  #define AMDGPU_WAIT_IDLE_TIMEOUT_IN_MS   3000
> diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c 
> b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c
> index 0593ef8fe0a6..1c574bd3b60d 100644
> --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c
> +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c
> @@ -195,6 +195,7 @@ int amdgpu_use_xgmi_p2p = 1;
>  int amdgpu_vcnfw_log;
>  int amdgpu_sg_display = -1; /* auto */
>  int amdgpu_user_partt_mode = AMDGPU_AUTO_COMPUTE_PARTITION_MODE;
> +int amdgpu_wbrf = -1;
>  
>  static void amdgpu_drv_delayed_reset_work_handler(struct work_struct *work);
>  
> @@ -981,6 +982,22 @@ module_param_named(user_partt_mode, 
> amdgpu_user_partt_mode, uint, 0444);
>  module_param(enforce_isolation, bool, 0444);
>  MODULE_PARM_DESC(enforce_isolation, "enforce process isolation between 
> graphics and compute . enforce_isolation = on");
>  
> +/**
> + * DOC: wbrf (int)
> + * Enable Wifi RFI interference mitigation feature.
> + * Due to electrical and mechanical constraints there may be likely 
> interference of
> + * relatively high-powered harmonics of the (G-)DDR memory clocks with local 
> radio
> + * module frequency bands used by Wifi 6/6e/7. To mitigate the possible RFI 
> interference,
> + * with this feature enabled, PMFW will use either “shadowed P-State” or 
> “P-State” based
> + * on active list of frequencies in-use (to be avoided) as part of initial 
> setting or
> + * P-state transition. However, there may be potential performance impact 
> with this
> + * feature enabled.
> + * (0 = disabled, 1 = enabled, -1 = auto (default setting, will be enabled 
> if supported))
> + */
> +MODULE_PARM_DESC(wbrf,
> + "Enable Wifi RFI interference mitigation (0 = disabled, 1 = enabled, -1 
> = auto(default)");
> +module_param_named(wbrf, amdgpu_wbrf, int, 0444);
> +
>  /* These devices are not supported by amdgpu.
>   * They are supported by the mach64, r128, radeon drivers
>   */
> diff --git a/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c 
> b/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c
> index 222af2fae745..d52cd7ed2868 100644
> --- a/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c
> +++ b/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c
> @@ -1228,6 +1228,174 @@ static int smu_get_thermal_temperature_range(struct 
> smu_context *smu)
>   return ret;
>  }
>  
> +/**
> + * smu_wbrf_handle_exclusion_ranges - consume the wbrf exclusion ranges
> + *
> + * @smu: smu_context pointer
> + *
> + * Retrieve the wbrf exclusion ranges and send them to PMFW for proper 
> handling.
> + * Returns 0 on success, error on failure.
> + */
> +static int smu_wbrf_handle_exclusion_ranges(struct smu_context *smu)
> +{
> + struct wbrf_ranges_in_out wbrf_exclusion = {0};
> + struct freq_band_range *wifi_bands = wbrf_exclusion.band_list;
> + struct amdgpu_device *adev = smu->adev;
> + uint32_t num_of_wbrf_ranges = MAX_NUM_OF_WBRF_RANGES;
> + uint64_t start, end;
> + int ret, i, j;
> +
> + ret = amd_wbrf_retrieve_freq_band(adev->dev, &wbrf_exclusion);
> + if (ret) {
> + dev_err(adev->dev, "Failed to retrieve exclusion ranges!\n");
> + return ret;
> + }
> +
> + /*
> +  * The exclusion ranges array we got might be filled with holes and 
> duplicate
> +  * entries. For example:
> +  * {(2400, 2500), (0, 0), (6882, 6962), (2400, 2500), (0, 0), (6117, 
> 6189), (0, 0)...}
> +  * We need to do some sortups to eliminate those holes and duplicate 
> entries.
> +  * Expected output: {(2400, 2500), (6117, 6189), (6882, 69

Re: [PATCH v12 9/9] drm/amd/pm: enable Wifi RFI mitigation feature support for SMU13.0.7

2023-10-17 Thread Ilpo Järvinen
On Tue, 17 Oct 2023, Ma Jun wrote:

> From: Evan Quan 
> 
> Fulfill the SMU13.0.7 support for Wifi RFI mitigation feature.
> 
> Signed-off-by: Evan Quan 
> Reviewed-by: Mario Limonciello 
> Signed-off-by: Ma Jun 
> --
> v10->v11:
>   - downgrade the prompt level on message failure(Lijo)
> ---
>  .../drm/amd/pm/swsmu/smu13/smu_v13_0_7_ppt.c  | 59 +++
>  1 file changed, 59 insertions(+)
> 
> diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_7_ppt.c 
> b/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_7_ppt.c
> index 62f2886ab4df..c5736fb3cf6d 100644
> --- a/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_7_ppt.c
> +++ b/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_7_ppt.c
> @@ -126,6 +126,7 @@ static struct cmn2asic_msg_mapping 
> smu_v13_0_7_message_map[SMU_MSG_MAX_COUNT] =
>   MSG_MAP(AllowGpo,   PPSMC_MSG_SetGpoAllow,  
>  0),
>   MSG_MAP(GetPptLimit,PPSMC_MSG_GetPptLimit,  
>0),
>   MSG_MAP(NotifyPowerSource,  PPSMC_MSG_NotifyPowerSource,
>0),
> + MSG_MAP(EnableUCLKShadow,   PPSMC_MSG_EnableUCLKShadow, 
>0),
>  };
>  
>  static struct cmn2asic_mapping smu_v13_0_7_clk_map[SMU_CLK_COUNT] = {
> @@ -207,6 +208,7 @@ static struct cmn2asic_mapping 
> smu_v13_0_7_table_map[SMU_TABLE_COUNT] = {
>   TAB_MAP(ACTIVITY_MONITOR_COEFF),
>   [SMU_TABLE_COMBO_PPTABLE] = {1, TABLE_COMBO_PPTABLE},
>   TAB_MAP(OVERDRIVE),
> + TAB_MAP(WIFIBAND),
>  };
>  
>  static struct cmn2asic_mapping 
> smu_v13_0_7_pwr_src_map[SMU_POWER_SOURCE_COUNT] = {
> @@ -503,6 +505,9 @@ static int smu_v13_0_7_tables_init(struct smu_context 
> *smu)
>  AMDGPU_GEM_DOMAIN_VRAM);
>   SMU_TABLE_INIT(tables, SMU_TABLE_COMBO_PPTABLE, 
> MP0_MP1_DATA_REGION_SIZE_COMBOPPTABLE,
>   PAGE_SIZE, AMDGPU_GEM_DOMAIN_VRAM);
> + SMU_TABLE_INIT(tables, SMU_TABLE_WIFIBAND,
> +sizeof(WifiBandEntryTable_t), PAGE_SIZE,
> +AMDGPU_GEM_DOMAIN_VRAM);
>  
>   smu_table->metrics_table = kzalloc(sizeof(SmuMetricsExternal_t), 
> GFP_KERNEL);
>   if (!smu_table->metrics_table)
> @@ -2179,6 +2184,57 @@ static int smu_v13_0_7_set_df_cstate(struct 
> smu_context *smu,
>  NULL);
>  }
>  
> +static bool smu_v13_0_7_wbrf_support_check(struct smu_context *smu)
> +{
> + return smu->smc_fw_version > 0x00524600;
> +}
> +
> +static int smu_v13_0_7_set_wbrf_exclusion_ranges(struct smu_context *smu,
> +  struct freq_band_range 
> *exclusion_ranges)
> +{
> + WifiBandEntryTable_t wifi_bands;
> + int valid_entries = 0;
> + int ret, i;
> +
> + memset(&wifi_bands, 0, sizeof(wifi_bands));
> + for (i = 0; i < ARRAY_SIZE(wifi_bands.WifiBandEntry); i++) {
> + if (!exclusion_ranges[i].start &&
> + !exclusion_ranges[i].end)

After having seen this construct nth time, I think you should have a 
static inline function for this check with a proper name.

> + break;
> +
> + /* PMFW expects the inputs to be in Mhz unit */
> + wifi_bands.WifiBandEntry[valid_entries].LowFreq =
> + DIV_ROUND_DOWN_ULL(exclusion_ranges[i].start, 
> HZ_IN_MHZ);
> + wifi_bands.WifiBandEntry[valid_entries++].HighFreq =
> + DIV_ROUND_UP_ULL(exclusion_ranges[i].end, HZ_IN_MHZ);
> + }
> + wifi_bands.WifiBandEntryNum = valid_entries;
> +
> + /*
> +  * Per confirm with PMFW team, WifiBandEntryNum = 0 is a valid setting.
> +  * Considering the scenarios below:
> +  * - At first the wifi device adds an exclusion range e.g. (2400,2500) 
> to
> +  *   BIOS and our driver gets notified. We will set WifiBandEntryNum = 1
> +  *   and pass the WifiBandEntry (2400, 2500) to PMFW.
> +  *
> +  * - Later the wifi device removes the wifiband list added above and
> +  *   our driver gets notified again. At this time, driver will set
> +  *   WifiBandEntryNum = 0 and pass an empty WifiBandEntry list to PMFW.
> +  *   - PMFW may still need to do some uclk shadow update(e.g. switching
> +  * from shadow clock back to primary clock) on receiving this.
> +  */
> +
> + ret = smu_cmn_update_table(smu,
> +SMU_TABLE_WIFIBAND,
> +0,
> +(void *)(&wifi_bands),
> +true);
> + if (ret)
> + dev_warn(smu->adev->dev, "Failed to set wifiband!");
> +
> + return ret;
> +}

Is this whole function duplicate of the one in the other file? Don't 
duplicate code like this but create reusable functions properly.

-- 
 i.

> +
>  static const struct pptable_funcs smu_v13_0_7_ppt_funcs = {
>   .get_allowed_feature_mask = smu_v13_0_7_get_allowed_feature_mask,
>   .set_default

Re: [PATCH v12 2/9] platform/x86/amd: Add support for AMD ACPI based Wifi band RFI mitigation feature

2023-10-17 Thread Ilpo Järvinen
On Tue, 17 Oct 2023, Ma Jun wrote:

> Due to electrical and mechanical constraints in certain platform designs
> there may be likely interference of relatively high-powered harmonics of
> the (G-)DDR memory clocks with local radio module frequency bands used
> by Wifi 6/6e/7.
> 
> To mitigate this, AMD has introduced a mechanism that devices can use to
> notify active use of particular frequencies so that other devices can make
> relative internal adjustments as necessary to avoid this resonance.
> 
> Co-Developed-by: Evan Quan 
> Signed-off-by: Evan Quan 
> Signed-off-by: Ma Jun 
> 
> --
> v11:
>  - fix typo(Simon)
> v12:
>  - Fix the code (Rafael)
>  - Move amd_wbrf.c to drivers/platform/x86/amd/wbrf.c
>  - Updated Evan's email because he's no longer at AMD.Thanks
> for his work in earlier versions.
> ---
>  drivers/platform/x86/amd/Kconfig  |  15 ++
>  drivers/platform/x86/amd/Makefile |   1 +
>  drivers/platform/x86/amd/wbrf.c   | 402 ++
>  include/linux/acpi_amd_wbrf.h | 101 
>  4 files changed, 519 insertions(+)
>  create mode 100644 drivers/platform/x86/amd/wbrf.c
>  create mode 100644 include/linux/acpi_amd_wbrf.h
> 
> diff --git a/drivers/platform/x86/amd/Kconfig 
> b/drivers/platform/x86/amd/Kconfig
> index d9685aef0887..fa5a978a2d22 100644
> --- a/drivers/platform/x86/amd/Kconfig
> +++ b/drivers/platform/x86/amd/Kconfig
> @@ -32,3 +32,18 @@ config AMD_HSMP
>  
> If you choose to compile this driver as a module the module will be
> called amd_hsmp.
> +
> +config AMD_WBRF
> + bool "AMD Wifi RF Band mitigations (WBRF)"
> + depends on ACPI
> + default n
> + help
> +   WBRF(Wifi Band RFI mitigation) mechanism allows Wifi drivers
> +   to notify the frequencies they are using so that other hardware
> +   can be reconfigured to avoid harmonic conflicts.
> +
> +   AMD provides an ACPI based mechanism to support WBRF on platform with
> +   appropriate underlying support.
> +
> +   This mechanism will only be activated on platforms that advertise a
> +   need for it.
> diff --git a/drivers/platform/x86/amd/Makefile 
> b/drivers/platform/x86/amd/Makefile
> index 65732f0a3913..62b98b048b17 100644
> --- a/drivers/platform/x86/amd/Makefile
> +++ b/drivers/platform/x86/amd/Makefile
> @@ -9,3 +9,4 @@ obj-$(CONFIG_AMD_PMC) += amd-pmc.o
>  amd_hsmp-y   := hsmp.o
>  obj-$(CONFIG_AMD_HSMP)   += amd_hsmp.o
>  obj-$(CONFIG_AMD_PMF)+= pmf/
> +obj-$(CONFIG_AMD_WBRF)   += wbrf.o
> diff --git a/drivers/platform/x86/amd/wbrf.c b/drivers/platform/x86/amd/wbrf.c
> new file mode 100644
> index ..fb414564f576
> --- /dev/null
> +++ b/drivers/platform/x86/amd/wbrf.c
> @@ -0,0 +1,402 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * Wifi Frequency Band Manage Interface
> + * Copyright (C) 2023 Advanced Micro Devices
> + */
> +
> +#include 
> +#include 
> +
> +#define ACPI_AMD_WBRF_METHOD "\\WBRF"
> +
> +/*
> + * Functions bit vector for WBRF method
> + *
> + * Bit 0: WBRF supported.
> + * Bit 1: Function 1 (Add / Remove frequency) is supported.
> + * Bit 2: Function 2 (Get frequency list) is supported.
> + */
> +#define WBRF_ENABLED 0x0
> +#define WBRF_RECORD  0x1
> +#define WBRF_RETRIEVE0x2
> +
> +#define WBRF_REVISION0x1
> +
> +/*
> + * The data structure used for WBRF_RETRIEVE is not naturally aligned.
> + * And unfortunately the design has been settled down.
> + */
> +struct amd_wbrf_ranges_out {
> + u32 num_of_ranges;
> + struct freq_band_range  band_list[MAX_NUM_OF_WBRF_RANGES];
> +} __packed;
> +
> +static const guid_t wifi_acpi_dsm_guid =
> + GUID_INIT(0x7b7656cf, 0xdc3d, 0x4c1c,
> +   0x83, 0xe9, 0x66, 0xe7, 0x21, 0xde, 0x30, 0x70);
> +
> +/*
> + * Used to notify consumer (amdgpu driver currently) about
> + * the wifi frequency is change.
> + */
> +static BLOCKING_NOTIFIER_HEAD(wbrf_chain_head);
> +
> +static int wbrf_record(struct acpi_device *adev, uint8_t action,
> +struct wbrf_ranges_in_out *in)
> +{
> + union acpi_object argv4;
> + union acpi_object *tmp;
> + union acpi_object *obj;
> + u32 num_of_ranges = 0;
> + u32 num_of_elements;
> + u32 arg_idx = 0;
> + u32 loop_idx;
> + int ret;
> +
> + if (!in)
> + return -EINVAL;
> +
> + /*
> +  * The num_of_ranges value in the "in" object supplied by
> +  * the caller is required to be equal to the number of
> +  * entries in the band_list array in there.
> +  */
> + for (loop_idx = 0; loop_idx < ARRAY_SIZE(in->band_list);
> +  loop_idx++)

This fits easily to one line.

What extra information loop_idx provides over the usual i? I see zero 
extra value, only extra characters.

> + if (in->band_list[loop_idx].start &&
> + in->band_list[loop_idx].end)

One line.

> +

Re: [PATCH v12 4/9] wifi: mac80211: Add support for WBRF features

2023-10-17 Thread Ilpo Järvinen
On Tue, 17 Oct 2023, Ma Jun wrote:

> From: Evan Quan 
> 
> To support the WBRF mechanism, Wifi adapters utilized in the system must
> register the frequencies in use(or unregister those frequencies no longer

Space is missing.

-- 
 i.



Re: [PATCH v12 3/9] cfg80211: expose nl80211_chan_width_to_mhz for wide sharing

2023-10-17 Thread Ilpo Järvinen
On Tue, 17 Oct 2023, Ma Jun wrote:

> From: Evan Quan 
> 
> The newly added WBRF feature needs this interface for channel
> width calculation.
> 
> Signed-off-by: Ma Jun 
> Signed-off-by: Evan Quan 
> 
> --
> v8->v9:
>   - correct typo(Mhz -> MHz) (Johnson)
> ---
>  include/net/cfg80211.h | 8 
>  net/wireless/chan.c| 3 ++-
>  2 files changed, 10 insertions(+), 1 deletion(-)
> 
> diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
> index d6fa7c8767ad..026d91083f37 100644
> --- a/include/net/cfg80211.h
> +++ b/include/net/cfg80211.h
> @@ -923,6 +923,14 @@ const struct cfg80211_chan_def *
>  cfg80211_chandef_compatible(const struct cfg80211_chan_def *chandef1,
>   const struct cfg80211_chan_def *chandef2);
>  
> +/**
> + * nl80211_chan_width_to_mhz - get the channel width in MHz
> + * @chan_width: the channel width from &enum nl80211_chan_width
> + * Return: channel width in MHz if the chan_width from &enum 
> nl80211_chan_width
> + * is valid. -1 otherwise.

Add empty line before Return:

> + */
> +int nl80211_chan_width_to_mhz(enum nl80211_chan_width chan_width);
> +
>  /**
>   * cfg80211_chandef_valid - check if a channel definition is valid
>   * @chandef: the channel definition to check
> diff --git a/net/wireless/chan.c b/net/wireless/chan.c
> index 0b7e81db383d..227db04eac42 100644
> --- a/net/wireless/chan.c
> +++ b/net/wireless/chan.c
> @@ -141,7 +141,7 @@ static bool cfg80211_edmg_chandef_valid(const struct 
> cfg80211_chan_def *chandef)
>   return true;
>  }
>  
> -static int nl80211_chan_width_to_mhz(enum nl80211_chan_width chan_width)
> +int nl80211_chan_width_to_mhz(enum nl80211_chan_width chan_width)
>  {
>   int mhz;
>  
> @@ -190,6 +190,7 @@ static int nl80211_chan_width_to_mhz(enum 
> nl80211_chan_width chan_width)
>   }
>   return mhz;
>  }
> +EXPORT_SYMBOL(nl80211_chan_width_to_mhz);
>  
>  static int cfg80211_chandef_get_width(const struct cfg80211_chan_def *c)
>  {
> 

-- 
 i.



Re: [PATCH v12 1/9] Documentation/driver-api: Add document about WBRF mechanism

2023-10-17 Thread Ilpo Järvinen
On Tue, 17 Oct 2023, Ma Jun wrote:

> Add documentation about AMD's Wifi band RFI mitigation (WBRF) mechanism
> explaining the theory and how it is used.
> 
> Signed-off-by: Ma Jun 
> ---
>  Documentation/driver-api/wbrf.rst | 73 +++
>  1 file changed, 73 insertions(+)
>  create mode 100644 Documentation/driver-api/wbrf.rst
> 
> diff --git a/Documentation/driver-api/wbrf.rst 
> b/Documentation/driver-api/wbrf.rst
> new file mode 100644
> index ..8561840263b3
> --- /dev/null
> +++ b/Documentation/driver-api/wbrf.rst
> @@ -0,0 +1,73 @@
> +.. SPDX-License-Identifier: GPL-2.0-or-later
> +
> +=
> +WBRF - Wifi Band RFI Mitigations
> +=
> +Due to electrical and mechanical constraints in certain platform designs

Add empty line before starting the content of a section.

> +there may be likely interference of relatively high-powered harmonics of
> +the GPU memory clocks with local radio module frequency bands used by
> +certain Wifi bands.
> +
> +To mitigate possible RFI interference producers can advertise the
> +frequencies in use and consumers can use this information to avoid using
> +these frequencies for sensitive features.
> +
> +When a platform is known to have this issue with any contained devices,
> +the platform designer will advertise the availability of this feature via
> +ACPI devices with a device specific method (_DSM).
> +* Producers with this _DSM will be able to advertise the frequencies in use.
> +* Consumers with this _DSM will be able to register for notifications of
> +frequencies in use.
> +
> +Some general terms
> +==
> +Producer: such component who can produce high-powered radio frequency
> +Consumer: such component who can adjust its in-use frequency in
> +   response to the radio frequencies of other components to
> +   mitigate the possible RFI.
> +
> +To make the mechanism function, those producers should notify active use
> +of their particular frequencies so that other consumers can make relative
> +internal adjustments as necessary to avoid this resonance.
> +
> +ACPI interface
> +==
> +Although initially used by for wifi + dGPU use cases, the ACPI interface
> +can be scaled to any type of device that a platform designer discovers
> +can cause interference.
> +
> +The GUID used for the _DSM is 7B7656CF-DC3D-4C1C-83E9-66E721DE3070.
> +
> +3 functions are available in this _DSM:
> +
> +* 0: discover # of functions available
> +* 1: record RF bands in use
> +* 2: retrieve RF bands in use
> +
> +Driver programming interface
> +
> +.. kernel-doc:: drivers/platform/x86/amd/wbrf.c
> +
> +Sample Usage
> +=
> +The expected flow for the producers:
> +1) During probe, call `acpi_amd_wbrf_supported_producer` to check if WBRF
> +can be enabled for the device.
> +2) On using some frequency band, call `acpi_amd_wbrf_add_remove` with 'add'
> +param to get other consumers properly notified.
> +3) Or on stopping using some frequency band, call
> +`acpi_amd_wbrf_add_remove` with 'remove' param to get other consumers 
> notified.
> +
> +The expected flow for the consumers:
> +1) During probe, call `acpi_amd_wbrf_supported_consumer` to check if WBRF
> +can be enabled for the device.
> +2) Call `amd_wbrf_register_notifier` to register for notification
> +of frequency band change(add or remove) from other producers.
> +3) Call the `amd_wbrf_retrieve_freq_band` intentionally to retrieve
> +current active frequency bands considering some producers may broadcast
> +such information before the consumer is up.
> +4) On receiving a notification for frequency band change, run
> +`amd_wbrf_retrieve_freq_band` again to retrieve the latest
> +active frequency bands.
> +5) During driver cleanup, call `amd_wbrf_unregister_notifier` to
> +unregister the notifier.

Align these so that only the numbers start from first column. I think the 
proper markup for numbered lists is 1. not 1).


-- 
 i.



Re: [PATCH v12 4/9] wifi: mac80211: Add support for WBRF features

2023-10-17 Thread Ilpo Järvinen
On Tue, 17 Oct 2023, Ma Jun wrote:

> From: Evan Quan 
> 
> To support the WBRF mechanism, Wifi adapters utilized in the system must
> register the frequencies in use(or unregister those frequencies no longer
> used) via the dedicated calls. So that, other drivers responding to the
> frequencies can take proper actions to mitigate possible interference.
> 
> Co-developed-by: Mario Limonciello 
> Signed-off-by: Mario Limonciello 
> Co-developed-by: Evan Quan 
> Signed-off-by: Evan Quan 
> Signed-off-by: Ma Jun 
> --
> v1->v2:
>   - place the new added member(`wbrf_supported`) in
> ieee80211_local(Johannes)
>   - handle chandefs change scenario properly(Johannes)
>   - some minor fixes around code sharing and possible invalid input
> checks(Johannes)
> v2->v3:
>   - drop unnecessary input checks and intermediate APIs(Mario)
>   - Separate some mac80211 common code(Mario, Johannes)
> v3->v4:
>   - some minor fixes around return values(Johannes)
> v9->v10:
>   - get ranges_in->num_of_ranges set and passed in(Johannes)
> v12:
>   - use acpi_amd_wbrf_add_remove to replace the acpi_amd_wbrf_add_exclusion
> acpi_amd_wbrf_remove_exclusion
> ---
>  include/linux/ieee80211.h  |   1 +
>  net/mac80211/Makefile  |   2 +
>  net/mac80211/chan.c|   9 
>  net/mac80211/ieee80211_i.h |   9 
>  net/mac80211/main.c|   2 +
>  net/mac80211/wbrf.c| 105 +
>  6 files changed, 128 insertions(+)
>  create mode 100644 net/mac80211/wbrf.c
> 
> diff --git a/include/linux/ieee80211.h b/include/linux/ieee80211.h
> index 4b998090898e..f995d06da87f 100644
> --- a/include/linux/ieee80211.h
> +++ b/include/linux/ieee80211.h
> @@ -4335,6 +4335,7 @@ static inline int ieee80211_get_tdls_action(struct 
> sk_buff *skb, u32 hdr_size)
>  /* convert frequencies */
>  #define MHZ_TO_KHZ(freq) ((freq) * 1000)
>  #define KHZ_TO_MHZ(freq) ((freq) / 1000)
> +#define KHZ_TO_HZ(freq)  ((freq) * 1000)

It would be better to not add more of these per subsystem but use the 
generic include/linux/units.h constants instead.

>  #define PR_KHZ(f) KHZ_TO_MHZ(f), f % 1000
>  #define KHZ_F "%d.%03d"
>  
> diff --git a/net/mac80211/Makefile b/net/mac80211/Makefile
> index b8de44da1fb8..d46c36f55fd3 100644
> --- a/net/mac80211/Makefile
> +++ b/net/mac80211/Makefile
> @@ -65,4 +65,6 @@ rc80211_minstrel-$(CONFIG_MAC80211_DEBUGFS) += \
>  
>  mac80211-$(CONFIG_MAC80211_RC_MINSTREL) += $(rc80211_minstrel-y)
>  
> +mac80211-y += wbrf.o
> +
>  ccflags-y += -DDEBUG
> diff --git a/net/mac80211/chan.c b/net/mac80211/chan.c
> index 68952752b599..458469c224ae 100644
> --- a/net/mac80211/chan.c
> +++ b/net/mac80211/chan.c
> @@ -506,11 +506,16 @@ static void _ieee80211_change_chanctx(struct 
> ieee80211_local *local,
>  
>   WARN_ON(!cfg80211_chandef_compatible(&ctx->conf.def, chandef));
>  
> + ieee80211_remove_wbrf(local, &ctx->conf.def);
> +
>   ctx->conf.def = *chandef;
>  
>   /* check if min chanctx also changed */
>   changed = IEEE80211_CHANCTX_CHANGE_WIDTH |
> _ieee80211_recalc_chanctx_min_def(local, ctx, rsvd_for);
> +
> + ieee80211_add_wbrf(local, &ctx->conf.def);
> +
>   drv_change_chanctx(local, ctx, changed);
>  
>   if (!local->use_chanctx) {
> @@ -668,6 +673,8 @@ static int ieee80211_add_chanctx(struct ieee80211_local 
> *local,
>   lockdep_assert_held(&local->mtx);
>   lockdep_assert_held(&local->chanctx_mtx);
>  
> + ieee80211_add_wbrf(local, &ctx->conf.def);
> +
>   if (!local->use_chanctx)
>   local->hw.conf.radar_enabled = ctx->conf.radar_enabled;
>  
> @@ -748,6 +755,8 @@ static void ieee80211_del_chanctx(struct ieee80211_local 
> *local,
>   }
>  
>   ieee80211_recalc_idle(local);
> +
> + ieee80211_remove_wbrf(local, &ctx->conf.def);
>  }
>  
>  static void ieee80211_free_chanctx(struct ieee80211_local *local,
> diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h
> index 91633a0b723e..719f2c892132 100644
> --- a/net/mac80211/ieee80211_i.h
> +++ b/net/mac80211/ieee80211_i.h
> @@ -1600,6 +1600,8 @@ struct ieee80211_local {
>  
>   /* extended capabilities provided by mac80211 */
>   u8 ext_capa[8];
> +
> + bool wbrf_supported;
>  };
>  
>  static inline struct ieee80211_sub_if_data *
> @@ -2638,4 +2640,11 @@ ieee80211_eht_cap_ie_to_sta_eht_cap(struct 
> ieee80211_sub_if_data *sdata,
>   const struct ieee80211_eht_cap_elem 
> *eht_cap_ie_elem,
>   u8 eht_cap_len,
>   struct link_sta_info *link_sta);
> +
> +void ieee80211_check_wbrf_support(struct ieee80211_local *local);
> +void ieee80211_add_wbrf(struct ieee80211_local *local,
> + struct cfg80211_chan_def *chandef);
> +void ieee80211_remove_wbrf(struct ieee80211_local *local,
> +struct cfg80211_chan_def *chandef);
> +
>  #endif /* IEEE80211_I_H */
> diff --git a/net/mac80211/m

Re: [PATCH v4 13/17] platform/x86/amd/pmf: Add PMF-AMDGPU get interface

2023-10-18 Thread Ilpo Järvinen
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 
> >> Signed-off-by: Mario Limonciello 
> >> Signed-off-by: Shyam Sundar S K 
> >> ---
> >>  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 
> >>  #include 
> >>  #include 
> >> +#include 
> >>  
> >>  #include 
> >>  #include 
> >> 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 ..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 
> >> + *
> >> + */
> > 
> > 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.


Re: [PATCH v4 11/17] platform/x86/amd/pmf: Add capability to sideload of policy binary

2023-10-18 Thread Ilpo Järvinen
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 
> Signed-off-by: Shyam Sundar S K 
> ---
>  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 
>   */
>  
> +#include 
>  #include 
>  #include 
>  #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);
> 


Re: [PATCH v4 12/17] platform/x86/amd/pmf: dump policy binary data

2023-10-18 Thread Ilpo Järvinen
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 
> Signed-off-by: Shyam Sundar S K 
> ---
>  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 

-- 
 i.


Re: [PATCH v4 10/17] platform/x86/amd/pmf: Add facility to dump TA inputs

2023-10-18 Thread Ilpo Järvinen
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 
> Signed-off-by: Shyam Sundar S K 
> ---
>  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 
>  #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);
> 


Re: [PATCH v4 16/17] platform/x86/amd/pmf: Add PMF-AMDSFH interface for HPD

2023-10-18 Thread Ilpo Järvinen
On Wed, 18 Oct 2023, Shyam Sundar S K wrote:

> From: Basavaraj Natikar 
> 
> 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 
> Signed-off-by: Shyam Sundar S K 
> Signed-off-by: Basavaraj Natikar 
> ---
>  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 
>   */
> +#include 
>  #include 
>  #include 
>  
>  #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
> 

Re: [PATCH v4 13/17] platform/x86/amd/pmf: Add PMF-AMDGPU get interface

2023-10-18 Thread Ilpo Järvinen
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 
> Signed-off-by: Mario Limonciello 
> Signed-off-by: Shyam Sundar S K 
> ---
>  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 
>  #include 
>  #include 
> +#include 
>  
>  #include 
>  #include 
> 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 ..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 
> + *
> + */

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

> +
> +#include 
> +#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_g

Re: [PATCH v4 15/17] HID: amd_sfh: rename float_to_int() to amd_sfh_float_to_int()

2023-10-18 Thread Ilpo Järvinen
s_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 

-- 
 i.


Re: [Patch v13 4/9] wifi: mac80211: Add support for WBRF features

2023-11-02 Thread Ilpo Järvinen
On Thu, 2 Nov 2023, Johannes Berg wrote:
> On Thu, 2023-11-02 at 13:55 +0200, Ilpo Järvinen wrote:
> 
> > > +static void get_chan_freq_boundary(u32 center_freq, u32 bandwidth, u64 
> > > *start, u64 *end)
> > > +{
> > > + bandwidth = MHZ_TO_KHZ(bandwidth);
> > > + center_freq = MHZ_TO_KHZ(center_freq);
> > 
> > Please use include/linux/units.h ones for these too.
> 
> Now we're feature creeping though - this has existed for *years* in the
> wireless stack with many instances? We can convert them over, I guess,
> but not sure that makes much sense here - we'd want to add such macros
> to units.h, but ... moving them can be independent of this patch?

What new macros you're talking about? Nothing new needs to be added 
as there's already KHZ_PER_MHZ so these would just be:

bandwidth *= KHZ_PER_MHZ;
center_freq *= KHZ_PER_MHZ;

Everything can of course be postponed by the argument that some 
subsystem specific mechanism has been there before the generic one
but the end of that road won't be pretty... What I was trying to do
here was to point out the new stuff introduced by this series into the 
direction of the generic thing.

-- 
 i.

Re: [Patch v13 4/9] wifi: mac80211: Add support for WBRF features

2023-11-02 Thread Ilpo Järvinen
On Mon, 30 Oct 2023, Ma Jun wrote:

> From: Evan Quan 
> 
> To support the WBRF mechanism, Wifi adapters utilized in the system must
> register the frequencies in use (or unregister those frequencies no longer
> used) via the dedicated calls. So that, other drivers responding to the
> frequencies can take proper actions to mitigate possible interference.
> 
> Co-developed-by: Mario Limonciello 
> Signed-off-by: Mario Limonciello 
> Co-developed-by: Evan Quan 
> Signed-off-by: Evan Quan 
> Signed-off-by: Ma Jun 
> --
> v1->v2:
>   - place the new added member(`wbrf_supported`) in
> ieee80211_local(Johannes)
>   - handle chandefs change scenario properly(Johannes)
>   - some minor fixes around code sharing and possible invalid input
> checks(Johannes)
> v2->v3:
>   - drop unnecessary input checks and intermediate APIs(Mario)
>   - Separate some mac80211 common code(Mario, Johannes)
> v3->v4:
>   - some minor fixes around return values(Johannes)
> v9->v10:
>   - get ranges_in->num_of_ranges set and passed in(Johannes)
> v12:
>   - use acpi_amd_wbrf_add_remove to replace the acpi_amd_wbrf_add_exclusion
> acpi_amd_wbrf_remove_exclusion
> v13:
>   - Fix the format issue (IIpo Jarvinen)
>   - Remove KHZ_TO_HZ and use HZ_PER_KHZ in linux/units.h (IIpo Jarvinen)
> ---
>  net/mac80211/Makefile  |  2 +
>  net/mac80211/chan.c|  9 
>  net/mac80211/ieee80211_i.h |  7 +++
>  net/mac80211/main.c|  2 +
>  net/mac80211/wbrf.c| 95 ++
>  5 files changed, 115 insertions(+)
>  create mode 100644 net/mac80211/wbrf.c
> 
> diff --git a/net/mac80211/Makefile b/net/mac80211/Makefile
> index b8de44da1fb8..d46c36f55fd3 100644
> --- a/net/mac80211/Makefile
> +++ b/net/mac80211/Makefile
> @@ -65,4 +65,6 @@ rc80211_minstrel-$(CONFIG_MAC80211_DEBUGFS) += \
>  
>  mac80211-$(CONFIG_MAC80211_RC_MINSTREL) += $(rc80211_minstrel-y)
>  
> +mac80211-y += wbrf.o
> +
>  ccflags-y += -DDEBUG
> diff --git a/net/mac80211/chan.c b/net/mac80211/chan.c
> index 68952752b599..458469c224ae 100644
> --- a/net/mac80211/chan.c
> +++ b/net/mac80211/chan.c
> @@ -506,11 +506,16 @@ static void _ieee80211_change_chanctx(struct 
> ieee80211_local *local,
>  
>   WARN_ON(!cfg80211_chandef_compatible(&ctx->conf.def, chandef));
>  
> + ieee80211_remove_wbrf(local, &ctx->conf.def);
> +
>   ctx->conf.def = *chandef;
>  
>   /* check if min chanctx also changed */
>   changed = IEEE80211_CHANCTX_CHANGE_WIDTH |
> _ieee80211_recalc_chanctx_min_def(local, ctx, rsvd_for);
> +
> + ieee80211_add_wbrf(local, &ctx->conf.def);
> +
>   drv_change_chanctx(local, ctx, changed);
>  
>   if (!local->use_chanctx) {
> @@ -668,6 +673,8 @@ static int ieee80211_add_chanctx(struct ieee80211_local 
> *local,
>   lockdep_assert_held(&local->mtx);
>   lockdep_assert_held(&local->chanctx_mtx);
>  
> + ieee80211_add_wbrf(local, &ctx->conf.def);
> +
>   if (!local->use_chanctx)
>   local->hw.conf.radar_enabled = ctx->conf.radar_enabled;
>  
> @@ -748,6 +755,8 @@ static void ieee80211_del_chanctx(struct ieee80211_local 
> *local,
>   }
>  
>   ieee80211_recalc_idle(local);
> +
> + ieee80211_remove_wbrf(local, &ctx->conf.def);
>  }
>  
>  static void ieee80211_free_chanctx(struct ieee80211_local *local,
> diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h
> index 98ef1fe1226e..1172554bd831 100644
> --- a/net/mac80211/ieee80211_i.h
> +++ b/net/mac80211/ieee80211_i.h
> @@ -1600,6 +1600,8 @@ struct ieee80211_local {
>  
>   /* extended capabilities provided by mac80211 */
>   u8 ext_capa[8];
> +
> + bool wbrf_supported;
>  };
>  
>  static inline struct ieee80211_sub_if_data *
> @@ -2637,4 +2639,9 @@ ieee80211_eht_cap_ie_to_sta_eht_cap(struct 
> ieee80211_sub_if_data *sdata,
>   const struct ieee80211_eht_cap_elem 
> *eht_cap_ie_elem,
>   u8 eht_cap_len,
>   struct link_sta_info *link_sta);
> +
> +void ieee80211_check_wbrf_support(struct ieee80211_local *local);
> +void ieee80211_add_wbrf(struct ieee80211_local *local, struct 
> cfg80211_chan_def *chandef);
> +void ieee80211_remove_wbrf(struct ieee80211_local *local, struct 
> cfg80211_chan_def *chandef);
> +
>  #endif /* IEEE80211_I_H */
> diff --git a/net/mac80211/main.c b/net/mac80211/main.c
> index 24315d7b3126..b20bdaac84db 100644
> --- a/net/mac80211/main.c
> +++ b/net/mac80211/main.c
> @@ -1396,6 +1396,8 @@ int ieee80211_register_hw(struct ieee80211_hw *hw)
>   debugfs_hw_add(local);
>   rate_control_add_debugfs(local);
>  
> + ieee80211_check_wbrf_support(local);
> +
>   rtnl_lock();
>   wiphy_lock(hw->wiphy);
>  
> diff --git a/net/mac80211/wbrf.c b/net/mac80211/wbrf.c
> new file mode 100644
> index ..ca3f30b58476
> --- /dev/null
> +++ b/net/mac80211/wbrf.c
> @@ -0,0 +1,95 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> 

Re: [PATCH v2 2/9] drm/radeon: Switch from pci_is_thunderbolt_attached() to dev_is_removable()

2023-11-06 Thread Ilpo Järvinen
On Fri, 3 Nov 2023, Mario Limonciello wrote:

> pci_is_thunderbolt_attached() only works for Intel TBT devices. Switch to
> using dev_is_removable() to be able to detect USB4 devices as well.

Same here as with 1/9.

-- 
 i.

> Signed-off-by: Mario Limonciello 
> ---
>  drivers/gpu/drm/radeon/radeon_device.c | 4 ++--
>  drivers/gpu/drm/radeon/radeon_kms.c| 2 +-
>  2 files changed, 3 insertions(+), 3 deletions(-)
> 
> diff --git a/drivers/gpu/drm/radeon/radeon_device.c 
> b/drivers/gpu/drm/radeon/radeon_device.c
> index afbb3a80c0c6..ba0ca0694d18 100644
> --- a/drivers/gpu/drm/radeon/radeon_device.c
> +++ b/drivers/gpu/drm/radeon/radeon_device.c
> @@ -1429,7 +1429,7 @@ int radeon_device_init(struct radeon_device *rdev,
>  
>   if (rdev->flags & RADEON_IS_PX)
>   runtime = true;
> - if (!pci_is_thunderbolt_attached(rdev->pdev))
> + if (!dev_is_removable(&rdev->pdev->dev))
>   vga_switcheroo_register_client(rdev->pdev,
>  &radeon_switcheroo_ops, runtime);
>   if (runtime)
> @@ -1519,7 +1519,7 @@ void radeon_device_fini(struct radeon_device *rdev)
>   radeon_bo_evict_vram(rdev);
>   radeon_audio_component_fini(rdev);
>   radeon_fini(rdev);
> - if (!pci_is_thunderbolt_attached(rdev->pdev))
> + if (!dev_is_removable(&rdev->pdev->dev))
>   vga_switcheroo_unregister_client(rdev->pdev);
>   if (rdev->flags & RADEON_IS_PX)
>   vga_switcheroo_fini_domain_pm_ops(rdev->dev);
> diff --git a/drivers/gpu/drm/radeon/radeon_kms.c 
> b/drivers/gpu/drm/radeon/radeon_kms.c
> index a16590c6247f..ead912a58ab8 100644
> --- a/drivers/gpu/drm/radeon/radeon_kms.c
> +++ b/drivers/gpu/drm/radeon/radeon_kms.c
> @@ -138,7 +138,7 @@ int radeon_driver_load_kms(struct drm_device *dev, 
> unsigned long flags)
>   if ((radeon_runtime_pm != 0) &&
>   radeon_has_atpx() &&
>   ((flags & RADEON_IS_IGP) == 0) &&
> - !pci_is_thunderbolt_attached(pdev))
> + !dev_is_removable(&pdev->dev))
>   flags |= RADEON_IS_PX;
>  
>   /* radeon_device_init should report only fatal error
> 


Re: [PATCH v2 5/9] PCI: pciehp: Move check for is_thunderbolt into a quirk

2023-11-06 Thread Ilpo Järvinen
On Fri, 3 Nov 2023, Mario Limonciello wrote:

> commit 493fb50e958c ("PCI: pciehp: Assume NoCompl+ for Thunderbolt
> ports") added a check into pciehp code to explicitly set NoCompl+
> for all Intel Thunderbolt controllers, including those that don't
> need it.
> 
> This overloaded the purpose of the `is_thunderbolt` member of
> `struct pci_device` because that means that any controller that
> identifies as thunderbolt would set NoCompl+ even if it doesn't
> suffer this deficiency. As that commit helpfully specifies all the
> controllers with the problem, move them into a PCI quirk.
> 
> Signed-off-by: Mario Limonciello 
> ---
>  drivers/pci/hotplug/pciehp_hpc.c |  6 +-
>  drivers/pci/quirks.c | 20 
>  include/linux/pci.h  |  1 +
>  3 files changed, 22 insertions(+), 5 deletions(-)
> 
> diff --git a/drivers/pci/hotplug/pciehp_hpc.c 
> b/drivers/pci/hotplug/pciehp_hpc.c
> index fd713abdfb9f..23a92d681d1c 100644
> --- a/drivers/pci/hotplug/pciehp_hpc.c
> +++ b/drivers/pci/hotplug/pciehp_hpc.c
> @@ -991,11 +991,7 @@ struct controller *pcie_init(struct pcie_device *dev)
>   if (pdev->hotplug_user_indicators)
>   slot_cap &= ~(PCI_EXP_SLTCAP_AIP | PCI_EXP_SLTCAP_PIP);
>  
> - /*
> -  * We assume no Thunderbolt controllers support Command Complete events,
> -  * but some controllers falsely claim they do.
> -  */
> - if (pdev->is_thunderbolt)
> + if (pdev->no_command_complete)
>   slot_cap |= PCI_EXP_SLTCAP_NCCS;
>  
>   ctrl->slot_cap = slot_cap;
> diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c
> index eeec1d6f9023..4bbf6e33ca11 100644
> --- a/drivers/pci/quirks.c
> +++ b/drivers/pci/quirks.c
> @@ -3807,6 +3807,26 @@ DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 
> PCI_DEVICE_ID_INTEL_CACTUS_RIDGE_4C
>  DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_PORT_RIDGE,
>   quirk_thunderbolt_hotplug_msi);
>  
> +/*
> + * We assume no Thunderbolt controllers support Command Complete events,
> + * but some controllers falsely claim they do.

IMO, this wording makes little sense with the new code. How about taking 
some text from the original commit's changelog:

/*
 * Certain Thunderbolt 1 controllers falsely claim to support Command 
 * Completed events.
 */

The code change looks fine.

-- 
 i.

> + */
> +static void quirk_thunderbolt_command_complete(struct pci_dev *pdev)
> +{
> + pdev->no_command_complete = 1;
> +}
> +DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_LIGHT_RIDGE,
> + quirk_thunderbolt_command_complete);
> +DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_EAGLE_RIDGE,
> + quirk_thunderbolt_command_complete);
> +DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_LIGHT_PEAK,
> + quirk_thunderbolt_command_complete);
> +DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 
> PCI_DEVICE_ID_INTEL_CACTUS_RIDGE_4C,
> + quirk_thunderbolt_command_complete);
> +DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 
> PCI_DEVICE_ID_INTEL_CACTUS_RIDGE_2C,
> + quirk_thunderbolt_command_complete);
> +DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_PORT_RIDGE,
> + quirk_thunderbolt_command_complete);
>  #ifdef CONFIG_ACPI
>  /*
>   * Apple: Shutdown Cactus Ridge Thunderbolt controller.
> diff --git a/include/linux/pci.h b/include/linux/pci.h
> index 530b0a360514..439c2dac8a3e 100644
> --- a/include/linux/pci.h
> +++ b/include/linux/pci.h
> @@ -441,6 +441,7 @@ struct pci_dev {
>   unsigned intis_hotplug_bridge:1;
>   unsigned intshpc_managed:1; /* SHPC owned by shpchp */
>   unsigned intis_thunderbolt:1;   /* Thunderbolt controller */
> + unsigned intno_command_complete:1;  /* No command completion */
>   /*
>* Devices marked being untrusted are the ones that can potentially
>* execute DMA attacks and similar. They are typically connected
> 



Re: [PATCH v2 3/9] PCI: Drop pci_is_thunderbolt_attached()

2023-11-06 Thread Ilpo Järvinen
On Fri, 3 Nov 2023, Mario Limonciello wrote:

> All callers have switched to dev_is_removable() for detecting
> hotpluggable PCIe devices.
> 
> Signed-off-by: Mario Limonciello 
> ---
>  include/linux/pci.h | 22 --
>  1 file changed, 22 deletions(-)
> 
> diff --git a/include/linux/pci.h b/include/linux/pci.h
> index b56417276042..530b0a360514 100644
> --- a/include/linux/pci.h
> +++ b/include/linux/pci.h
> @@ -2616,28 +2616,6 @@ static inline bool pci_ari_enabled(struct pci_bus *bus)
>   return bus->self && bus->self->ari_enabled;
>  }
>  
> -/**
> - * pci_is_thunderbolt_attached - whether device is on a Thunderbolt daisy 
> chain
> - * @pdev: PCI device to check
> - *
> - * Walk upwards from @pdev and check for each encountered bridge if it's part
> - * of a Thunderbolt controller.  Reaching the host bridge means @pdev is not
> - * Thunderbolt-attached.  (But rather soldered to the mainboard usually.)
> - */
> -static inline bool pci_is_thunderbolt_attached(struct pci_dev *pdev)
> -{
> - struct pci_dev *parent = pdev;
> -
> - if (pdev->is_thunderbolt)
> - return true;
> -
> - while ((parent = pci_upstream_bridge(parent)))
> - if (parent->is_thunderbolt)
> - return true;
> -
> - return false;
> -}
> -
>  #if defined(CONFIG_PCIEPORTBUS) || defined(CONFIG_EEH)
>  void pci_uevent_ers(struct pci_dev *pdev, enum  pci_ers_result err_type);
>  #endif
> 

I don't think all callers have been removed. Ah, lkp has caught the same 
problem.

-- 
 i.



Re: [PATCH v2 1/9] drm/nouveau: Switch from pci_is_thunderbolt_attached() to dev_is_removable()

2023-11-06 Thread Ilpo Järvinen
On Fri, 3 Nov 2023, Mario Limonciello wrote:

> pci_is_thunderbolt_attached() only works for Intel TBT devices. Switch to
> using dev_is_removable() to be able to detect USB4 devices as well.

Please extend this with more details. I had to lookup the TBT change to 
be able to make any guess why you're doing this (and it's still a guess 
at best).

-- 
 i.


> Signed-off-by: Mario Limonciello 
> ---
>  drivers/gpu/drm/nouveau/nouveau_vga.c | 6 +++---
>  1 file changed, 3 insertions(+), 3 deletions(-)
> 
> diff --git a/drivers/gpu/drm/nouveau/nouveau_vga.c 
> b/drivers/gpu/drm/nouveau/nouveau_vga.c
> index f8bf0ec26844..14215b7ca187 100644
> --- a/drivers/gpu/drm/nouveau/nouveau_vga.c
> +++ b/drivers/gpu/drm/nouveau/nouveau_vga.c
> @@ -94,8 +94,8 @@ nouveau_vga_init(struct nouveau_drm *drm)
>  
>   vga_client_register(pdev, nouveau_vga_set_decode);
>  
> - /* don't register Thunderbolt eGPU with vga_switcheroo */
> - if (pci_is_thunderbolt_attached(pdev))
> + /* don't register USB4/Thunderbolt eGPU with vga_switcheroo */
> + if (dev_is_removable(&pdev->dev))
>   return;
>  
>   vga_switcheroo_register_client(pdev, &nouveau_switcheroo_ops, runtime);
> @@ -118,7 +118,7 @@ nouveau_vga_fini(struct nouveau_drm *drm)
>  
>   vga_client_unregister(pdev);
>  
> - if (pci_is_thunderbolt_attached(pdev))
> + if (dev_is_removable(&pdev->dev))
>   return;
>  
>   vga_switcheroo_unregister_client(pdev);
> 


Re: [PATCH v2 8/9] PCI: Exclude PCIe ports used for tunneling in pcie_bandwidth_available()

2023-11-06 Thread Ilpo Järvinen
On Fri, 3 Nov 2023, Mario Limonciello wrote:

> The USB4 spec specifies that PCIe ports that are used for tunneling
> PCIe traffic over USB4 fabric will be hardcoded to advertise 2.5GT/s and
> behave as a PCIe Gen1 device. The actual performance of these ports is
> controlled by the fabric implementation.
> 
> Downstream drivers such as amdgpu which utilize pcie_bandwidth_available()
> to program the device will always find the PCIe ports used for
> tunneling as a limiting factor potentially leading to incorrect
> performance decisions.
> 
> To prevent problems in downstream drivers check explicitly for ports
> being used for PCIe tunneling and skip them when looking for bandwidth
> limitations of the hierarchy. If the only device connected is a root port
> used for tunneling then report that device.
> 
> Downstream drivers could make this change on their own but then they
> wouldn't be able to detect other potential speed bottlenecks from the
> hierarchy without duplicating pcie_bandwidth_available() logic.
> 
> Link: https://gitlab.freedesktop.org/drm/amd/-/issues/2925#note_2145860
> Link: https://www.usb.org/document-library/usb4r-specification-v20
>   USB4 V2 with Errata and ECN through June 2023
>   Section 11.2.1
> Signed-off-by: Mario Limonciello 
> ---
>  drivers/pci/pci.c | 74 +++
>  1 file changed, 49 insertions(+), 25 deletions(-)
> 
> diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c
> index d9aa5a39f585..15e37164ce56 100644
> --- a/drivers/pci/pci.c
> +++ b/drivers/pci/pci.c
> @@ -6223,6 +6223,35 @@ int pcie_set_mps(struct pci_dev *dev, int mps)
>  }
>  EXPORT_SYMBOL(pcie_set_mps);
>  
> +static u32 pcie_calc_bw_limits(struct pci_dev *dev, u32 bw,
> +struct pci_dev **limiting_dev,
> +enum pci_bus_speed *speed,
> +enum pcie_link_width *width)
> +{
> + enum pcie_link_width next_width;
> + enum pci_bus_speed next_speed;
> + u32 next_bw;
> + u16 lnksta;
> +
> + pcie_capability_read_word(dev, PCI_EXP_LNKSTA, &lnksta);
> + next_speed = pcie_link_speed[lnksta & PCI_EXP_LNKSTA_CLS];
> + next_width = (lnksta & PCI_EXP_LNKSTA_NLW) >> PCI_EXP_LNKSTA_NLW_SHIFT;
> + next_bw = next_width * PCIE_SPEED2MBS_ENC(next_speed);
> +
> + /* Check if current device limits the total bandwidth */
> + if (!bw || next_bw <= bw) {
> + bw = next_bw;
> + if (limiting_dev)
> + *limiting_dev = dev;
> + if (speed)
> + *speed = next_speed;
> + if (width)
> + *width = next_width;
> + }
> +
> + return bw;
> +}
> +
>  /**
>   * pcie_bandwidth_available - determine minimum link settings of a PCIe
>   * device and its bandwidth limitation
> @@ -6236,47 +6265,42 @@ EXPORT_SYMBOL(pcie_set_mps);
>   * limiting_dev, speed, and width pointers are supplied) information about
>   * that point.  The bandwidth returned is in Mb/s, i.e., megabits/second of
>   * raw bandwidth.
> + *
> + * This excludes the bandwidth calculation that has been returned from a
> + * PCIe device used for transmitting tunneled PCIe traffic over a Thunderbolt
> + * or USB4 link that is part of larger hierarchy. The calculation is excluded
> + * because the USB4 specification specifies that the max speed returned from
> + * PCIe configuration registers for the tunneling link is always PCI 1x 2.5 
> GT/s.
> + * When only tunneled devices are present, the bandwidth returned is the
> + * bandwidth available from the first tunneled device.
>   */
>  u32 pcie_bandwidth_available(struct pci_dev *dev, struct pci_dev 
> **limiting_dev,
>enum pci_bus_speed *speed,
>enum pcie_link_width *width)
>  {
> - u16 lnksta;
> - enum pci_bus_speed next_speed;
> - enum pcie_link_width next_width;
> - u32 bw, next_bw;
> + struct pci_dev *tdev = NULL;
> + u32 bw = 0;
>  
>   if (speed)
>   *speed = PCI_SPEED_UNKNOWN;
>   if (width)
>   *width = PCIE_LNK_WIDTH_UNKNOWN;
>  
> - bw = 0;
> -
>   while (dev) {
> - pcie_capability_read_word(dev, PCI_EXP_LNKSTA, &lnksta);
> -
> - next_speed = pcie_link_speed[lnksta & PCI_EXP_LNKSTA_CLS];
> - next_width = (lnksta & PCI_EXP_LNKSTA_NLW) >>
> - PCI_EXP_LNKSTA_NLW_SHIFT;
> -
> - next_bw = next_width * PCIE_SPEED2MBS_ENC(next_speed);
> -
> - /* Check if current device limits the total bandwidth */
> - if (!bw || next_bw <= bw) {
> - bw = next_bw;
> -
> - if (limiting_dev)
> - *limiting_dev = dev;
> - if (speed)
> - *speed = next_speed;
> - if (width)
> - *width = next_wid

Re: [PATCH v3 4/7] PCI: pciehp: Move check for is_thunderbolt into a quirk

2023-11-16 Thread Ilpo Järvinen
On Tue, 14 Nov 2023, Mario Limonciello wrote:

> commit 493fb50e958c ("PCI: pciehp: Assume NoCompl+ for Thunderbolt
> ports") added a check into pciehp code to explicitly set NoCompl+
> for all Intel Thunderbolt controllers, including those that don't
> need it.
> 
> This overloaded the purpose of the `is_thunderbolt` member of
> `struct pci_device` because that means that any controller that
> identifies as thunderbolt would set NoCompl+ even if it doesn't
> suffer this deficiency. As that commit helpfully specifies all the
> controllers with the problem, move them into a PCI quirk.
> 
> Signed-off-by: Mario Limonciello 
> ---
> v2->v3:
>  * Reword commit message
>  * Update comments
> ---
>  drivers/pci/hotplug/pciehp_hpc.c |  6 +-
>  drivers/pci/quirks.c | 20 
>  include/linux/pci.h  |  1 +
>  3 files changed, 22 insertions(+), 5 deletions(-)
> 
> diff --git a/drivers/pci/hotplug/pciehp_hpc.c 
> b/drivers/pci/hotplug/pciehp_hpc.c
> index b1d0a1b3917d..40f7a26fb98f 100644
> --- a/drivers/pci/hotplug/pciehp_hpc.c
> +++ b/drivers/pci/hotplug/pciehp_hpc.c
> @@ -992,11 +992,7 @@ struct controller *pcie_init(struct pcie_device *dev)
>   if (pdev->hotplug_user_indicators)
>   slot_cap &= ~(PCI_EXP_SLTCAP_AIP | PCI_EXP_SLTCAP_PIP);
>  
> - /*
> -  * We assume no Thunderbolt controllers support Command Complete events,
> -  * but some controllers falsely claim they do.
> -  */
> - if (pdev->is_thunderbolt)
> + if (pdev->no_command_complete)
>   slot_cap |= PCI_EXP_SLTCAP_NCCS;
>  
>   ctrl->slot_cap = slot_cap;
> diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c
> index ea476252280a..fa9b82cd7b3b 100644
> --- a/drivers/pci/quirks.c
> +++ b/drivers/pci/quirks.c
> @@ -3809,6 +3809,26 @@ DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 
> PCI_DEVICE_ID_INTEL_CACTUS_RIDGE_4C
>  DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_PORT_RIDGE,
>   quirk_thunderbolt_hotplug_msi);
>  
> +/*
> + * Certain Thunderbolt 1 controllers falsely claim to support Command
> + * Completed events.
> + */
> +static void quirk_thunderbolt_command_complete(struct pci_dev *pdev)
> +{
> + pdev->no_command_complete = 1;
> +}
> +DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_LIGHT_RIDGE,
> + quirk_thunderbolt_command_complete);
> +DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_EAGLE_RIDGE,
> + quirk_thunderbolt_command_complete);
> +DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_LIGHT_PEAK,
> + quirk_thunderbolt_command_complete);
> +DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 
> PCI_DEVICE_ID_INTEL_CACTUS_RIDGE_4C,
> + quirk_thunderbolt_command_complete);
> +DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 
> PCI_DEVICE_ID_INTEL_CACTUS_RIDGE_2C,
> + quirk_thunderbolt_command_complete);
> +DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_PORT_RIDGE,
> + quirk_thunderbolt_command_complete);
>  #ifdef CONFIG_ACPI
>  /*
>   * Apple: Shutdown Cactus Ridge Thunderbolt controller.
> diff --git a/include/linux/pci.h b/include/linux/pci.h
> index 1fbca2bd92e8..20a6e4fc3060 100644
> --- a/include/linux/pci.h
> +++ b/include/linux/pci.h
> @@ -441,6 +441,7 @@ struct pci_dev {
>   unsigned intis_hotplug_bridge:1;
>   unsigned intshpc_managed:1; /* SHPC owned by shpchp */
>   unsigned intis_thunderbolt:1;   /* Thunderbolt controller */
> + unsigned intno_command_complete:1;  /* No command completion */
>   /*
>* Devices marked being untrusted are the ones that can potentially
>* execute DMA attacks and similar. They are typically connected
> 

Reviewed-by: Ilpo Järvinen 

-- 
 i.


Re: [PATCH v3 6/7] PCI: Split up some logic in pcie_bandwidth_available() to separate function

2023-11-16 Thread Ilpo Järvinen
On Tue, 14 Nov 2023, Mario Limonciello wrote:

> The logic to calculate bandwidth limits may be used at multiple call sites
> so split it up into its own static function instead.
> 
> No intended functional changes.
> 
> Suggested-by: Ilpo Järvinen 
> Signed-off-by: Mario Limonciello 
> ---
> v2->v3:
>  * Split from previous patch version
> ---
>  drivers/pci/pci.c | 60 +++
>  1 file changed, 34 insertions(+), 26 deletions(-)
> 
> diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c
> index 55bc3576a985..0ff7883cc774 100644
> --- a/drivers/pci/pci.c
> +++ b/drivers/pci/pci.c
> @@ -6224,6 +6224,38 @@ int pcie_set_mps(struct pci_dev *dev, int mps)
>  }
>  EXPORT_SYMBOL(pcie_set_mps);
>  
> +static u32 pcie_calc_bw_limits(struct pci_dev *dev, u32 bw,
> +struct pci_dev **limiting_dev,
> +enum pci_bus_speed *speed,
> +enum pcie_link_width *width)
> +{
> + enum pcie_link_width next_width;
> + enum pci_bus_speed next_speed;
> + u32 next_bw;
> + u16 lnksta;
> +
> + pcie_capability_read_word(dev, PCI_EXP_LNKSTA, &lnksta);
> +
> + next_speed = pcie_link_speed[FIELD_GET(PCI_EXP_LNKSTA_CLS, lnksta)];
> + next_width = FIELD_GET(PCI_EXP_LNKSTA_NLW, lnksta);
> +
> + next_bw = next_width * PCIE_SPEED2MBS_ENC(next_speed);
> +
> + /* Check if current device limits the total bandwidth */

I'd make this a function comment instead and say:

/* Check if @dev limits the total bandwidth. */

Other than that,

Reviewed-by: Ilpo Järvinen 

-- 
 i.

> + if (!bw || next_bw <= bw) {
> + bw = next_bw;
> +
> + if (limiting_dev)
> + *limiting_dev = dev;
> + if (speed)
> + *speed = next_speed;
> + if (width)
> + *width = next_width;
> + }
> +
> + return bw;
> +}
> +
>  /**
>   * pcie_bandwidth_available - determine minimum link settings of a PCIe
>   * device and its bandwidth limitation
> @@ -6242,39 +6274,15 @@ u32 pcie_bandwidth_available(struct pci_dev *dev, 
> struct pci_dev **limiting_dev,
>enum pci_bus_speed *speed,
>enum pcie_link_width *width)
>  {
> - u16 lnksta;
> - enum pci_bus_speed next_speed;
> - enum pcie_link_width next_width;
> - u32 bw, next_bw;
> + u32 bw = 0;
>  
>   if (speed)
>   *speed = PCI_SPEED_UNKNOWN;
>   if (width)
>   *width = PCIE_LNK_WIDTH_UNKNOWN;
>  
> - bw = 0;
> -
>   while (dev) {
> - pcie_capability_read_word(dev, PCI_EXP_LNKSTA, &lnksta);
> -
> - next_speed = pcie_link_speed[FIELD_GET(PCI_EXP_LNKSTA_CLS,
> -lnksta)];
> - next_width = FIELD_GET(PCI_EXP_LNKSTA_NLW, lnksta);
> -
> - next_bw = next_width * PCIE_SPEED2MBS_ENC(next_speed);
> -
> - /* Check if current device limits the total bandwidth */
> - if (!bw || next_bw <= bw) {
> - bw = next_bw;
> -
> - if (limiting_dev)
> - *limiting_dev = dev;
> - if (speed)
> - *speed = next_speed;
> - if (width)
> - *width = next_width;
> - }
> -
> + bw = pcie_calc_bw_limits(dev, bw, limiting_dev, speed, width);
>   dev = pci_upstream_bridge(dev);
>   }
>  
> 

Re: [PATCH v3 3/7] PCI: Drop pci_is_thunderbolt_attached()

2023-11-16 Thread Ilpo Järvinen
On Tue, 14 Nov 2023, Mario Limonciello wrote:

> All callers have switched to dev_is_removable() for detecting
> hotpluggable PCIe devices.
> 
> Signed-off-by: Mario Limonciello 
> ---
> v2->v3:
>  * No changes
> ---
>  include/linux/pci.h | 22 --
>  1 file changed, 22 deletions(-)
> 
> diff --git a/include/linux/pci.h b/include/linux/pci.h
> index 60ca768bc867..1fbca2bd92e8 100644
> --- a/include/linux/pci.h
> +++ b/include/linux/pci.h
> @@ -2645,28 +2645,6 @@ static inline bool pci_ari_enabled(struct pci_bus *bus)
>   return bus->self && bus->self->ari_enabled;
>  }
>  
> -/**
> - * pci_is_thunderbolt_attached - whether device is on a Thunderbolt daisy 
> chain
> - * @pdev: PCI device to check
> - *
> - * Walk upwards from @pdev and check for each encountered bridge if it's part
> - * of a Thunderbolt controller.  Reaching the host bridge means @pdev is not
> - * Thunderbolt-attached.  (But rather soldered to the mainboard usually.)
> - */
> -static inline bool pci_is_thunderbolt_attached(struct pci_dev *pdev)
> -{
> - struct pci_dev *parent = pdev;
> -
> - if (pdev->is_thunderbolt)
> - return true;
> -
> - while ((parent = pci_upstream_bridge(parent)))
> - if (parent->is_thunderbolt)
> - return true;
> -
> - return false;
> -}
> -
>  #if defined(CONFIG_PCIEPORTBUS) || defined(CONFIG_EEH)
>  void pci_uevent_ers(struct pci_dev *pdev, enum  pci_ers_result err_type);
>  #endif
> 

Reviewed-by: Ilpo Järvinen 

-- 
 i.


Re: [PATCH v3 1/7] drm/nouveau: Switch from pci_is_thunderbolt_attached() to dev_is_removable()

2023-11-16 Thread Ilpo Järvinen
On Tue, 14 Nov 2023, Mario Limonciello wrote:

> pci_is_thunderbolt_attached() looks at the hierarchy of the PCIe device
> to determine if any bridge along the way has the is_thunderbolt bit set.
> This bit will only be set when one of the devices in the hierarchy is an
> Intel Thunderbolt device.
> 
> However PCIe devices can be connected to USB4 hubs and routers which won't
> necessarily set the is_thunderbolt bit. These devices will however be
> marked as externally facing which means they are marked removable by
> pci_set_removable().
> 
> Look whether the device is marked removable to determine it's
> connected to a Thunderbolt controller or USB4 router.

(I hate having to say this) but I still feel the actual reason why you're 
doing this change is missing from the above and has to be read between the 
lines.

Perhaps something along these lines matches what's your intent here:

The external GPU check added in commit 1d3c11030103 ("drm/nouveau: Don't 
register Thunderbolt eGPU with vga_switcheroo") covers only Thunderbolt
devices but removable PCIe devices can also be connected to USB4 hubs and 
routers. Those devices won't necessarily set the is_thunderbolt bit that
pci_is_thunderbolt_attached() checks for.

USB4 hubs and routers are however marked as externally facing which means 
they are marked removable by pci_set_removable().

Extend the check for removable device beyond Thunderbolt devices by 
using dev_is_removable() that covers also USB4 routers.

?

-- 
 i.

> Signed-off-by: Mario Limonciello 
> ---
> v2->v3:
>  * Update commit message
> ---
>  drivers/gpu/drm/nouveau/nouveau_vga.c | 6 +++---
>  1 file changed, 3 insertions(+), 3 deletions(-)
> 
> diff --git a/drivers/gpu/drm/nouveau/nouveau_vga.c 
> b/drivers/gpu/drm/nouveau/nouveau_vga.c
> index f8bf0ec26844..14215b7ca187 100644
> --- a/drivers/gpu/drm/nouveau/nouveau_vga.c
> +++ b/drivers/gpu/drm/nouveau/nouveau_vga.c
> @@ -94,8 +94,8 @@ nouveau_vga_init(struct nouveau_drm *drm)
>  
>   vga_client_register(pdev, nouveau_vga_set_decode);
>  
> - /* don't register Thunderbolt eGPU with vga_switcheroo */
> - if (pci_is_thunderbolt_attached(pdev))
> + /* don't register USB4/Thunderbolt eGPU with vga_switcheroo */
> + if (dev_is_removable(&pdev->dev))
>   return;
>  
>   vga_switcheroo_register_client(pdev, &nouveau_switcheroo_ops, runtime);
> @@ -118,7 +118,7 @@ nouveau_vga_fini(struct nouveau_drm *drm)
>  
>   vga_client_unregister(pdev);
>  
> - if (pci_is_thunderbolt_attached(pdev))
> + if (dev_is_removable(&pdev->dev))
>   return;
>  
>   vga_switcheroo_unregister_client(pdev);
> 



Re: [Patch v13 1/9] Documentation/driver-api: Add document about WBRF mechanism

2023-11-20 Thread Ilpo Järvinen
On Mon, 30 Oct 2023, Ma Jun wrote:

> Add documentation about AMD's Wifi band RFI mitigation (WBRF) mechanism
> explaining the theory and how it is used.
> 
> Signed-off-by: Ma Jun 
> ---
>  Documentation/driver-api/wbrf.rst | 76 +++
>  1 file changed, 76 insertions(+)
>  create mode 100644 Documentation/driver-api/wbrf.rst
> 
> +Driver programming interface
> +
> +.. kernel-doc:: drivers/platform/x86/amd/wbrf.c
> +
> +Sample Usage
> +=

A lot better but you missed adding newlines here for this and previous 
section title.

> +The expected flow for the producers:
> +1). During probe, call `acpi_amd_wbrf_supported_producer` to check if WBRF
> +can be enabled for the device.
> +2). On using some frequency band, call `acpi_amd_wbrf_add_remove` with 'add'
> +param to get other consumers properly notified.
> +3). Or on stopping using some frequency band, call
> +`acpi_amd_wbrf_add_remove` with 'remove' param to get other consumers 
> notified.
> +
> +The expected flow for the consumers:
> +1). During probe, call `acpi_amd_wbrf_supported_consumer` to check if WBRF
> +can be enabled for the device.
> +2). Call `amd_wbrf_register_notifier` to register for notification
> +of frequency band change(add or remove) from other producers.
> +3). Call the `amd_wbrf_retrieve_freq_band` intentionally to retrieve
> +current active frequency bands considering some producers may broadcast
> +such information before the consumer is up.
> +4). On receiving a notification for frequency band change, run
> +`amd_wbrf_retrieve_freq_band` again to retrieve the latest
> +active frequency bands.
> +5). During driver cleanup, call `amd_wbrf_unregister_notifier` to
> +unregister the notifier.

The correct kerneldoc format should be without the closing parenthesis:

1. Text here that
   spills to second line.
2. Second entry.

-- 
 i.



Re: [PATCH] kernel/resource: optimize find_next_iomem_res

2024-06-03 Thread Ilpo Järvinen
On Sun, 2 Jun 2024, Andy Shevchenko wrote:

> On Fri, May 31, 2024 at 02:31:45PM -0700, Chia-I Wu wrote:
> > On Fri, May 31, 2024 at 1:57 AM Andy Shevchenko <
> > andriy.shevche...@linux.intel.com> wrote:
> > > On Thu, May 30, 2024 at 10:36:57PM -0700, Chia-I Wu wrote:
> 
> ...
> 
> > > P.S> I'm not so sure about this change. It needs a thoroughly testing, 
> > > esp.
> > > in PCI case. Cc'ing to Ilpo.
> 
> > What's special about PCI?
> 
> PCI, due to its nature, may rebuild resources either by shrinking or expanding
> of the entire subtree after the PCI bridge in question. And this may happen at
> run-time due to hotplug support. But I'm not a deep expert in this area, Ilpo
> knows much more than me.

There is code which clearly tries to do expanding resource but that 
usually fails to work as intended because of a parent resource whose size 
is fixed because it's already assigned.

Some other code might block shrinking too under certain conditions.

This area would need to be reworked in PCI core but it's massive and 
scary looking change.

-- 
 i.

Re: [PATCH] kernel/resource: optimize find_next_iomem_res

2024-06-03 Thread Ilpo Järvinen
On Fri, 31 May 2024, Chia-I Wu wrote:
> On Fri, May 31, 2024 at 1:57 AM Andy Shevchenko 
> 
> wrote:
>   On Thu, May 30, 2024 at 10:36:57PM -0700, Chia-I Wu wrote:
>   > We can skip children resources when the parent resource does not cover
>   > the range.
>   >
>   > This should help vmf_insert_* users on x86, such as several DRM
>   drivers.
>   > On my AMD Ryzen 5 7520C, when streaming data from cpu memory into
>   amdgpu
>   > bo, the throughput goes from 5.1GB/s to 6.6GB/s.  perf report says
>   >
>   >   34.69%--__do_fault
>   >   34.60%--amdgpu_gem_fault
>   >   34.00%--ttm_bo_vm_fault_reserved
>   >   32.95%--vmf_insert_pfn_prot
>   >   25.89%--track_pfn_insert
>   >   24.35%--lookup_memtype
>   >   21.77%--pat_pagerange_is_ram
>   >   20.80%--walk_system_ram_range
>   >   17.42%--find_next_iomem_res
>   >
>   > before this change, and
>   >
>   >   26.67%--__do_fault
>   >   26.57%--amdgpu_gem_fault
>   >   25.83%--ttm_bo_vm_fault_reserved
>   >   24.40%--vmf_insert_pfn_prot
>   >   14.30%--track_pfn_insert
>   >   12.20%--lookup_memtype
>   >   9.34%--pat_pagerange_is_ram
>   >   8.22%--walk_system_ram_range
>   >   5.09%--find_next_iomem_res
>   >
>   > after.
> 
>   Is there any documentation that explicitly says that the children
>   resources
>   must not overlap parent's one? Do we have some test cases? (Either way
>   they
>   needs to be added / expanded).
> 
> I think it's the opposite.  The assumption here is that a child is always a 
> subset of
> its parent.  Thus, if the range to be checked is not covered by a parent, we 
> can skip
> the children.
>
> That's guaranteed by __request_resource.  I am less sure about 
> __insert_resource but
> it appears to be the case too.  FWIW, resource_is_exclusive has the same 
> assumption
> already.

Yes, the children resources are contained within the parent resource (at 
least in PCI but given the code, I'd expect that to be general state of 
affairs).

> It looks like I need to do some refactoring to add tests.
> 
> 
>   P.S> I'm not so sure about this change. It needs a thoroughly testing,
>   esp.
>   in PCI case. Cc'ing to Ilpo.
> 
> What's special about PCI?

-- 
 i.


Re: [PATCH 3/3] RDMA/hfi1: Use RMW accessors for changing LNKCTL2

2024-05-03 Thread Ilpo Järvinen
On Thu, 15 Feb 2024, Ilpo Järvinen wrote:

> Convert open coded RMW accesses for LNKCTL2 to use
> pcie_capability_clear_and_set_word() which makes its easier to
> understand what the code tries to do.
> 
> LNKCTL2 is not really owned by any driver because it is a collection of
> control bits that PCI core might need to touch. RMW accessors already
> have support for proper locking for a selected set of registers
> (LNKCTL2 is not yet among them but likely will be in the future) to
> avoid losing concurrent updates.
> 
> Suggested-by: Lukas Wunner 
> Signed-off-by: Ilpo Järvinen 
> Reviewed-by: Dean Luick 

I found out from Linux RDMA and InfiniBand patchwork that this patch had 
been silently closed as "Not Applicable". Is there some reason for that?

I was sending this change independently out (among 2 similar ones that 
already got applied) so I wouldn't need to keep carrying it within my PCIe 
bandwidth controller series. It seemed useful enough as cleanups to stand 
on its own legs w/o requiring it to be part of PCIe bw controller series.

Should I resend the patch or do RDMA/IB maintainers prefer it to remain 
as a part of PCIe BW controller series?

-- 
 i.

> ---
>  drivers/infiniband/hw/hfi1/pcie.c | 30 --
>  1 file changed, 8 insertions(+), 22 deletions(-)
> 
> diff --git a/drivers/infiniband/hw/hfi1/pcie.c 
> b/drivers/infiniband/hw/hfi1/pcie.c
> index 119ec2f1382b..7133964749f8 100644
> --- a/drivers/infiniband/hw/hfi1/pcie.c
> +++ b/drivers/infiniband/hw/hfi1/pcie.c
> @@ -1207,14 +1207,11 @@ int do_pcie_gen3_transition(struct hfi1_devdata *dd)
>   (u32)lnkctl2);
>   /* only write to parent if target is not as high as ours */
>   if ((lnkctl2 & PCI_EXP_LNKCTL2_TLS) < target_vector) {
> - lnkctl2 &= ~PCI_EXP_LNKCTL2_TLS;
> - lnkctl2 |= target_vector;
> - dd_dev_info(dd, "%s: ..new link control2: 0x%x\n", __func__,
> - (u32)lnkctl2);
> - ret = pcie_capability_write_word(parent,
> -  PCI_EXP_LNKCTL2, lnkctl2);
> + ret = pcie_capability_clear_and_set_word(parent, 
> PCI_EXP_LNKCTL2,
> +  PCI_EXP_LNKCTL2_TLS,
> +  target_vector);
>   if (ret) {
> - dd_dev_err(dd, "Unable to write to PCI config\n");
> + dd_dev_err(dd, "Unable to change parent PCI target 
> speed\n");
>   return_error = 1;
>   goto done;
>   }
> @@ -1223,22 +1220,11 @@ int do_pcie_gen3_transition(struct hfi1_devdata *dd)
>   }
>  
>   dd_dev_info(dd, "%s: setting target link speed\n", __func__);
> - ret = pcie_capability_read_word(dd->pcidev, PCI_EXP_LNKCTL2, &lnkctl2);
> + ret = pcie_capability_clear_and_set_word(dd->pcidev, PCI_EXP_LNKCTL2,
> +  PCI_EXP_LNKCTL2_TLS,
> +  target_vector);
>   if (ret) {
> - dd_dev_err(dd, "Unable to read from PCI config\n");
> - return_error = 1;
> - goto done;
> - }
> -
> - dd_dev_info(dd, "%s: ..old link control2: 0x%x\n", __func__,
> - (u32)lnkctl2);
> - lnkctl2 &= ~PCI_EXP_LNKCTL2_TLS;
> - lnkctl2 |= target_vector;
> - dd_dev_info(dd, "%s: ..new link control2: 0x%x\n", __func__,
> - (u32)lnkctl2);
> - ret = pcie_capability_write_word(dd->pcidev, PCI_EXP_LNKCTL2, lnkctl2);
> - if (ret) {
> - dd_dev_err(dd, "Unable to write to PCI config\n");
> + dd_dev_err(dd, "Unable to change device PCI target speed\n");
>   return_error = 1;
>   goto done;
>   }
> 

[PATCH v4 2/8] drm/radeon: Use RMW accessors for changing LNKCTL2

2024-01-05 Thread Ilpo Järvinen
Don't assume that only the driver would be accessing LNKCTL2. In the
case of upstream (parent), the driver does not even own the device it's
changing the registers for.

Use RMW capability accessors which do proper locking to avoid losing
concurrent updates to the register value. This change is also useful as
a cleanup.

Suggested-by: Lukas Wunner 
Signed-off-by: Ilpo Järvinen 
---
 drivers/gpu/drm/radeon/cik.c | 40 ++--
 drivers/gpu/drm/radeon/si.c  | 40 ++--
 2 files changed, 30 insertions(+), 50 deletions(-)

diff --git a/drivers/gpu/drm/radeon/cik.c b/drivers/gpu/drm/radeon/cik.c
index 10be30366c2b..b5e96a8fc2c1 100644
--- a/drivers/gpu/drm/radeon/cik.c
+++ b/drivers/gpu/drm/radeon/cik.c
@@ -9592,28 +9592,18 @@ static void cik_pcie_gen3_enable(struct radeon_device 
*rdev)
   
PCI_EXP_LNKCTL_HAWD);
 
/* linkctl2 */
-   pcie_capability_read_word(root, PCI_EXP_LNKCTL2,
- &tmp16);
-   tmp16 &= ~(PCI_EXP_LNKCTL2_ENTER_COMP |
-  PCI_EXP_LNKCTL2_TX_MARGIN);
-   tmp16 |= (bridge_cfg2 &
- (PCI_EXP_LNKCTL2_ENTER_COMP |
-  PCI_EXP_LNKCTL2_TX_MARGIN));
-   pcie_capability_write_word(root,
-  PCI_EXP_LNKCTL2,
-  tmp16);
-
-   pcie_capability_read_word(rdev->pdev,
- PCI_EXP_LNKCTL2,
- &tmp16);
-   tmp16 &= ~(PCI_EXP_LNKCTL2_ENTER_COMP |
-  PCI_EXP_LNKCTL2_TX_MARGIN);
-   tmp16 |= (gpu_cfg2 &
- (PCI_EXP_LNKCTL2_ENTER_COMP |
-  PCI_EXP_LNKCTL2_TX_MARGIN));
-   pcie_capability_write_word(rdev->pdev,
-  PCI_EXP_LNKCTL2,
-  tmp16);
+   pcie_capability_clear_and_set_word(root, 
PCI_EXP_LNKCTL2,
+  
PCI_EXP_LNKCTL2_ENTER_COMP |
+  
PCI_EXP_LNKCTL2_TX_MARGIN,
+  bridge_cfg2 |
+  
(PCI_EXP_LNKCTL2_ENTER_COMP |
+   
PCI_EXP_LNKCTL2_TX_MARGIN));
+   pcie_capability_clear_and_set_word(rdev->pdev, 
PCI_EXP_LNKCTL2,
+  
PCI_EXP_LNKCTL2_ENTER_COMP |
+  
PCI_EXP_LNKCTL2_TX_MARGIN,
+  gpu_cfg2 |
+  
(PCI_EXP_LNKCTL2_ENTER_COMP |
+   
PCI_EXP_LNKCTL2_TX_MARGIN));
 
tmp = RREG32_PCIE_PORT(PCIE_LC_CNTL4);
tmp &= ~LC_SET_QUIESCE;
@@ -9627,15 +9617,15 @@ static void cik_pcie_gen3_enable(struct radeon_device 
*rdev)
speed_cntl &= ~LC_FORCE_DIS_SW_SPEED_CHANGE;
WREG32_PCIE_PORT(PCIE_LC_SPEED_CNTL, speed_cntl);
 
-   pcie_capability_read_word(rdev->pdev, PCI_EXP_LNKCTL2, &tmp16);
-   tmp16 &= ~PCI_EXP_LNKCTL2_TLS;
+   tmp16 = 0;
if (speed_cap == PCIE_SPEED_8_0GT)
tmp16 |= PCI_EXP_LNKCTL2_TLS_8_0GT; /* gen3 */
else if (speed_cap == PCIE_SPEED_5_0GT)
tmp16 |= PCI_EXP_LNKCTL2_TLS_5_0GT; /* gen2 */
else
tmp16 |= PCI_EXP_LNKCTL2_TLS_2_5GT; /* gen1 */
-   pcie_capability_write_word(rdev->pdev, PCI_EXP_LNKCTL2, tmp16);
+   pcie_capability_clear_and_set_word(rdev->pdev, PCI_EXP_LNKCTL2,
+  PCI_EXP_LNKCTL2_TLS, tmp16);
 
speed_cntl = RREG32_PCIE_PORT(PCIE_LC_SPEED_CNTL);
speed_cntl |= LC_INITIATE_LINK_SPEED_CHANGE;
diff --git a/drivers/gpu/drm/radeon/si.c b/drivers/gpu/drm/radeon/si.c
index a91012447b56..32871ca09a0f 100644
--- a/drivers/gpu/drm/radeon/si.c
+++ b/drivers/gpu/drm/radeon/si.c
@@ -7189,28 +71

[PATCH v4 3/8] drm/amdgpu: Use RMW accessors for changing LNKCTL2

2024-01-05 Thread Ilpo Järvinen
Don't assume that only the driver would be accessing LNKCTL2. In the
case of upstream (parent), the driver does not even own the device it's
changing the registers for.

Use RMW capability accessors which do proper locking to avoid losing
concurrent updates to the register value. This change is also useful as
a cleanup.

Suggested-by: Lukas Wunner 
Signed-off-by: Ilpo Järvinen 
---
 drivers/gpu/drm/amd/amdgpu/cik.c | 41 
 drivers/gpu/drm/amd/amdgpu/si.c  | 41 
 2 files changed, 30 insertions(+), 52 deletions(-)

diff --git a/drivers/gpu/drm/amd/amdgpu/cik.c b/drivers/gpu/drm/amd/amdgpu/cik.c
index 4dfaa017cf7f..a3a643254d7a 100644
--- a/drivers/gpu/drm/amd/amdgpu/cik.c
+++ b/drivers/gpu/drm/amd/amdgpu/cik.c
@@ -1638,28 +1638,18 @@ static void cik_pcie_gen3_enable(struct amdgpu_device 
*adev)
   
PCI_EXP_LNKCTL_HAWD);
 
/* linkctl2 */
-   pcie_capability_read_word(root, PCI_EXP_LNKCTL2,
- &tmp16);
-   tmp16 &= ~(PCI_EXP_LNKCTL2_ENTER_COMP |
-  PCI_EXP_LNKCTL2_TX_MARGIN);
-   tmp16 |= (bridge_cfg2 &
- (PCI_EXP_LNKCTL2_ENTER_COMP |
-  PCI_EXP_LNKCTL2_TX_MARGIN));
-   pcie_capability_write_word(root,
-  PCI_EXP_LNKCTL2,
-  tmp16);
-
-   pcie_capability_read_word(adev->pdev,
- PCI_EXP_LNKCTL2,
- &tmp16);
-   tmp16 &= ~(PCI_EXP_LNKCTL2_ENTER_COMP |
-  PCI_EXP_LNKCTL2_TX_MARGIN);
-   tmp16 |= (gpu_cfg2 &
- (PCI_EXP_LNKCTL2_ENTER_COMP |
-  PCI_EXP_LNKCTL2_TX_MARGIN));
-   pcie_capability_write_word(adev->pdev,
-  PCI_EXP_LNKCTL2,
-  tmp16);
+   pcie_capability_clear_and_set_word(root, 
PCI_EXP_LNKCTL2,
+  
PCI_EXP_LNKCTL2_ENTER_COMP |
+  
PCI_EXP_LNKCTL2_TX_MARGIN,
+  bridge_cfg2 &
+  
(PCI_EXP_LNKCTL2_ENTER_COMP |
+   
PCI_EXP_LNKCTL2_TX_MARGIN));
+   pcie_capability_clear_and_set_word(adev->pdev, 
PCI_EXP_LNKCTL2,
+  
PCI_EXP_LNKCTL2_ENTER_COMP |
+  
PCI_EXP_LNKCTL2_TX_MARGIN,
+  gpu_cfg2 &
+  
(PCI_EXP_LNKCTL2_ENTER_COMP |
+   
PCI_EXP_LNKCTL2_TX_MARGIN));
 
tmp = RREG32_PCIE(ixPCIE_LC_CNTL4);
tmp &= ~PCIE_LC_CNTL4__LC_SET_QUIESCE_MASK;
@@ -1674,16 +1664,15 @@ static void cik_pcie_gen3_enable(struct amdgpu_device 
*adev)
speed_cntl &= ~PCIE_LC_SPEED_CNTL__LC_FORCE_DIS_SW_SPEED_CHANGE_MASK;
WREG32_PCIE(ixPCIE_LC_SPEED_CNTL, speed_cntl);
 
-   pcie_capability_read_word(adev->pdev, PCI_EXP_LNKCTL2, &tmp16);
-   tmp16 &= ~PCI_EXP_LNKCTL2_TLS;
-
+   tmp16 = 0;
if (adev->pm.pcie_gen_mask & CAIL_PCIE_LINK_SPEED_SUPPORT_GEN3)
tmp16 |= PCI_EXP_LNKCTL2_TLS_8_0GT; /* gen3 */
else if (adev->pm.pcie_gen_mask & CAIL_PCIE_LINK_SPEED_SUPPORT_GEN2)
tmp16 |= PCI_EXP_LNKCTL2_TLS_5_0GT; /* gen2 */
else
tmp16 |= PCI_EXP_LNKCTL2_TLS_2_5GT; /* gen1 */
-   pcie_capability_write_word(adev->pdev, PCI_EXP_LNKCTL2, tmp16);
+   pcie_capability_clear_and_set_word(adev->pdev, PCI_EXP_LNKCTL2,
+  PCI_EXP_LNKCTL2_TLS, tmp16);
 
speed_cntl = RREG32_PCIE(ixPCIE_LC_SPEED_CNTL);
speed_cntl |= PCIE_LC_SPEED_CNTL__LC_INITIATE_LINK_SPEED_CHANGE_MASK;
diff --git a/drivers/gpu/drm/amd/amdgpu/si.c b/drivers/gpu/drm/amd/amdgpu/si.c
index a757526153e5..23e4e

[PATCH 2/3] drm/amdgpu: Use RMW accessors for changing LNKCTL2

2024-02-15 Thread Ilpo Järvinen
Convert open coded RMW accesses for LNKCTL2 to use
pcie_capability_clear_and_set_word() which makes its easier to
understand what the code tries to do.

LNKCTL2 is not really owned by any driver because it is a collection of
control bits that PCI core might need to touch. RMW accessors already
have support for proper locking for a selected set of registers
(LNKCTL2 is not yet among them but likely will be in the future) to
avoid losing concurrent updates.

Suggested-by: Lukas Wunner 
Signed-off-by: Ilpo Järvinen 
---
 drivers/gpu/drm/amd/amdgpu/cik.c | 41 
 drivers/gpu/drm/amd/amdgpu/si.c  | 41 
 2 files changed, 30 insertions(+), 52 deletions(-)

diff --git a/drivers/gpu/drm/amd/amdgpu/cik.c b/drivers/gpu/drm/amd/amdgpu/cik.c
index 4dfaa017cf7f..a3a643254d7a 100644
--- a/drivers/gpu/drm/amd/amdgpu/cik.c
+++ b/drivers/gpu/drm/amd/amdgpu/cik.c
@@ -1638,28 +1638,18 @@ static void cik_pcie_gen3_enable(struct amdgpu_device 
*adev)
   
PCI_EXP_LNKCTL_HAWD);
 
/* linkctl2 */
-   pcie_capability_read_word(root, PCI_EXP_LNKCTL2,
- &tmp16);
-   tmp16 &= ~(PCI_EXP_LNKCTL2_ENTER_COMP |
-  PCI_EXP_LNKCTL2_TX_MARGIN);
-   tmp16 |= (bridge_cfg2 &
- (PCI_EXP_LNKCTL2_ENTER_COMP |
-  PCI_EXP_LNKCTL2_TX_MARGIN));
-   pcie_capability_write_word(root,
-  PCI_EXP_LNKCTL2,
-  tmp16);
-
-   pcie_capability_read_word(adev->pdev,
- PCI_EXP_LNKCTL2,
- &tmp16);
-   tmp16 &= ~(PCI_EXP_LNKCTL2_ENTER_COMP |
-  PCI_EXP_LNKCTL2_TX_MARGIN);
-   tmp16 |= (gpu_cfg2 &
- (PCI_EXP_LNKCTL2_ENTER_COMP |
-  PCI_EXP_LNKCTL2_TX_MARGIN));
-   pcie_capability_write_word(adev->pdev,
-  PCI_EXP_LNKCTL2,
-  tmp16);
+   pcie_capability_clear_and_set_word(root, 
PCI_EXP_LNKCTL2,
+  
PCI_EXP_LNKCTL2_ENTER_COMP |
+  
PCI_EXP_LNKCTL2_TX_MARGIN,
+  bridge_cfg2 &
+  
(PCI_EXP_LNKCTL2_ENTER_COMP |
+   
PCI_EXP_LNKCTL2_TX_MARGIN));
+   pcie_capability_clear_and_set_word(adev->pdev, 
PCI_EXP_LNKCTL2,
+  
PCI_EXP_LNKCTL2_ENTER_COMP |
+  
PCI_EXP_LNKCTL2_TX_MARGIN,
+  gpu_cfg2 &
+  
(PCI_EXP_LNKCTL2_ENTER_COMP |
+   
PCI_EXP_LNKCTL2_TX_MARGIN));
 
tmp = RREG32_PCIE(ixPCIE_LC_CNTL4);
tmp &= ~PCIE_LC_CNTL4__LC_SET_QUIESCE_MASK;
@@ -1674,16 +1664,15 @@ static void cik_pcie_gen3_enable(struct amdgpu_device 
*adev)
speed_cntl &= ~PCIE_LC_SPEED_CNTL__LC_FORCE_DIS_SW_SPEED_CHANGE_MASK;
WREG32_PCIE(ixPCIE_LC_SPEED_CNTL, speed_cntl);
 
-   pcie_capability_read_word(adev->pdev, PCI_EXP_LNKCTL2, &tmp16);
-   tmp16 &= ~PCI_EXP_LNKCTL2_TLS;
-
+   tmp16 = 0;
if (adev->pm.pcie_gen_mask & CAIL_PCIE_LINK_SPEED_SUPPORT_GEN3)
tmp16 |= PCI_EXP_LNKCTL2_TLS_8_0GT; /* gen3 */
else if (adev->pm.pcie_gen_mask & CAIL_PCIE_LINK_SPEED_SUPPORT_GEN2)
tmp16 |= PCI_EXP_LNKCTL2_TLS_5_0GT; /* gen2 */
else
tmp16 |= PCI_EXP_LNKCTL2_TLS_2_5GT; /* gen1 */
-   pcie_capability_write_word(adev->pdev, PCI_EXP_LNKCTL2, tmp16);
+   pcie_capability_clear_and_set_word(adev->pdev, PCI_EXP_LNKCTL2,
+  PCI_EXP_LNKCTL2_TLS, tmp16);
 
speed_cntl = RREG32_PCIE(ixPCIE_LC_SPEED_CNTL);
speed_cntl |= PCIE_LC_SPEED_CNTL__LC_INITIATE_LINK_S

[PATCH 0/3] PCI LNKCTL2 RMW Accessor Cleanup

2024-02-15 Thread Ilpo Järvinen
This series converts open-coded LNKCTL2 RMW accesses to use RMW
accessor. These patches used to be part of PCIe BW controller series
[1] which will require RMW ops to LNKCTL2 be properly locked.

However, since these RMW accessor patches are useful as cleanups on
their own I chose to send them now separately to reduce the size of the
BW controller series.

[1] 
https://lore.kernel.org/linux-pci/20240105112547.7301-1-ilpo.jarvi...@linux.intel.com/

Ilpo Järvinen (3):
  drm/radeon: Use RMW accessors for changing LNKCTL2
  drm/amdgpu: Use RMW accessors for changing LNKCTL2
  RDMA/hfi1: Use RMW accessors for changing LNKCTL2

 drivers/gpu/drm/amd/amdgpu/cik.c  | 41 +++
 drivers/gpu/drm/amd/amdgpu/si.c   | 41 +++
 drivers/gpu/drm/radeon/cik.c  | 40 +++---
 drivers/gpu/drm/radeon/si.c   | 40 +++---
 drivers/infiniband/hw/hfi1/pcie.c | 30 ++
 5 files changed, 68 insertions(+), 124 deletions(-)

-- 
2.39.2



[PATCH 3/3] RDMA/hfi1: Use RMW accessors for changing LNKCTL2

2024-02-15 Thread Ilpo Järvinen
Convert open coded RMW accesses for LNKCTL2 to use
pcie_capability_clear_and_set_word() which makes its easier to
understand what the code tries to do.

LNKCTL2 is not really owned by any driver because it is a collection of
control bits that PCI core might need to touch. RMW accessors already
have support for proper locking for a selected set of registers
(LNKCTL2 is not yet among them but likely will be in the future) to
avoid losing concurrent updates.

Suggested-by: Lukas Wunner 
Signed-off-by: Ilpo Järvinen 
Reviewed-by: Dean Luick 
---
 drivers/infiniband/hw/hfi1/pcie.c | 30 --
 1 file changed, 8 insertions(+), 22 deletions(-)

diff --git a/drivers/infiniband/hw/hfi1/pcie.c 
b/drivers/infiniband/hw/hfi1/pcie.c
index 119ec2f1382b..7133964749f8 100644
--- a/drivers/infiniband/hw/hfi1/pcie.c
+++ b/drivers/infiniband/hw/hfi1/pcie.c
@@ -1207,14 +1207,11 @@ int do_pcie_gen3_transition(struct hfi1_devdata *dd)
(u32)lnkctl2);
/* only write to parent if target is not as high as ours */
if ((lnkctl2 & PCI_EXP_LNKCTL2_TLS) < target_vector) {
-   lnkctl2 &= ~PCI_EXP_LNKCTL2_TLS;
-   lnkctl2 |= target_vector;
-   dd_dev_info(dd, "%s: ..new link control2: 0x%x\n", __func__,
-   (u32)lnkctl2);
-   ret = pcie_capability_write_word(parent,
-PCI_EXP_LNKCTL2, lnkctl2);
+   ret = pcie_capability_clear_and_set_word(parent, 
PCI_EXP_LNKCTL2,
+PCI_EXP_LNKCTL2_TLS,
+target_vector);
if (ret) {
-   dd_dev_err(dd, "Unable to write to PCI config\n");
+   dd_dev_err(dd, "Unable to change parent PCI target 
speed\n");
return_error = 1;
goto done;
}
@@ -1223,22 +1220,11 @@ int do_pcie_gen3_transition(struct hfi1_devdata *dd)
}
 
dd_dev_info(dd, "%s: setting target link speed\n", __func__);
-   ret = pcie_capability_read_word(dd->pcidev, PCI_EXP_LNKCTL2, &lnkctl2);
+   ret = pcie_capability_clear_and_set_word(dd->pcidev, PCI_EXP_LNKCTL2,
+PCI_EXP_LNKCTL2_TLS,
+target_vector);
if (ret) {
-   dd_dev_err(dd, "Unable to read from PCI config\n");
-   return_error = 1;
-   goto done;
-   }
-
-   dd_dev_info(dd, "%s: ..old link control2: 0x%x\n", __func__,
-   (u32)lnkctl2);
-   lnkctl2 &= ~PCI_EXP_LNKCTL2_TLS;
-   lnkctl2 |= target_vector;
-   dd_dev_info(dd, "%s: ..new link control2: 0x%x\n", __func__,
-   (u32)lnkctl2);
-   ret = pcie_capability_write_word(dd->pcidev, PCI_EXP_LNKCTL2, lnkctl2);
-   if (ret) {
-   dd_dev_err(dd, "Unable to write to PCI config\n");
+   dd_dev_err(dd, "Unable to change device PCI target speed\n");
return_error = 1;
goto done;
}
-- 
2.39.2



[PATCH 1/3] drm/radeon: Use RMW accessors for changing LNKCTL2

2024-02-15 Thread Ilpo Järvinen
Convert open coded RMW accesses for LNKCTL2 to use
pcie_capability_clear_and_set_word() which makes its easier to
understand what the code tries to do.

LNKCTL2 is not really owned by any driver because it is a collection of
control bits that PCI core might need to touch. RMW accessors already
have support for proper locking for a selected set of registers
(LNKCTL2 is not yet among them but likely will be in the future) to
avoid losing concurrent updates.

Suggested-by: Lukas Wunner 
Signed-off-by: Ilpo Järvinen 
---
 drivers/gpu/drm/radeon/cik.c | 40 ++--
 drivers/gpu/drm/radeon/si.c  | 40 ++--
 2 files changed, 30 insertions(+), 50 deletions(-)

diff --git a/drivers/gpu/drm/radeon/cik.c b/drivers/gpu/drm/radeon/cik.c
index 10be30366c2b..b5e96a8fc2c1 100644
--- a/drivers/gpu/drm/radeon/cik.c
+++ b/drivers/gpu/drm/radeon/cik.c
@@ -9592,28 +9592,18 @@ static void cik_pcie_gen3_enable(struct radeon_device 
*rdev)
   
PCI_EXP_LNKCTL_HAWD);
 
/* linkctl2 */
-   pcie_capability_read_word(root, PCI_EXP_LNKCTL2,
- &tmp16);
-   tmp16 &= ~(PCI_EXP_LNKCTL2_ENTER_COMP |
-  PCI_EXP_LNKCTL2_TX_MARGIN);
-   tmp16 |= (bridge_cfg2 &
- (PCI_EXP_LNKCTL2_ENTER_COMP |
-  PCI_EXP_LNKCTL2_TX_MARGIN));
-   pcie_capability_write_word(root,
-  PCI_EXP_LNKCTL2,
-  tmp16);
-
-   pcie_capability_read_word(rdev->pdev,
- PCI_EXP_LNKCTL2,
- &tmp16);
-   tmp16 &= ~(PCI_EXP_LNKCTL2_ENTER_COMP |
-  PCI_EXP_LNKCTL2_TX_MARGIN);
-   tmp16 |= (gpu_cfg2 &
- (PCI_EXP_LNKCTL2_ENTER_COMP |
-  PCI_EXP_LNKCTL2_TX_MARGIN));
-   pcie_capability_write_word(rdev->pdev,
-  PCI_EXP_LNKCTL2,
-  tmp16);
+   pcie_capability_clear_and_set_word(root, 
PCI_EXP_LNKCTL2,
+  
PCI_EXP_LNKCTL2_ENTER_COMP |
+  
PCI_EXP_LNKCTL2_TX_MARGIN,
+  bridge_cfg2 |
+  
(PCI_EXP_LNKCTL2_ENTER_COMP |
+   
PCI_EXP_LNKCTL2_TX_MARGIN));
+   pcie_capability_clear_and_set_word(rdev->pdev, 
PCI_EXP_LNKCTL2,
+  
PCI_EXP_LNKCTL2_ENTER_COMP |
+  
PCI_EXP_LNKCTL2_TX_MARGIN,
+  gpu_cfg2 |
+  
(PCI_EXP_LNKCTL2_ENTER_COMP |
+   
PCI_EXP_LNKCTL2_TX_MARGIN));
 
tmp = RREG32_PCIE_PORT(PCIE_LC_CNTL4);
tmp &= ~LC_SET_QUIESCE;
@@ -9627,15 +9617,15 @@ static void cik_pcie_gen3_enable(struct radeon_device 
*rdev)
speed_cntl &= ~LC_FORCE_DIS_SW_SPEED_CHANGE;
WREG32_PCIE_PORT(PCIE_LC_SPEED_CNTL, speed_cntl);
 
-   pcie_capability_read_word(rdev->pdev, PCI_EXP_LNKCTL2, &tmp16);
-   tmp16 &= ~PCI_EXP_LNKCTL2_TLS;
+   tmp16 = 0;
if (speed_cap == PCIE_SPEED_8_0GT)
tmp16 |= PCI_EXP_LNKCTL2_TLS_8_0GT; /* gen3 */
else if (speed_cap == PCIE_SPEED_5_0GT)
tmp16 |= PCI_EXP_LNKCTL2_TLS_5_0GT; /* gen2 */
else
tmp16 |= PCI_EXP_LNKCTL2_TLS_2_5GT; /* gen1 */
-   pcie_capability_write_word(rdev->pdev, PCI_EXP_LNKCTL2, tmp16);
+   pcie_capability_clear_and_set_word(rdev->pdev, PCI_EXP_LNKCTL2,
+  PCI_EXP_LNKCTL2_TLS, tmp16);
 
speed_cntl = RREG32_PCIE_PORT(PCIE_LC_SPEED_CNTL);
speed_cntl |= LC_INITIATE_LINK_SPEED_CHANGE;
diff --git a/drivers/gpu/drm/radeon/si.c b/drivers/gpu/drm/radeon/si.c
index 85e9cba49cec..8eeaea64c75d 100644
--- a/drivers/gpu/drm/radeon/s

RE: [PATCH 1/3] drm/radeon: Use RMW accessors for changing LNKCTL2

2024-02-16 Thread Ilpo Järvinen
On Thu, 15 Feb 2024, Deucher, Alexander wrote:

> [Public]
> 
> > -Original Message-
> > From: Ilpo Järvinen 
> > Sent: Thursday, February 15, 2024 8:32 AM
> > To: Deucher, Alexander ; amd-
> > g...@lists.freedesktop.org; Daniel Vetter ; David Airlie
> > ; Dennis Dalessandro
> > ; dri-
> > de...@lists.freedesktop.org; Jason Gunthorpe ; Leon
> > Romanovsky ; linux-ker...@vger.kernel.org; linux-
> > r...@vger.kernel.org; Pan, Xinhui ; Koenig, Christian
> > 
> > Cc: Ilpo Järvinen ; Lukas Wunner
> > 
> > Subject: [PATCH 1/3] drm/radeon: Use RMW accessors for changing LNKCTL2
> >
> > Convert open coded RMW accesses for LNKCTL2 to use
> > pcie_capability_clear_and_set_word() which makes its easier to understand
> > what the code tries to do.
> >
> > LNKCTL2 is not really owned by any driver because it is a collection of 
> > control
> > bits that PCI core might need to touch. RMW accessors already have support
> > for proper locking for a selected set of registers
> > (LNKCTL2 is not yet among them but likely will be in the future) to avoid 
> > losing
> > concurrent updates.
> >
> > Suggested-by: Lukas Wunner 
> > Signed-off-by: Ilpo Järvinen 
> 
> The radeon and amdgpu patches are:
> Acked-by: Alex Deucher 
> 
> Are you looking for me to pick them up or do you want to land them as 
> part of some larger change?  Either way is fine with me. 

Hi,

You please take them, I intentionally took them apart from the BW 
controller series so they can go through the usual trees, not along with 
the BW controller. (I don't expect the BW controller to be accepted during 
this cycle).

-- 
 i.


Re: [PATCH v5 05/11] drm/amdgpu: Use RMW accessors for changing LNKCTL

2023-08-04 Thread Ilpo Järvinen
On Fri, 21 Jul 2023, Alex Deucher wrote:

> On Fri, Jul 21, 2023 at 4:18 AM Ilpo Järvinen
>  wrote:
> >
> > On Thu, 20 Jul 2023, Bjorn Helgaas wrote:
> >
> > > On Mon, Jul 17, 2023 at 03:04:57PM +0300, Ilpo Järvinen wrote:
> > > > Don't assume that only the driver would be accessing LNKCTL. ASPM
> > > > policy changes can trigger write to LNKCTL outside of driver's control.
> > > > And in the case of upstream bridge, the driver does not even own the
> > > > device it's changing the registers for.
> > > >
> > > > Use RMW capability accessors which do proper locking to avoid losing
> > > > concurrent updates to the register value.
> > > >
> > > > Fixes: a2e73f56fa62 ("drm/amdgpu: Add support for CIK parts")
> > > > Fixes: 62a37553414a ("drm/amdgpu: add si implementation v10")
> > > > Suggested-by: Lukas Wunner 
> > > > Signed-off-by: Ilpo Järvinen 
> > > > Cc: sta...@vger.kernel.org
> > >
> > > Do we have any reports of problems that are fixed by this patch (or by
> > > others in the series)?  If not, I'm not sure it really fits the usual
> > > stable kernel criteria:
> > >
> > > https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/Documentation/process/stable-kernel-rules.rst?id=v6.4
> >
> > I was on the edge with this. The answer to your direct question is no,
> > there are no such reports so it would be okay to leave stable out I think.
> > This applies to all patches in this series.
> >
> > Basically, this series came to be after Lukas noted the potential
> > concurrency issues with how LNKCTL is unprotected when reviewing
> > (internally) my bandwidth controller series. Then I went to look around
> > all LNKCTL usage and realized existing things might alreary have similar
> > issues.
> >
> > Do you want me to send another version w/o cc stable or you'll take care
> > of that?
> >
> > > > ---
> > > >  drivers/gpu/drm/amd/amdgpu/cik.c | 36 +---
> > > >  drivers/gpu/drm/amd/amdgpu/si.c  | 36 +---
> > > >  2 files changed, 20 insertions(+), 52 deletions(-)
> > > >
> > > > diff --git a/drivers/gpu/drm/amd/amdgpu/cik.c 
> > > > b/drivers/gpu/drm/amd/amdgpu/cik.c
> > > > index 5641cf05d856..e63abdf52b6c 100644
> > > > --- a/drivers/gpu/drm/amd/amdgpu/cik.c
> > > > +++ b/drivers/gpu/drm/amd/amdgpu/cik.c
> > > > @@ -1574,17 +1574,8 @@ static void cik_pcie_gen3_enable(struct 
> > > > amdgpu_device *adev)
> > > > u16 bridge_cfg2, gpu_cfg2;
> > > > u32 max_lw, current_lw, tmp;
> > > >
> > > > -   pcie_capability_read_word(root, PCI_EXP_LNKCTL,
> > > > - &bridge_cfg);
> > > > -   pcie_capability_read_word(adev->pdev, 
> > > > PCI_EXP_LNKCTL,
> > > > - &gpu_cfg);
> > > > -
> > > > -   tmp16 = bridge_cfg | PCI_EXP_LNKCTL_HAWD;
> > > > -   pcie_capability_write_word(root, PCI_EXP_LNKCTL, 
> > > > tmp16);
> > > > -
> > > > -   tmp16 = gpu_cfg | PCI_EXP_LNKCTL_HAWD;
> > > > -   pcie_capability_write_word(adev->pdev, 
> > > > PCI_EXP_LNKCTL,
> > > > -  tmp16);
> > > > +   pcie_capability_set_word(root, PCI_EXP_LNKCTL, 
> > > > PCI_EXP_LNKCTL_HAWD);
> > > > +   pcie_capability_set_word(adev->pdev, 
> > > > PCI_EXP_LNKCTL, PCI_EXP_LNKCTL_HAWD);
> > > >
> > > > tmp = RREG32_PCIE(ixPCIE_LC_STATUS1);
> > > > max_lw = (tmp & 
> > > > PCIE_LC_STATUS1__LC_DETECTED_LINK_WIDTH_MASK) >>
> > > > @@ -1637,21 +1628,14 @@ static void cik_pcie_gen3_enable(struct 
> > > > amdgpu_device *adev)
> > > > msleep(100);
> > > >
> > > > /* linkctl */
> > > > -   pcie_capability_read_word(root, 
> > > > PCI_EXP_LNKCTL,
> > > > - &tmp16);
> > > > -   

[PATCH 03/10] drm/amdgpu: Use RMW accessors for changing LNKCTL2

2023-08-17 Thread Ilpo Järvinen
Don't assume that only the driver would be accessing LNKCTL2. In the
case of upstream (parent), the driver does not even own the device it's
changing the registers for.

Use RMW capability accessors which do proper locking to avoid losing
concurrent updates to the register value. This change is also useful as
a cleanup.

Suggested-by: Lukas Wunner 
Signed-off-by: Ilpo Järvinen 
---
 drivers/gpu/drm/amd/amdgpu/cik.c | 41 
 drivers/gpu/drm/amd/amdgpu/si.c  | 41 
 2 files changed, 30 insertions(+), 52 deletions(-)

diff --git a/drivers/gpu/drm/amd/amdgpu/cik.c b/drivers/gpu/drm/amd/amdgpu/cik.c
index e63abdf52b6c..7bcd41996927 100644
--- a/drivers/gpu/drm/amd/amdgpu/cik.c
+++ b/drivers/gpu/drm/amd/amdgpu/cik.c
@@ -1638,28 +1638,18 @@ static void cik_pcie_gen3_enable(struct amdgpu_device 
*adev)
   
PCI_EXP_LNKCTL_HAWD);
 
/* linkctl2 */
-   pcie_capability_read_word(root, PCI_EXP_LNKCTL2,
- &tmp16);
-   tmp16 &= ~(PCI_EXP_LNKCTL2_ENTER_COMP |
-  PCI_EXP_LNKCTL2_TX_MARGIN);
-   tmp16 |= (bridge_cfg2 &
- (PCI_EXP_LNKCTL2_ENTER_COMP |
-  PCI_EXP_LNKCTL2_TX_MARGIN));
-   pcie_capability_write_word(root,
-  PCI_EXP_LNKCTL2,
-  tmp16);
-
-   pcie_capability_read_word(adev->pdev,
- PCI_EXP_LNKCTL2,
- &tmp16);
-   tmp16 &= ~(PCI_EXP_LNKCTL2_ENTER_COMP |
-  PCI_EXP_LNKCTL2_TX_MARGIN);
-   tmp16 |= (gpu_cfg2 &
- (PCI_EXP_LNKCTL2_ENTER_COMP |
-  PCI_EXP_LNKCTL2_TX_MARGIN));
-   pcie_capability_write_word(adev->pdev,
-  PCI_EXP_LNKCTL2,
-  tmp16);
+   pcie_capability_clear_and_set_word(root, 
PCI_EXP_LNKCTL2,
+  
PCI_EXP_LNKCTL2_ENTER_COMP |
+  
PCI_EXP_LNKCTL2_TX_MARGIN,
+  bridge_cfg2 &
+  
(PCI_EXP_LNKCTL2_ENTER_COMP |
+   
PCI_EXP_LNKCTL2_TX_MARGIN));
+   pcie_capability_clear_and_set_word(adev->pdev, 
PCI_EXP_LNKCTL2,
+  
PCI_EXP_LNKCTL2_ENTER_COMP |
+  
PCI_EXP_LNKCTL2_TX_MARGIN,
+  gpu_cfg2 &
+  
(PCI_EXP_LNKCTL2_ENTER_COMP |
+   
PCI_EXP_LNKCTL2_TX_MARGIN));
 
tmp = RREG32_PCIE(ixPCIE_LC_CNTL4);
tmp &= ~PCIE_LC_CNTL4__LC_SET_QUIESCE_MASK;
@@ -1674,16 +1664,15 @@ static void cik_pcie_gen3_enable(struct amdgpu_device 
*adev)
speed_cntl &= ~PCIE_LC_SPEED_CNTL__LC_FORCE_DIS_SW_SPEED_CHANGE_MASK;
WREG32_PCIE(ixPCIE_LC_SPEED_CNTL, speed_cntl);
 
-   pcie_capability_read_word(adev->pdev, PCI_EXP_LNKCTL2, &tmp16);
-   tmp16 &= ~PCI_EXP_LNKCTL2_TLS;
-
+   tmp16 = 0;
if (adev->pm.pcie_gen_mask & CAIL_PCIE_LINK_SPEED_SUPPORT_GEN3)
tmp16 |= PCI_EXP_LNKCTL2_TLS_8_0GT; /* gen3 */
else if (adev->pm.pcie_gen_mask & CAIL_PCIE_LINK_SPEED_SUPPORT_GEN2)
tmp16 |= PCI_EXP_LNKCTL2_TLS_5_0GT; /* gen2 */
else
tmp16 |= PCI_EXP_LNKCTL2_TLS_2_5GT; /* gen1 */
-   pcie_capability_write_word(adev->pdev, PCI_EXP_LNKCTL2, tmp16);
+   pcie_capability_clear_and_set_word(adev->pdev, PCI_EXP_LNKCTL2,
+  PCI_EXP_LNKCTL2_TLS, tmp16);
 
speed_cntl = RREG32_PCIE(ixPCIE_LC_SPEED_CNTL);
speed_cntl |= PCIE_LC_SPEED_CNTL__LC_INITIATE_LINK_SPEED_CHANGE_MASK;
diff --git a/drivers/gpu/drm/amd/amdgpu/si.c b/drivers/gpu/drm/amd/amdgpu/si.c
index 4b81f29e5fd5..8ea60

[PATCH 02/10] drm/radeon: Use RMW accessors for changing LNKCTL2

2023-08-17 Thread Ilpo Järvinen
Don't assume that only the driver would be accessing LNKCTL2. In the
case of upstream (parent), the driver does not even own the device it's
changing the registers for.

Use RMW capability accessors which do proper locking to avoid losing
concurrent updates to the register value. This change is also useful as
a cleanup.

Suggested-by: Lukas Wunner 
Signed-off-by: Ilpo Järvinen 
---
 drivers/gpu/drm/radeon/cik.c | 40 ++--
 drivers/gpu/drm/radeon/si.c  | 40 ++--
 2 files changed, 30 insertions(+), 50 deletions(-)

diff --git a/drivers/gpu/drm/radeon/cik.c b/drivers/gpu/drm/radeon/cik.c
index a6f3c811ceb8..b1558b822f9c 100644
--- a/drivers/gpu/drm/radeon/cik.c
+++ b/drivers/gpu/drm/radeon/cik.c
@@ -9592,28 +9592,18 @@ static void cik_pcie_gen3_enable(struct radeon_device 
*rdev)
   
PCI_EXP_LNKCTL_HAWD);
 
/* linkctl2 */
-   pcie_capability_read_word(root, PCI_EXP_LNKCTL2,
- &tmp16);
-   tmp16 &= ~(PCI_EXP_LNKCTL2_ENTER_COMP |
-  PCI_EXP_LNKCTL2_TX_MARGIN);
-   tmp16 |= (bridge_cfg2 &
- (PCI_EXP_LNKCTL2_ENTER_COMP |
-  PCI_EXP_LNKCTL2_TX_MARGIN));
-   pcie_capability_write_word(root,
-  PCI_EXP_LNKCTL2,
-  tmp16);
-
-   pcie_capability_read_word(rdev->pdev,
- PCI_EXP_LNKCTL2,
- &tmp16);
-   tmp16 &= ~(PCI_EXP_LNKCTL2_ENTER_COMP |
-  PCI_EXP_LNKCTL2_TX_MARGIN);
-   tmp16 |= (gpu_cfg2 &
- (PCI_EXP_LNKCTL2_ENTER_COMP |
-  PCI_EXP_LNKCTL2_TX_MARGIN));
-   pcie_capability_write_word(rdev->pdev,
-  PCI_EXP_LNKCTL2,
-  tmp16);
+   pcie_capability_clear_and_set_word(root, 
PCI_EXP_LNKCTL2,
+  
PCI_EXP_LNKCTL2_ENTER_COMP |
+  
PCI_EXP_LNKCTL2_TX_MARGIN,
+  bridge_cfg2 |
+  
(PCI_EXP_LNKCTL2_ENTER_COMP |
+   
PCI_EXP_LNKCTL2_TX_MARGIN));
+   pcie_capability_clear_and_set_word(rdev->pdev, 
PCI_EXP_LNKCTL2,
+  
PCI_EXP_LNKCTL2_ENTER_COMP |
+  
PCI_EXP_LNKCTL2_TX_MARGIN,
+  gpu_cfg2 |
+  
(PCI_EXP_LNKCTL2_ENTER_COMP |
+   
PCI_EXP_LNKCTL2_TX_MARGIN));
 
tmp = RREG32_PCIE_PORT(PCIE_LC_CNTL4);
tmp &= ~LC_SET_QUIESCE;
@@ -9627,15 +9617,15 @@ static void cik_pcie_gen3_enable(struct radeon_device 
*rdev)
speed_cntl &= ~LC_FORCE_DIS_SW_SPEED_CHANGE;
WREG32_PCIE_PORT(PCIE_LC_SPEED_CNTL, speed_cntl);
 
-   pcie_capability_read_word(rdev->pdev, PCI_EXP_LNKCTL2, &tmp16);
-   tmp16 &= ~PCI_EXP_LNKCTL2_TLS;
+   tmp16 = 0;
if (speed_cap == PCIE_SPEED_8_0GT)
tmp16 |= PCI_EXP_LNKCTL2_TLS_8_0GT; /* gen3 */
else if (speed_cap == PCIE_SPEED_5_0GT)
tmp16 |= PCI_EXP_LNKCTL2_TLS_5_0GT; /* gen2 */
else
tmp16 |= PCI_EXP_LNKCTL2_TLS_2_5GT; /* gen1 */
-   pcie_capability_write_word(rdev->pdev, PCI_EXP_LNKCTL2, tmp16);
+   pcie_capability_clear_and_set_word(rdev->pdev, PCI_EXP_LNKCTL2,
+  PCI_EXP_LNKCTL2_TLS, tmp16);
 
speed_cntl = RREG32_PCIE_PORT(PCIE_LC_SPEED_CNTL);
speed_cntl |= LC_INITIATE_LINK_SPEED_CHANGE;
diff --git a/drivers/gpu/drm/radeon/si.c b/drivers/gpu/drm/radeon/si.c
index a91012447b56..32871ca09a0f 100644
--- a/drivers/gpu/drm/radeon/si.c
+++ b/drivers/gpu/drm/radeon/si.c
@@ -7189,28 +71

RE: [PATCH v5 06/11] drm/radeon: Use RMW accessors for changing LNKCTL

2023-08-21 Thread Ilpo Järvinen
On Fri, 18 Aug 2023, Deucher, Alexander wrote:

> [Public]
> 
> > -Original Message-
> > From: Ilpo Järvinen 
> > Sent: Monday, July 17, 2023 8:05 AM
> > To: linux-...@vger.kernel.org; Bjorn Helgaas ; Lorenzo
> > Pieralisi ; Rob Herring ;
> > Krzysztof Wilczyński ; Emmanuel Grumbach
> > ; Rafael J . Wysocki ;
> > Heiner Kallweit ; Lukas Wunner ;
> > Andy Shevchenko ; Deucher, Alexander
> > ; Koenig, Christian
> > ; Pan, Xinhui ; David
> > Airlie ; Daniel Vetter ; amd-
> > g...@lists.freedesktop.org; dri-de...@lists.freedesktop.org; linux-
> > ker...@vger.kernel.org
> > Cc: Dean Luick ; Jonas Dreßler
> > ; Ilpo Järvinen ;
> > sta...@vger.kernel.org
> > Subject: [PATCH v5 06/11] drm/radeon: Use RMW accessors for changing
> > LNKCTL
> >
> > Don't assume that only the driver would be accessing LNKCTL. ASPM policy
> > changes can trigger write to LNKCTL outside of driver's control.
> > And in the case of upstream bridge, the driver does not even own the device
> > it's changing the registers for.
> >
> > Use RMW capability accessors which do proper locking to avoid losing
> > concurrent updates to the register value.
> >
> > Fixes: 8a7cd27679d0 ("drm/radeon/cik: add support for pcie gen1/2/3
> > switching")
> > Fixes: b9d305dfb66c ("drm/radeon: implement pcie gen2/3 support for SI")
> > Suggested-by: Lukas Wunner 
> > Signed-off-by: Ilpo Järvinen 
> > Cc: sta...@vger.kernel.org
> 
> For this and the amdgpu patch:
> Acked-by: Alex Deucher 
> I'm not sure if this is stable material however.  Is there some issue today?

These were added without Cc stable into pci.git/pcie-rmw.

-- 
 i.


[PATCH v2 02/10] drm/radeon: Use RMW accessors for changing LNKCTL2

2023-09-15 Thread Ilpo Järvinen
Don't assume that only the driver would be accessing LNKCTL2. In the
case of upstream (parent), the driver does not even own the device it's
changing the registers for.

Use RMW capability accessors which do proper locking to avoid losing
concurrent updates to the register value. This change is also useful as
a cleanup.

Suggested-by: Lukas Wunner 
Signed-off-by: Ilpo Järvinen 
---
 drivers/gpu/drm/radeon/cik.c | 40 ++--
 drivers/gpu/drm/radeon/si.c  | 40 ++--
 2 files changed, 30 insertions(+), 50 deletions(-)

diff --git a/drivers/gpu/drm/radeon/cik.c b/drivers/gpu/drm/radeon/cik.c
index 10be30366c2b..b5e96a8fc2c1 100644
--- a/drivers/gpu/drm/radeon/cik.c
+++ b/drivers/gpu/drm/radeon/cik.c
@@ -9592,28 +9592,18 @@ static void cik_pcie_gen3_enable(struct radeon_device 
*rdev)
   
PCI_EXP_LNKCTL_HAWD);
 
/* linkctl2 */
-   pcie_capability_read_word(root, PCI_EXP_LNKCTL2,
- &tmp16);
-   tmp16 &= ~(PCI_EXP_LNKCTL2_ENTER_COMP |
-  PCI_EXP_LNKCTL2_TX_MARGIN);
-   tmp16 |= (bridge_cfg2 &
- (PCI_EXP_LNKCTL2_ENTER_COMP |
-  PCI_EXP_LNKCTL2_TX_MARGIN));
-   pcie_capability_write_word(root,
-  PCI_EXP_LNKCTL2,
-  tmp16);
-
-   pcie_capability_read_word(rdev->pdev,
- PCI_EXP_LNKCTL2,
- &tmp16);
-   tmp16 &= ~(PCI_EXP_LNKCTL2_ENTER_COMP |
-  PCI_EXP_LNKCTL2_TX_MARGIN);
-   tmp16 |= (gpu_cfg2 &
- (PCI_EXP_LNKCTL2_ENTER_COMP |
-  PCI_EXP_LNKCTL2_TX_MARGIN));
-   pcie_capability_write_word(rdev->pdev,
-  PCI_EXP_LNKCTL2,
-  tmp16);
+   pcie_capability_clear_and_set_word(root, 
PCI_EXP_LNKCTL2,
+  
PCI_EXP_LNKCTL2_ENTER_COMP |
+  
PCI_EXP_LNKCTL2_TX_MARGIN,
+  bridge_cfg2 |
+  
(PCI_EXP_LNKCTL2_ENTER_COMP |
+   
PCI_EXP_LNKCTL2_TX_MARGIN));
+   pcie_capability_clear_and_set_word(rdev->pdev, 
PCI_EXP_LNKCTL2,
+  
PCI_EXP_LNKCTL2_ENTER_COMP |
+  
PCI_EXP_LNKCTL2_TX_MARGIN,
+  gpu_cfg2 |
+  
(PCI_EXP_LNKCTL2_ENTER_COMP |
+   
PCI_EXP_LNKCTL2_TX_MARGIN));
 
tmp = RREG32_PCIE_PORT(PCIE_LC_CNTL4);
tmp &= ~LC_SET_QUIESCE;
@@ -9627,15 +9617,15 @@ static void cik_pcie_gen3_enable(struct radeon_device 
*rdev)
speed_cntl &= ~LC_FORCE_DIS_SW_SPEED_CHANGE;
WREG32_PCIE_PORT(PCIE_LC_SPEED_CNTL, speed_cntl);
 
-   pcie_capability_read_word(rdev->pdev, PCI_EXP_LNKCTL2, &tmp16);
-   tmp16 &= ~PCI_EXP_LNKCTL2_TLS;
+   tmp16 = 0;
if (speed_cap == PCIE_SPEED_8_0GT)
tmp16 |= PCI_EXP_LNKCTL2_TLS_8_0GT; /* gen3 */
else if (speed_cap == PCIE_SPEED_5_0GT)
tmp16 |= PCI_EXP_LNKCTL2_TLS_5_0GT; /* gen2 */
else
tmp16 |= PCI_EXP_LNKCTL2_TLS_2_5GT; /* gen1 */
-   pcie_capability_write_word(rdev->pdev, PCI_EXP_LNKCTL2, tmp16);
+   pcie_capability_clear_and_set_word(rdev->pdev, PCI_EXP_LNKCTL2,
+  PCI_EXP_LNKCTL2_TLS, tmp16);
 
speed_cntl = RREG32_PCIE_PORT(PCIE_LC_SPEED_CNTL);
speed_cntl |= LC_INITIATE_LINK_SPEED_CHANGE;
diff --git a/drivers/gpu/drm/radeon/si.c b/drivers/gpu/drm/radeon/si.c
index a91012447b56..32871ca09a0f 100644
--- a/drivers/gpu/drm/radeon/si.c
+++ b/drivers/gpu/drm/radeon/si.c
@@ -7189,28 +71

[PATCH v2 03/10] drm/amdgpu: Use RMW accessors for changing LNKCTL2

2023-09-15 Thread Ilpo Järvinen
Don't assume that only the driver would be accessing LNKCTL2. In the
case of upstream (parent), the driver does not even own the device it's
changing the registers for.

Use RMW capability accessors which do proper locking to avoid losing
concurrent updates to the register value. This change is also useful as
a cleanup.

Suggested-by: Lukas Wunner 
Signed-off-by: Ilpo Järvinen 
---
 drivers/gpu/drm/amd/amdgpu/cik.c | 41 
 drivers/gpu/drm/amd/amdgpu/si.c  | 41 
 2 files changed, 30 insertions(+), 52 deletions(-)

diff --git a/drivers/gpu/drm/amd/amdgpu/cik.c b/drivers/gpu/drm/amd/amdgpu/cik.c
index e63abdf52b6c..7bcd41996927 100644
--- a/drivers/gpu/drm/amd/amdgpu/cik.c
+++ b/drivers/gpu/drm/amd/amdgpu/cik.c
@@ -1638,28 +1638,18 @@ static void cik_pcie_gen3_enable(struct amdgpu_device 
*adev)
   
PCI_EXP_LNKCTL_HAWD);
 
/* linkctl2 */
-   pcie_capability_read_word(root, PCI_EXP_LNKCTL2,
- &tmp16);
-   tmp16 &= ~(PCI_EXP_LNKCTL2_ENTER_COMP |
-  PCI_EXP_LNKCTL2_TX_MARGIN);
-   tmp16 |= (bridge_cfg2 &
- (PCI_EXP_LNKCTL2_ENTER_COMP |
-  PCI_EXP_LNKCTL2_TX_MARGIN));
-   pcie_capability_write_word(root,
-  PCI_EXP_LNKCTL2,
-  tmp16);
-
-   pcie_capability_read_word(adev->pdev,
- PCI_EXP_LNKCTL2,
- &tmp16);
-   tmp16 &= ~(PCI_EXP_LNKCTL2_ENTER_COMP |
-  PCI_EXP_LNKCTL2_TX_MARGIN);
-   tmp16 |= (gpu_cfg2 &
- (PCI_EXP_LNKCTL2_ENTER_COMP |
-  PCI_EXP_LNKCTL2_TX_MARGIN));
-   pcie_capability_write_word(adev->pdev,
-  PCI_EXP_LNKCTL2,
-  tmp16);
+   pcie_capability_clear_and_set_word(root, 
PCI_EXP_LNKCTL2,
+  
PCI_EXP_LNKCTL2_ENTER_COMP |
+  
PCI_EXP_LNKCTL2_TX_MARGIN,
+  bridge_cfg2 &
+  
(PCI_EXP_LNKCTL2_ENTER_COMP |
+   
PCI_EXP_LNKCTL2_TX_MARGIN));
+   pcie_capability_clear_and_set_word(adev->pdev, 
PCI_EXP_LNKCTL2,
+  
PCI_EXP_LNKCTL2_ENTER_COMP |
+  
PCI_EXP_LNKCTL2_TX_MARGIN,
+  gpu_cfg2 &
+  
(PCI_EXP_LNKCTL2_ENTER_COMP |
+   
PCI_EXP_LNKCTL2_TX_MARGIN));
 
tmp = RREG32_PCIE(ixPCIE_LC_CNTL4);
tmp &= ~PCIE_LC_CNTL4__LC_SET_QUIESCE_MASK;
@@ -1674,16 +1664,15 @@ static void cik_pcie_gen3_enable(struct amdgpu_device 
*adev)
speed_cntl &= ~PCIE_LC_SPEED_CNTL__LC_FORCE_DIS_SW_SPEED_CHANGE_MASK;
WREG32_PCIE(ixPCIE_LC_SPEED_CNTL, speed_cntl);
 
-   pcie_capability_read_word(adev->pdev, PCI_EXP_LNKCTL2, &tmp16);
-   tmp16 &= ~PCI_EXP_LNKCTL2_TLS;
-
+   tmp16 = 0;
if (adev->pm.pcie_gen_mask & CAIL_PCIE_LINK_SPEED_SUPPORT_GEN3)
tmp16 |= PCI_EXP_LNKCTL2_TLS_8_0GT; /* gen3 */
else if (adev->pm.pcie_gen_mask & CAIL_PCIE_LINK_SPEED_SUPPORT_GEN2)
tmp16 |= PCI_EXP_LNKCTL2_TLS_5_0GT; /* gen2 */
else
tmp16 |= PCI_EXP_LNKCTL2_TLS_2_5GT; /* gen1 */
-   pcie_capability_write_word(adev->pdev, PCI_EXP_LNKCTL2, tmp16);
+   pcie_capability_clear_and_set_word(adev->pdev, PCI_EXP_LNKCTL2,
+  PCI_EXP_LNKCTL2_TLS, tmp16);
 
speed_cntl = RREG32_PCIE(ixPCIE_LC_SPEED_CNTL);
speed_cntl |= PCIE_LC_SPEED_CNTL__LC_INITIATE_LINK_SPEED_CHANGE_MASK;
diff --git a/drivers/gpu/drm/amd/amdgpu/si.c b/drivers/gpu/drm/amd/amdgpu/si.c
index 4b81f29e5fd5..8ea60

Re: [PATCH 03/15] platform/x86/amd/pmf: Change signature of amd_pmf_set_dram_addr

2023-09-26 Thread Ilpo Järvinen
On Fri, 22 Sep 2023, Shyam Sundar S K wrote:

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

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

This says nothing about the move of allocation.

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

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

-- 
 i.



Re: [PATCH 02/15] platform/x86/amd/pmf: Add support PMF-TA interaction

2023-09-26 Thread Ilpo Järvinen
On Fri, 22 Sep 2023, Shyam Sundar S K wrote:

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

I suppose double _ is not intentional?

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

Add comma to the second line too.

Did you mean to have double _?

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

No __func__s please.

> + return -EINVAL;
> + }
> +
> + return 0;
> +}
> +
> +static int amd_pmf_invoke_cmd_init(struct amd_pmf_dev *dev)
> +{
> + struct ta_pmf_shared_memory *ta_sm = NULL;
> + struct tee_param param[MAX_TEE_PARAM];
> + struct tee_ioctl_invoke_arg arg;
> + int ret = 0;
> +
> + if (!dev->tee

Re: [PATCH 05/15] platform/x86/amd/pmf: change debugfs init sequence

2023-09-26 Thread Ilpo Järvinen
On Fri, 22 Sep 2023, Shyam Sundar S K wrote:

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

Please answer to why? question too here.

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

-- 
 i.



Re: [PATCH 01/15] platform/x86/amd/pmf: Add PMF TEE interface

2023-09-26 Thread Ilpo Järvinen
On Fri, 22 Sep 2023, Shyam Sundar S K wrote:

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

Re: [PATCH 04/15] platform/x86/amd/pmf: Add support for PMF Policy Binary

2023-09-26 Thread Ilpo Järvinen
On Fri, 22 Sep 2023, Shyam Sundar S K wrote:

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

Re: [PATCH 06/15] platform/x86/amd/pmf: Add support to get inputs from other subsystems

2023-09-26 Thread Ilpo Järvinen
On Fri, 22 Sep 2023, Shyam Sundar S K wrote:

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

Is this safe from overflow?

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

Re: [PATCH 04/15] platform/x86/amd/pmf: Add support for PMF Policy Binary

2023-09-27 Thread Ilpo Järvinen
On Fri, 22 Sep 2023, Shyam Sundar S K wrote:

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

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

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

The %d does not match u32.

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

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

> + }
> + break;
> +
> + case PMF_POLICY_SPPT:
> + if (dev->prev_data->sppt != val) {
> + amd_pmf_send_cmd(dev, SET_SPPT, false, val, 
> NULL);
> + dev_dbg(dev->dev, "update SPPT : %d\n", val);
> + dev->prev_data->sppt = val;
> + }
> + break;
> +
> + case PMF_POLICY_FPPT:
> + if (dev->prev_data->fppt != val) {
> + amd_pmf_send_cmd(dev, SET_FPPT, false, val, 
> NULL);
> + dev_dbg(dev->dev, "update FPPT : %d\n", val);
> + dev->prev_data->fppt = val;
> + }
> + break;
> +
> + case PMF_POLICY_SPPT_APU_ONLY:
> + if (dev->prev_data->sppt_apuonly != val) {
> + amd_pmf_send_cmd(dev, SET_SPPT_APU_ONLY, false, 
> val, NULL);
> + dev_dbg(dev->dev, "update SPPT_APU_ONLY : 
> %d\n"

Re: [PATCH 09/15] platform/x86/amd/pmf: Add facility to dump TA inputs

2023-09-27 Thread Ilpo Järvinen
On Fri, 22 Sep 2023, Shyam Sundar S K wrote:

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

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

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

Re: [PATCH 08/15] platform/x86/amd/pmf: Add support to update system state

2023-09-27 Thread Ilpo Järvinen
On Fri, 22 Sep 2023, Shyam Sundar S K wrote:

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

Re: [PATCH 07/15] platform/x86/amd/pmf: Add support update p3t limit

2023-09-27 Thread Ilpo Järvinen
On Fri, 22 Sep 2023, Shyam Sundar S K wrote:

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

%d vs u32

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

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


-- 
 i.



Re: [PATCH 10/15] platform/x86/amd/pmf: Add capability to sideload of policy binary

2023-09-27 Thread Ilpo Järvinen
On Fri, 22 Sep 2023, Shyam Sundar S K wrote:

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

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

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

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

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

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

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

-- 
 i.



Re: [PATCH 12/15] platform/x86/amd/pmf: Add PMF-AMDGPU get interface

2023-09-27 Thread Ilpo Järvinen
On Fri, 22 Sep 2023, Shyam Sundar S K wrote:

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

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

> + if (connector->status == connector_status_connected) {
> + pmf->con_status[i] = connector->status;
> + pmf->connector_type[i] = connector->connector_type;
> + pmf->display_count++;
> + }
> + i++;
> + }
> + drm_connector_list_iter_end(&iter);
> + mutex_unlock(&mode_config->mutex);
> +
> + return 0;
> +}
> +EXPORT_SYMBOL_GPL(amd_pmf_get_gfx_data);
> diff --git a/drivers/platform/x86/amd/pmf/Kconfig 
> b/drivers/pla

Re: [PATCH 13/15] platform/x86/amd/pmf: Add PMF-AMDGPU set interface

2023-09-27 Thread Ilpo Järvinen
On Fri, 22 Sep 2023, Shyam Sundar S K wrote:

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

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

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

-- 
 i.



Re: [PATCH 14/15] platform/x86/amd/pmf: Add PMF-AMDSFH interface for HPD

2023-09-27 Thread Ilpo Järvinen
On Fri, 22 Sep 2023, Shyam Sundar S K wrote:

> From: Basavaraj Natikar 
> 
> 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 
> Signed-off-by: Shyam Sundar S K 
> Signed-off-by: Basavaraj Natikar 
> ---
>  drivers/hid/amd-sfh-hid/amd_sfh_common.h  |  5 
>  drivers/hid/amd-sfh-hid/sfh1_1/amd_sfh_desc.c |  2 +-
>  drivers/hid/amd-sfh-hid/sfh1_1/amd_sfh_init.c | 11 
>  .../amd-sfh-hid/sfh1_1/amd_sfh_interface.c| 28 +++
>  .../amd-sfh-hid/sfh1_1/amd_sfh_interface.h|  1 +
>  drivers/platform/x86/amd/pmf/spc.c| 21 ++
>  include/linux/amd-pmf-io.h| 22 ++-
>  7 files changed, 88 insertions(+), 2 deletions(-)
> 
> diff --git a/drivers/hid/amd-sfh-hid/amd_sfh_common.h 
> b/drivers/hid/amd-sfh-hid/amd_sfh_common.h
> index 2643bb14fee2..cd57037bf217 100644
> --- a/drivers/hid/amd-sfh-hid/amd_sfh_common.h
> +++ b/drivers/hid/amd-sfh-hid/amd_sfh_common.h
> @@ -37,6 +37,10 @@ struct amd_mp2_sensor_info {
>   dma_addr_t dma_address;
>  };
>  
> +struct sfh_dev_status {
> + bool is_hpd_present;
> +};
> +
>  struct amd_mp2_dev {
>   struct pci_dev *pdev;
>   struct amdtp_cl_data *cl_data;
> @@ -47,6 +51,7 @@ struct amd_mp2_dev {
>   struct amd_input_data in_data;
>   /* mp2 active control status */
>   u32 mp2_acs;
> + struct sfh_dev_status dev_en;
>  };
>  
>  struct amd_mp2_ops {
> diff --git a/drivers/hid/amd-sfh-hid/sfh1_1/amd_sfh_desc.c 
> b/drivers/hid/amd-sfh-hid/sfh1_1/amd_sfh_desc.c
> index 06bdcf072d10..d7467c41ad3b 100644
> --- a/drivers/hid/amd-sfh-hid/sfh1_1/amd_sfh_desc.c
> +++ b/drivers/hid/amd-sfh-hid/sfh1_1/amd_sfh_desc.c
> @@ -132,7 +132,7 @@ static void get_common_inputs(struct 
> common_input_property *common, int report_i
>   common->event_type = HID_USAGE_SENSOR_EVENT_DATA_UPDATED_ENUM;
>  }
>  
> -static int float_to_int(u32 flt32_val)
> +int float_to_int(u32 flt32_val)

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

>  {
>   int fraction, shift, mantissa, sign, exp, zeropre;
>  
> diff --git a/drivers/hid/amd-sfh-hid/sfh1_1/amd_sfh_init.c 
> b/drivers/hid/amd-sfh-hid/sfh1_1/amd_sfh_init.c
> index e9c6413af24a..9c623456ee12 100644
> --- a/drivers/hid/amd-sfh-hid/sfh1_1/amd_sfh_init.c
> +++ b/drivers/hid/amd-sfh-hid/sfh1_1/amd_sfh_init.c
> @@ -73,6 +73,12 @@ static int amd_sfh_hid_client_deinit(struct amd_mp2_dev 
> *privdata)
>   int i, status;
>  
>   for (i = 0; i < cl_data->num_hid_devices; i++) {
> + switch (cl_data->sensor_idx[i]) {
> + case HPD_IDX:
> + privdata->dev_en.is_hpd_present = false;
> + break;
> + }
> +
>   if (cl_data->sensor_sts[i] == SENSOR_ENABLED) {
>   privdata->mp2_ops->stop(privdata, 
> cl_data->sensor_idx[i]);
>   status = amd_sfh_wait_for_response
> @@ -178,6 +184,11 @@ static int amd_sfh1_1_hid_client_init(struct amd_mp2_dev 
> *privdata)
>   rc = amdtp_hid_probe(i, cl_data);
>   if (rc)
>   goto cleanup;
> + switch (cl_data->sensor_idx[i]) {
> + case HPD_IDX:
> + privdata->dev_en.is_hpd_present = true;
> + break;
> + }
>   }
>   dev_dbg(dev, "sid 0x%x (%s) status 0x%x\n",
>   cl_data->sensor_idx[i], 
> get_sensor_name(cl_data->sensor_idx[i]),
> diff --git a/drivers/hid/amd-sfh-hid/sfh1_1/amd_sfh_interface.c 
> b/drivers/hid/amd-sfh-hid/sfh1_1/amd_sfh_interface.c
> index 4f81ef2d4f56..63a5bbca5a09 100644
> --- a/drivers/hid/amd-sfh-hid/sfh1_1/amd_sfh_interface.c
> +++ b/drivers/hid/amd-sfh-hid/sfh1_1/amd_sfh_interface.c
> @@ -7,11 +7,14 @@
>   *
>   * Author: Basavaraj Natikar 
>   */
> +#include 
>  #include 
>  #include 
>  
>  #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

Re: [PATCH 15/15] platform/x86/amd/pmf: Add PMF-AMDSFH interface for ALS

2023-09-27 Thread Ilpo Järvinen
On Fri, 22 Sep 2023, Shyam Sundar S K wrote:

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

%d vs u32

>   dev_dbg(dev->dev, " TA inputs END \n");
>  }
>  #else
> @@ -161,6 +162,10 @@ static void amd_pmf_get_sensor_info(struct amd_pmf_dev 
> *dev, struct ta_pmf_enact
>  {
>   struct amd_sfh_info sfh_info;
>  
> + /* get ALS data */
> + amd_get_sfh_info(&sfh_info, MT_ALS);
> + in->ev_info.ambient_light = sfh_info.ambient_light;
> +
>   /* get HPD data */
>   amd_get_sfh_info(&sfh_info, MT_HPD);
>   switch (sfh_info.user_present) {
> diff --git a/include/linux/amd-pmf-io.h b/include/linux/amd-pmf-io.h
> index 4f82973f6ad2..dac0af573a16 100644
> --- a/include/linux/amd-pmf-io.h
> +++ b/include/linux/amd-pmf-io.h
>

[PATCH v3 02/10] drm/radeon: Use RMW accessors for changing LNKCTL2

2023-09-29 Thread Ilpo Järvinen
Don't assume that only the driver would be accessing LNKCTL2. In the
case of upstream (parent), the driver does not even own the device it's
changing the registers for.

Use RMW capability accessors which do proper locking to avoid losing
concurrent updates to the register value. This change is also useful as
a cleanup.

Suggested-by: Lukas Wunner 
Signed-off-by: Ilpo Järvinen 
---
 drivers/gpu/drm/radeon/cik.c | 40 ++--
 drivers/gpu/drm/radeon/si.c  | 40 ++--
 2 files changed, 30 insertions(+), 50 deletions(-)

diff --git a/drivers/gpu/drm/radeon/cik.c b/drivers/gpu/drm/radeon/cik.c
index 10be30366c2b..b5e96a8fc2c1 100644
--- a/drivers/gpu/drm/radeon/cik.c
+++ b/drivers/gpu/drm/radeon/cik.c
@@ -9592,28 +9592,18 @@ static void cik_pcie_gen3_enable(struct radeon_device 
*rdev)
   
PCI_EXP_LNKCTL_HAWD);
 
/* linkctl2 */
-   pcie_capability_read_word(root, PCI_EXP_LNKCTL2,
- &tmp16);
-   tmp16 &= ~(PCI_EXP_LNKCTL2_ENTER_COMP |
-  PCI_EXP_LNKCTL2_TX_MARGIN);
-   tmp16 |= (bridge_cfg2 &
- (PCI_EXP_LNKCTL2_ENTER_COMP |
-  PCI_EXP_LNKCTL2_TX_MARGIN));
-   pcie_capability_write_word(root,
-  PCI_EXP_LNKCTL2,
-  tmp16);
-
-   pcie_capability_read_word(rdev->pdev,
- PCI_EXP_LNKCTL2,
- &tmp16);
-   tmp16 &= ~(PCI_EXP_LNKCTL2_ENTER_COMP |
-  PCI_EXP_LNKCTL2_TX_MARGIN);
-   tmp16 |= (gpu_cfg2 &
- (PCI_EXP_LNKCTL2_ENTER_COMP |
-  PCI_EXP_LNKCTL2_TX_MARGIN));
-   pcie_capability_write_word(rdev->pdev,
-  PCI_EXP_LNKCTL2,
-  tmp16);
+   pcie_capability_clear_and_set_word(root, 
PCI_EXP_LNKCTL2,
+  
PCI_EXP_LNKCTL2_ENTER_COMP |
+  
PCI_EXP_LNKCTL2_TX_MARGIN,
+  bridge_cfg2 |
+  
(PCI_EXP_LNKCTL2_ENTER_COMP |
+   
PCI_EXP_LNKCTL2_TX_MARGIN));
+   pcie_capability_clear_and_set_word(rdev->pdev, 
PCI_EXP_LNKCTL2,
+  
PCI_EXP_LNKCTL2_ENTER_COMP |
+  
PCI_EXP_LNKCTL2_TX_MARGIN,
+  gpu_cfg2 |
+  
(PCI_EXP_LNKCTL2_ENTER_COMP |
+   
PCI_EXP_LNKCTL2_TX_MARGIN));
 
tmp = RREG32_PCIE_PORT(PCIE_LC_CNTL4);
tmp &= ~LC_SET_QUIESCE;
@@ -9627,15 +9617,15 @@ static void cik_pcie_gen3_enable(struct radeon_device 
*rdev)
speed_cntl &= ~LC_FORCE_DIS_SW_SPEED_CHANGE;
WREG32_PCIE_PORT(PCIE_LC_SPEED_CNTL, speed_cntl);
 
-   pcie_capability_read_word(rdev->pdev, PCI_EXP_LNKCTL2, &tmp16);
-   tmp16 &= ~PCI_EXP_LNKCTL2_TLS;
+   tmp16 = 0;
if (speed_cap == PCIE_SPEED_8_0GT)
tmp16 |= PCI_EXP_LNKCTL2_TLS_8_0GT; /* gen3 */
else if (speed_cap == PCIE_SPEED_5_0GT)
tmp16 |= PCI_EXP_LNKCTL2_TLS_5_0GT; /* gen2 */
else
tmp16 |= PCI_EXP_LNKCTL2_TLS_2_5GT; /* gen1 */
-   pcie_capability_write_word(rdev->pdev, PCI_EXP_LNKCTL2, tmp16);
+   pcie_capability_clear_and_set_word(rdev->pdev, PCI_EXP_LNKCTL2,
+  PCI_EXP_LNKCTL2_TLS, tmp16);
 
speed_cntl = RREG32_PCIE_PORT(PCIE_LC_SPEED_CNTL);
speed_cntl |= LC_INITIATE_LINK_SPEED_CHANGE;
diff --git a/drivers/gpu/drm/radeon/si.c b/drivers/gpu/drm/radeon/si.c
index a91012447b56..32871ca09a0f 100644
--- a/drivers/gpu/drm/radeon/si.c
+++ b/drivers/gpu/drm/radeon/si.c
@@ -7189,28 +71

[PATCH v3 03/10] drm/amdgpu: Use RMW accessors for changing LNKCTL2

2023-09-29 Thread Ilpo Järvinen
Don't assume that only the driver would be accessing LNKCTL2. In the
case of upstream (parent), the driver does not even own the device it's
changing the registers for.

Use RMW capability accessors which do proper locking to avoid losing
concurrent updates to the register value. This change is also useful as
a cleanup.

Suggested-by: Lukas Wunner 
Signed-off-by: Ilpo Järvinen 
---
 drivers/gpu/drm/amd/amdgpu/cik.c | 41 
 drivers/gpu/drm/amd/amdgpu/si.c  | 41 
 2 files changed, 30 insertions(+), 52 deletions(-)

diff --git a/drivers/gpu/drm/amd/amdgpu/cik.c b/drivers/gpu/drm/amd/amdgpu/cik.c
index e63abdf52b6c..7bcd41996927 100644
--- a/drivers/gpu/drm/amd/amdgpu/cik.c
+++ b/drivers/gpu/drm/amd/amdgpu/cik.c
@@ -1638,28 +1638,18 @@ static void cik_pcie_gen3_enable(struct amdgpu_device 
*adev)
   
PCI_EXP_LNKCTL_HAWD);
 
/* linkctl2 */
-   pcie_capability_read_word(root, PCI_EXP_LNKCTL2,
- &tmp16);
-   tmp16 &= ~(PCI_EXP_LNKCTL2_ENTER_COMP |
-  PCI_EXP_LNKCTL2_TX_MARGIN);
-   tmp16 |= (bridge_cfg2 &
- (PCI_EXP_LNKCTL2_ENTER_COMP |
-  PCI_EXP_LNKCTL2_TX_MARGIN));
-   pcie_capability_write_word(root,
-  PCI_EXP_LNKCTL2,
-  tmp16);
-
-   pcie_capability_read_word(adev->pdev,
- PCI_EXP_LNKCTL2,
- &tmp16);
-   tmp16 &= ~(PCI_EXP_LNKCTL2_ENTER_COMP |
-  PCI_EXP_LNKCTL2_TX_MARGIN);
-   tmp16 |= (gpu_cfg2 &
- (PCI_EXP_LNKCTL2_ENTER_COMP |
-  PCI_EXP_LNKCTL2_TX_MARGIN));
-   pcie_capability_write_word(adev->pdev,
-  PCI_EXP_LNKCTL2,
-  tmp16);
+   pcie_capability_clear_and_set_word(root, 
PCI_EXP_LNKCTL2,
+  
PCI_EXP_LNKCTL2_ENTER_COMP |
+  
PCI_EXP_LNKCTL2_TX_MARGIN,
+  bridge_cfg2 &
+  
(PCI_EXP_LNKCTL2_ENTER_COMP |
+   
PCI_EXP_LNKCTL2_TX_MARGIN));
+   pcie_capability_clear_and_set_word(adev->pdev, 
PCI_EXP_LNKCTL2,
+  
PCI_EXP_LNKCTL2_ENTER_COMP |
+  
PCI_EXP_LNKCTL2_TX_MARGIN,
+  gpu_cfg2 &
+  
(PCI_EXP_LNKCTL2_ENTER_COMP |
+   
PCI_EXP_LNKCTL2_TX_MARGIN));
 
tmp = RREG32_PCIE(ixPCIE_LC_CNTL4);
tmp &= ~PCIE_LC_CNTL4__LC_SET_QUIESCE_MASK;
@@ -1674,16 +1664,15 @@ static void cik_pcie_gen3_enable(struct amdgpu_device 
*adev)
speed_cntl &= ~PCIE_LC_SPEED_CNTL__LC_FORCE_DIS_SW_SPEED_CHANGE_MASK;
WREG32_PCIE(ixPCIE_LC_SPEED_CNTL, speed_cntl);
 
-   pcie_capability_read_word(adev->pdev, PCI_EXP_LNKCTL2, &tmp16);
-   tmp16 &= ~PCI_EXP_LNKCTL2_TLS;
-
+   tmp16 = 0;
if (adev->pm.pcie_gen_mask & CAIL_PCIE_LINK_SPEED_SUPPORT_GEN3)
tmp16 |= PCI_EXP_LNKCTL2_TLS_8_0GT; /* gen3 */
else if (adev->pm.pcie_gen_mask & CAIL_PCIE_LINK_SPEED_SUPPORT_GEN2)
tmp16 |= PCI_EXP_LNKCTL2_TLS_5_0GT; /* gen2 */
else
tmp16 |= PCI_EXP_LNKCTL2_TLS_2_5GT; /* gen1 */
-   pcie_capability_write_word(adev->pdev, PCI_EXP_LNKCTL2, tmp16);
+   pcie_capability_clear_and_set_word(adev->pdev, PCI_EXP_LNKCTL2,
+  PCI_EXP_LNKCTL2_TLS, tmp16);
 
speed_cntl = RREG32_PCIE(ixPCIE_LC_SPEED_CNTL);
speed_cntl |= PCIE_LC_SPEED_CNTL__LC_INITIATE_LINK_SPEED_CHANGE_MASK;
diff --git a/drivers/gpu/drm/amd/amdgpu/si.c b/drivers/gpu/drm/amd/amdgpu/si.c
index 4b81f29e5fd5..8ea60

Re: [PATCH 06/15] platform/x86/amd/pmf: Add support to get inputs from other subsystems

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

[PATCH 05/17] drm/radeon: Use pcie_lnkctl{, 2}_clear_and_set() for changing LNKCTL{, 2}

2023-05-11 Thread Ilpo Järvinen
Don't assume that only the driver would be accessing LNKCTL/LNKCTL2.
ASPM policy changes can trigger write to LNKCTL outside of driver's
control. And in the case of upstream (parent), the driver does not even
own the device it's changing the registers for.

Use pcie_lnkctl_clear_and_set() and pcie_lnkctl2_clear_and_set() which
do proper locking to avoid losing concurrent updates to the register
value.

Suggested-by: Lukas Wunner 
Signed-off-by: Ilpo Järvinen 
---
 drivers/gpu/drm/radeon/cik.c | 71 ++-
 drivers/gpu/drm/radeon/si.c  | 72 ++--
 2 files changed, 40 insertions(+), 103 deletions(-)

diff --git a/drivers/gpu/drm/radeon/cik.c b/drivers/gpu/drm/radeon/cik.c
index 5819737c21c6..c592b3d68ae6 100644
--- a/drivers/gpu/drm/radeon/cik.c
+++ b/drivers/gpu/drm/radeon/cik.c
@@ -9534,17 +9534,8 @@ static void cik_pcie_gen3_enable(struct radeon_device 
*rdev)
u16 bridge_cfg2, gpu_cfg2;
u32 max_lw, current_lw, tmp;
 
-   pcie_capability_read_word(root, PCI_EXP_LNKCTL,
- &bridge_cfg);
-   pcie_capability_read_word(rdev->pdev, PCI_EXP_LNKCTL,
- &gpu_cfg);
-
-   tmp16 = bridge_cfg | PCI_EXP_LNKCTL_HAWD;
-   pcie_capability_write_word(root, PCI_EXP_LNKCTL, tmp16);
-
-   tmp16 = gpu_cfg | PCI_EXP_LNKCTL_HAWD;
-   pcie_capability_write_word(rdev->pdev, PCI_EXP_LNKCTL,
-  tmp16);
+   pcie_lnkctl_clear_and_set(root, 0, PCI_EXP_LNKCTL_HAWD);
+   pcie_lnkctl_clear_and_set(rdev->pdev, 0, 
PCI_EXP_LNKCTL_HAWD);
 
tmp = RREG32_PCIE_PORT(PCIE_LC_STATUS1);
max_lw = (tmp & LC_DETECTED_LINK_WIDTH_MASK) >> 
LC_DETECTED_LINK_WIDTH_SHIFT;
@@ -9591,45 +9582,24 @@ static void cik_pcie_gen3_enable(struct radeon_device 
*rdev)
msleep(100);
 
/* linkctl */
-   pcie_capability_read_word(root, PCI_EXP_LNKCTL,
- &tmp16);
-   tmp16 &= ~PCI_EXP_LNKCTL_HAWD;
-   tmp16 |= (bridge_cfg & PCI_EXP_LNKCTL_HAWD);
-   pcie_capability_write_word(root, PCI_EXP_LNKCTL,
-  tmp16);
-
-   pcie_capability_read_word(rdev->pdev,
- PCI_EXP_LNKCTL,
- &tmp16);
-   tmp16 &= ~PCI_EXP_LNKCTL_HAWD;
-   tmp16 |= (gpu_cfg & PCI_EXP_LNKCTL_HAWD);
-   pcie_capability_write_word(rdev->pdev,
-  PCI_EXP_LNKCTL,
-  tmp16);
+   pcie_lnkctl_clear_and_set(root, 
PCI_EXP_LNKCTL_HAWD,
+bridge_cfg & 
PCI_EXP_LNKCTL_HAWD);
+   pcie_lnkctl_clear_and_set(rdev->pdev, 
PCI_EXP_LNKCTL_HAWD,
+gpu_cfg & 
PCI_EXP_LNKCTL_HAWD);
 
/* linkctl2 */
-   pcie_capability_read_word(root, PCI_EXP_LNKCTL2,
- &tmp16);
-   tmp16 &= ~(PCI_EXP_LNKCTL2_ENTER_COMP |
-  PCI_EXP_LNKCTL2_TX_MARGIN);
-   tmp16 |= (bridge_cfg2 &
- (PCI_EXP_LNKCTL2_ENTER_COMP |
-  PCI_EXP_LNKCTL2_TX_MARGIN));
-   pcie_capability_write_word(root,
-  PCI_EXP_LNKCTL2,
-  tmp16);
-
-   pcie_capability_read_word(rdev->pdev,
- PCI_EXP_LNKCTL2,
- &tmp16);
-   tmp16 &= ~(PCI_EXP_LNKCTL2_ENTER_COMP |
-  PCI_EXP_LNKCTL2_TX_MARGIN);
-   tmp16 |= (gpu_cfg2 &
- (PCI_EXP_LNKCTL2_ENTER_COMP |
-  PCI_EXP_LNKCTL2_TX_MARGIN));
-   pci

[PATCH 04/17] drm/amdgpu: Use pcie_lnkctl{, 2}_clear_and_set() for changing LNKCTL{, 2}

2023-05-11 Thread Ilpo Järvinen
Don't assume that only the driver would be accessing LNKCTL/LNKCTL2.
ASPM policy changes can trigger write to LNKCTL outside of driver's
control. And in the case of upstream (parent), the driver does not even
own the device it's changing the registers for.

Use pcie_lnkctl_clear_and_set() and pcie_lnkctl2_clear_and_set() which
do proper locking to avoid losing concurrent updates to the register
value.

Suggested-by: Lukas Wunner 
Signed-off-by: Ilpo Järvinen 
---
 drivers/gpu/drm/amd/amdgpu/cik.c | 72 +--
 drivers/gpu/drm/amd/amdgpu/si.c  | 74 +---
 2 files changed, 41 insertions(+), 105 deletions(-)

diff --git a/drivers/gpu/drm/amd/amdgpu/cik.c b/drivers/gpu/drm/amd/amdgpu/cik.c
index de6d10390ab2..f9f2c28c7125 100644
--- a/drivers/gpu/drm/amd/amdgpu/cik.c
+++ b/drivers/gpu/drm/amd/amdgpu/cik.c
@@ -1574,17 +1574,8 @@ static void cik_pcie_gen3_enable(struct amdgpu_device 
*adev)
u16 bridge_cfg2, gpu_cfg2;
u32 max_lw, current_lw, tmp;
 
-   pcie_capability_read_word(root, PCI_EXP_LNKCTL,
- &bridge_cfg);
-   pcie_capability_read_word(adev->pdev, PCI_EXP_LNKCTL,
- &gpu_cfg);
-
-   tmp16 = bridge_cfg | PCI_EXP_LNKCTL_HAWD;
-   pcie_capability_write_word(root, PCI_EXP_LNKCTL, tmp16);
-
-   tmp16 = gpu_cfg | PCI_EXP_LNKCTL_HAWD;
-   pcie_capability_write_word(adev->pdev, PCI_EXP_LNKCTL,
-  tmp16);
+   pcie_lnkctl_clear_and_set(root, 0, PCI_EXP_LNKCTL_HAWD);
+   pcie_lnkctl_clear_and_set(adev->pdev, 0, 
PCI_EXP_LNKCTL_HAWD);
 
tmp = RREG32_PCIE(ixPCIE_LC_STATUS1);
max_lw = (tmp & 
PCIE_LC_STATUS1__LC_DETECTED_LINK_WIDTH_MASK) >>
@@ -1637,45 +1628,24 @@ static void cik_pcie_gen3_enable(struct amdgpu_device 
*adev)
msleep(100);
 
/* linkctl */
-   pcie_capability_read_word(root, PCI_EXP_LNKCTL,
- &tmp16);
-   tmp16 &= ~PCI_EXP_LNKCTL_HAWD;
-   tmp16 |= (bridge_cfg & PCI_EXP_LNKCTL_HAWD);
-   pcie_capability_write_word(root, PCI_EXP_LNKCTL,
-  tmp16);
-
-   pcie_capability_read_word(adev->pdev,
- PCI_EXP_LNKCTL,
- &tmp16);
-   tmp16 &= ~PCI_EXP_LNKCTL_HAWD;
-   tmp16 |= (gpu_cfg & PCI_EXP_LNKCTL_HAWD);
-   pcie_capability_write_word(adev->pdev,
-  PCI_EXP_LNKCTL,
-  tmp16);
+   pcie_lnkctl_clear_and_set(root, 
PCI_EXP_LNKCTL_HAWD,
+ bridge_cfg & 
PCI_EXP_LNKCTL_HAWD);
+   pcie_lnkctl_clear_and_set(adev->pdev, 
PCI_EXP_LNKCTL_HAWD,
+ gpu_cfg & 
PCI_EXP_LNKCTL_HAWD);
 
/* linkctl2 */
-   pcie_capability_read_word(root, PCI_EXP_LNKCTL2,
- &tmp16);
-   tmp16 &= ~(PCI_EXP_LNKCTL2_ENTER_COMP |
-  PCI_EXP_LNKCTL2_TX_MARGIN);
-   tmp16 |= (bridge_cfg2 &
- (PCI_EXP_LNKCTL2_ENTER_COMP |
-  PCI_EXP_LNKCTL2_TX_MARGIN));
-   pcie_capability_write_word(root,
-  PCI_EXP_LNKCTL2,
-  tmp16);
-
-   pcie_capability_read_word(adev->pdev,
- PCI_EXP_LNKCTL2,
- &tmp16);
-   tmp16 &= ~(PCI_EXP_LNKCTL2_ENTER_COMP |
-  PCI_EXP_LNKCTL2_TX_MARGIN);
-   tmp16 |= (gpu_cfg2 &
- (PCI_EXP_LNKCTL2_ENTER_COMP |
-  PCI_EXP_LNKCTL2_TX_MARGIN));
-   pci

[PATCH v2 5/9] drm/radeon: Use RMW accessors for changing LNKCTL

2023-05-17 Thread Ilpo Järvinen
Don't assume that only the driver would be accessing LNKCTL. ASPM
policy changes can trigger write to LNKCTL outside of driver's control.
And in the case of upstream bridge, the driver does not even own the
device it's changing the registers for.

Use RMW capability accessors which do proper locking to avoid losing
concurrent updates to the register value.

Fixes: 8a7cd27679d0 ("drm/radeon/cik: add support for pcie gen1/2/3 switching")
Fixes: b9d305dfb66c ("drm/radeon: implement pcie gen2/3 support for SI")
Suggested-by: Lukas Wunner 
Signed-off-by: Ilpo Järvinen 
Cc: sta...@vger.kernel.org
---
 drivers/gpu/drm/radeon/cik.c | 36 ++-
 drivers/gpu/drm/radeon/si.c  | 37 ++--
 2 files changed, 20 insertions(+), 53 deletions(-)

diff --git a/drivers/gpu/drm/radeon/cik.c b/drivers/gpu/drm/radeon/cik.c
index 5819737c21c6..a6f3c811ceb8 100644
--- a/drivers/gpu/drm/radeon/cik.c
+++ b/drivers/gpu/drm/radeon/cik.c
@@ -9534,17 +9534,8 @@ static void cik_pcie_gen3_enable(struct radeon_device 
*rdev)
u16 bridge_cfg2, gpu_cfg2;
u32 max_lw, current_lw, tmp;
 
-   pcie_capability_read_word(root, PCI_EXP_LNKCTL,
- &bridge_cfg);
-   pcie_capability_read_word(rdev->pdev, PCI_EXP_LNKCTL,
- &gpu_cfg);
-
-   tmp16 = bridge_cfg | PCI_EXP_LNKCTL_HAWD;
-   pcie_capability_write_word(root, PCI_EXP_LNKCTL, tmp16);
-
-   tmp16 = gpu_cfg | PCI_EXP_LNKCTL_HAWD;
-   pcie_capability_write_word(rdev->pdev, PCI_EXP_LNKCTL,
-  tmp16);
+   pcie_capability_set_word(root, PCI_EXP_LNKCTL, 
PCI_EXP_LNKCTL_HAWD);
+   pcie_capability_set_word(rdev->pdev, PCI_EXP_LNKCTL, 
PCI_EXP_LNKCTL_HAWD);
 
tmp = RREG32_PCIE_PORT(PCIE_LC_STATUS1);
max_lw = (tmp & LC_DETECTED_LINK_WIDTH_MASK) >> 
LC_DETECTED_LINK_WIDTH_SHIFT;
@@ -9591,21 +9582,14 @@ static void cik_pcie_gen3_enable(struct radeon_device 
*rdev)
msleep(100);
 
/* linkctl */
-   pcie_capability_read_word(root, PCI_EXP_LNKCTL,
- &tmp16);
-   tmp16 &= ~PCI_EXP_LNKCTL_HAWD;
-   tmp16 |= (bridge_cfg & PCI_EXP_LNKCTL_HAWD);
-   pcie_capability_write_word(root, PCI_EXP_LNKCTL,
-  tmp16);
-
-   pcie_capability_read_word(rdev->pdev,
- PCI_EXP_LNKCTL,
- &tmp16);
-   tmp16 &= ~PCI_EXP_LNKCTL_HAWD;
-   tmp16 |= (gpu_cfg & PCI_EXP_LNKCTL_HAWD);
-   pcie_capability_write_word(rdev->pdev,
-  PCI_EXP_LNKCTL,
-  tmp16);
+   pcie_capability_clear_and_set_word(root, 
PCI_EXP_LNKCTL,
+  
PCI_EXP_LNKCTL_HAWD,
+  bridge_cfg &
+  
PCI_EXP_LNKCTL_HAWD);
+   pcie_capability_clear_and_set_word(rdev->pdev, 
PCI_EXP_LNKCTL,
+  
PCI_EXP_LNKCTL_HAWD,
+  gpu_cfg &
+  
PCI_EXP_LNKCTL_HAWD);
 
/* linkctl2 */
pcie_capability_read_word(root, PCI_EXP_LNKCTL2,
diff --git a/drivers/gpu/drm/radeon/si.c b/drivers/gpu/drm/radeon/si.c
index 8d5e4b25609d..a91012447b56 100644
--- a/drivers/gpu/drm/radeon/si.c
+++ b/drivers/gpu/drm/radeon/si.c
@@ -7131,17 +7131,8 @@ static void si_pcie_gen3_enable(struct radeon_device 
*rdev)
u16 bridge_cfg2, gpu_cfg2;
u32 max_lw, current_lw, tmp;
 
-   pcie_capability_read_word(root, PCI_EXP_LNKCTL,
- &bridge_cfg);
-   pcie_capability_read_word(rdev->pdev, PCI_EXP_LNKCTL,
- &gpu_cfg);
-
-   tmp16 = bridge_cfg | PCI_EXP_LNKCTL_HAWD

[PATCH v2 4/9] drm/amdgpu: Use RMW accessors for changing LNKCTL

2023-05-17 Thread Ilpo Järvinen
Don't assume that only the driver would be accessing LNKCTL. ASPM
policy changes can trigger write to LNKCTL outside of driver's control.
And in the case of upstream bridge, the driver does not even own the
device it's changing the registers for.

Use RMW capability accessors which do proper locking to avoid losing
concurrent updates to the register value.

Fixes: a2e73f56fa62 ("drm/amdgpu: Add support for CIK parts")
Fixes: 62a37553414a ("drm/amdgpu: add si implementation v10")
Suggested-by: Lukas Wunner 
Signed-off-by: Ilpo Järvinen 
Cc: sta...@vger.kernel.org
---
 drivers/gpu/drm/amd/amdgpu/cik.c | 36 +---
 drivers/gpu/drm/amd/amdgpu/si.c  | 36 +---
 2 files changed, 20 insertions(+), 52 deletions(-)

diff --git a/drivers/gpu/drm/amd/amdgpu/cik.c b/drivers/gpu/drm/amd/amdgpu/cik.c
index de6d10390ab2..9be6da37032a 100644
--- a/drivers/gpu/drm/amd/amdgpu/cik.c
+++ b/drivers/gpu/drm/amd/amdgpu/cik.c
@@ -1574,17 +1574,8 @@ static void cik_pcie_gen3_enable(struct amdgpu_device 
*adev)
u16 bridge_cfg2, gpu_cfg2;
u32 max_lw, current_lw, tmp;
 
-   pcie_capability_read_word(root, PCI_EXP_LNKCTL,
- &bridge_cfg);
-   pcie_capability_read_word(adev->pdev, PCI_EXP_LNKCTL,
- &gpu_cfg);
-
-   tmp16 = bridge_cfg | PCI_EXP_LNKCTL_HAWD;
-   pcie_capability_write_word(root, PCI_EXP_LNKCTL, tmp16);
-
-   tmp16 = gpu_cfg | PCI_EXP_LNKCTL_HAWD;
-   pcie_capability_write_word(adev->pdev, PCI_EXP_LNKCTL,
-  tmp16);
+   pcie_capability_set_word(root, PCI_EXP_LNKCTL, 
PCI_EXP_LNKCTL_HAWD);
+   pcie_capability_set_word(adev->pdev, PCI_EXP_LNKCTL, 
PCI_EXP_LNKCTL_HAWD);
 
tmp = RREG32_PCIE(ixPCIE_LC_STATUS1);
max_lw = (tmp & 
PCIE_LC_STATUS1__LC_DETECTED_LINK_WIDTH_MASK) >>
@@ -1637,21 +1628,14 @@ static void cik_pcie_gen3_enable(struct amdgpu_device 
*adev)
msleep(100);
 
/* linkctl */
-   pcie_capability_read_word(root, PCI_EXP_LNKCTL,
- &tmp16);
-   tmp16 &= ~PCI_EXP_LNKCTL_HAWD;
-   tmp16 |= (bridge_cfg & PCI_EXP_LNKCTL_HAWD);
-   pcie_capability_write_word(root, PCI_EXP_LNKCTL,
-  tmp16);
-
-   pcie_capability_read_word(adev->pdev,
- PCI_EXP_LNKCTL,
- &tmp16);
-   tmp16 &= ~PCI_EXP_LNKCTL_HAWD;
-   tmp16 |= (gpu_cfg & PCI_EXP_LNKCTL_HAWD);
-   pcie_capability_write_word(adev->pdev,
-  PCI_EXP_LNKCTL,
-  tmp16);
+   pcie_capability_clear_and_set_word(root, 
PCI_EXP_LNKCTL,
+  
PCI_EXP_LNKCTL_HAWD,
+  bridge_cfg &
+  
PCI_EXP_LNKCTL_HAWD);
+   pcie_capability_clear_and_set_word(adev->pdev, 
PCI_EXP_LNKCTL,
+  
PCI_EXP_LNKCTL_HAWD,
+  gpu_cfg &
+  
PCI_EXP_LNKCTL_HAWD);
 
/* linkctl2 */
pcie_capability_read_word(root, PCI_EXP_LNKCTL2,
diff --git a/drivers/gpu/drm/amd/amdgpu/si.c b/drivers/gpu/drm/amd/amdgpu/si.c
index 7f99e130acd0..fd34c2100bd9 100644
--- a/drivers/gpu/drm/amd/amdgpu/si.c
+++ b/drivers/gpu/drm/amd/amdgpu/si.c
@@ -2276,17 +2276,8 @@ static void si_pcie_gen3_enable(struct amdgpu_device 
*adev)
u16 bridge_cfg2, gpu_cfg2;
u32 max_lw, current_lw, tmp;
 
-   pcie_capability_read_word(root, PCI_EXP_LNKCTL,
- &bridge_cfg);
-   pcie_capability_read_word(adev->pdev, PCI_EXP_LNKCTL,
- &gpu_cfg);
-
-   tmp16 = bridge_cfg | PCI_EXP_LNKCTL_HAWD;
-   

[PATCH v3 05/10] drm/amdgpu: Use RMW accessors for changing LNKCTL

2023-06-21 Thread Ilpo Järvinen
Don't assume that only the driver would be accessing LNKCTL. ASPM
policy changes can trigger write to LNKCTL outside of driver's control.
And in the case of upstream bridge, the driver does not even own the
device it's changing the registers for.

Use RMW capability accessors which do proper locking to avoid losing
concurrent updates to the register value.

Fixes: a2e73f56fa62 ("drm/amdgpu: Add support for CIK parts")
Fixes: 62a37553414a ("drm/amdgpu: add si implementation v10")
Suggested-by: Lukas Wunner 
Signed-off-by: Ilpo Järvinen 
Cc: sta...@vger.kernel.org
---
 drivers/gpu/drm/amd/amdgpu/cik.c | 36 +---
 drivers/gpu/drm/amd/amdgpu/si.c  | 36 +---
 2 files changed, 20 insertions(+), 52 deletions(-)

diff --git a/drivers/gpu/drm/amd/amdgpu/cik.c b/drivers/gpu/drm/amd/amdgpu/cik.c
index de6d10390ab2..9be6da37032a 100644
--- a/drivers/gpu/drm/amd/amdgpu/cik.c
+++ b/drivers/gpu/drm/amd/amdgpu/cik.c
@@ -1574,17 +1574,8 @@ static void cik_pcie_gen3_enable(struct amdgpu_device 
*adev)
u16 bridge_cfg2, gpu_cfg2;
u32 max_lw, current_lw, tmp;
 
-   pcie_capability_read_word(root, PCI_EXP_LNKCTL,
- &bridge_cfg);
-   pcie_capability_read_word(adev->pdev, PCI_EXP_LNKCTL,
- &gpu_cfg);
-
-   tmp16 = bridge_cfg | PCI_EXP_LNKCTL_HAWD;
-   pcie_capability_write_word(root, PCI_EXP_LNKCTL, tmp16);
-
-   tmp16 = gpu_cfg | PCI_EXP_LNKCTL_HAWD;
-   pcie_capability_write_word(adev->pdev, PCI_EXP_LNKCTL,
-  tmp16);
+   pcie_capability_set_word(root, PCI_EXP_LNKCTL, 
PCI_EXP_LNKCTL_HAWD);
+   pcie_capability_set_word(adev->pdev, PCI_EXP_LNKCTL, 
PCI_EXP_LNKCTL_HAWD);
 
tmp = RREG32_PCIE(ixPCIE_LC_STATUS1);
max_lw = (tmp & 
PCIE_LC_STATUS1__LC_DETECTED_LINK_WIDTH_MASK) >>
@@ -1637,21 +1628,14 @@ static void cik_pcie_gen3_enable(struct amdgpu_device 
*adev)
msleep(100);
 
/* linkctl */
-   pcie_capability_read_word(root, PCI_EXP_LNKCTL,
- &tmp16);
-   tmp16 &= ~PCI_EXP_LNKCTL_HAWD;
-   tmp16 |= (bridge_cfg & PCI_EXP_LNKCTL_HAWD);
-   pcie_capability_write_word(root, PCI_EXP_LNKCTL,
-  tmp16);
-
-   pcie_capability_read_word(adev->pdev,
- PCI_EXP_LNKCTL,
- &tmp16);
-   tmp16 &= ~PCI_EXP_LNKCTL_HAWD;
-   tmp16 |= (gpu_cfg & PCI_EXP_LNKCTL_HAWD);
-   pcie_capability_write_word(adev->pdev,
-  PCI_EXP_LNKCTL,
-  tmp16);
+   pcie_capability_clear_and_set_word(root, 
PCI_EXP_LNKCTL,
+  
PCI_EXP_LNKCTL_HAWD,
+  bridge_cfg &
+  
PCI_EXP_LNKCTL_HAWD);
+   pcie_capability_clear_and_set_word(adev->pdev, 
PCI_EXP_LNKCTL,
+  
PCI_EXP_LNKCTL_HAWD,
+  gpu_cfg &
+  
PCI_EXP_LNKCTL_HAWD);
 
/* linkctl2 */
pcie_capability_read_word(root, PCI_EXP_LNKCTL2,
diff --git a/drivers/gpu/drm/amd/amdgpu/si.c b/drivers/gpu/drm/amd/amdgpu/si.c
index 7f99e130acd0..fd34c2100bd9 100644
--- a/drivers/gpu/drm/amd/amdgpu/si.c
+++ b/drivers/gpu/drm/amd/amdgpu/si.c
@@ -2276,17 +2276,8 @@ static void si_pcie_gen3_enable(struct amdgpu_device 
*adev)
u16 bridge_cfg2, gpu_cfg2;
u32 max_lw, current_lw, tmp;
 
-   pcie_capability_read_word(root, PCI_EXP_LNKCTL,
- &bridge_cfg);
-   pcie_capability_read_word(adev->pdev, PCI_EXP_LNKCTL,
- &gpu_cfg);
-
-   tmp16 = bridge_cfg | PCI_EXP_LNKCTL_HAWD;
-   

[PATCH v3 06/10] drm/radeon: Use RMW accessors for changing LNKCTL

2023-06-21 Thread Ilpo Järvinen
Don't assume that only the driver would be accessing LNKCTL. ASPM
policy changes can trigger write to LNKCTL outside of driver's control.
And in the case of upstream bridge, the driver does not even own the
device it's changing the registers for.

Use RMW capability accessors which do proper locking to avoid losing
concurrent updates to the register value.

Fixes: 8a7cd27679d0 ("drm/radeon/cik: add support for pcie gen1/2/3 switching")
Fixes: b9d305dfb66c ("drm/radeon: implement pcie gen2/3 support for SI")
Suggested-by: Lukas Wunner 
Signed-off-by: Ilpo Järvinen 
Cc: sta...@vger.kernel.org
---
 drivers/gpu/drm/radeon/cik.c | 36 ++-
 drivers/gpu/drm/radeon/si.c  | 37 ++--
 2 files changed, 20 insertions(+), 53 deletions(-)

diff --git a/drivers/gpu/drm/radeon/cik.c b/drivers/gpu/drm/radeon/cik.c
index 5819737c21c6..a6f3c811ceb8 100644
--- a/drivers/gpu/drm/radeon/cik.c
+++ b/drivers/gpu/drm/radeon/cik.c
@@ -9534,17 +9534,8 @@ static void cik_pcie_gen3_enable(struct radeon_device 
*rdev)
u16 bridge_cfg2, gpu_cfg2;
u32 max_lw, current_lw, tmp;
 
-   pcie_capability_read_word(root, PCI_EXP_LNKCTL,
- &bridge_cfg);
-   pcie_capability_read_word(rdev->pdev, PCI_EXP_LNKCTL,
- &gpu_cfg);
-
-   tmp16 = bridge_cfg | PCI_EXP_LNKCTL_HAWD;
-   pcie_capability_write_word(root, PCI_EXP_LNKCTL, tmp16);
-
-   tmp16 = gpu_cfg | PCI_EXP_LNKCTL_HAWD;
-   pcie_capability_write_word(rdev->pdev, PCI_EXP_LNKCTL,
-  tmp16);
+   pcie_capability_set_word(root, PCI_EXP_LNKCTL, 
PCI_EXP_LNKCTL_HAWD);
+   pcie_capability_set_word(rdev->pdev, PCI_EXP_LNKCTL, 
PCI_EXP_LNKCTL_HAWD);
 
tmp = RREG32_PCIE_PORT(PCIE_LC_STATUS1);
max_lw = (tmp & LC_DETECTED_LINK_WIDTH_MASK) >> 
LC_DETECTED_LINK_WIDTH_SHIFT;
@@ -9591,21 +9582,14 @@ static void cik_pcie_gen3_enable(struct radeon_device 
*rdev)
msleep(100);
 
/* linkctl */
-   pcie_capability_read_word(root, PCI_EXP_LNKCTL,
- &tmp16);
-   tmp16 &= ~PCI_EXP_LNKCTL_HAWD;
-   tmp16 |= (bridge_cfg & PCI_EXP_LNKCTL_HAWD);
-   pcie_capability_write_word(root, PCI_EXP_LNKCTL,
-  tmp16);
-
-   pcie_capability_read_word(rdev->pdev,
- PCI_EXP_LNKCTL,
- &tmp16);
-   tmp16 &= ~PCI_EXP_LNKCTL_HAWD;
-   tmp16 |= (gpu_cfg & PCI_EXP_LNKCTL_HAWD);
-   pcie_capability_write_word(rdev->pdev,
-  PCI_EXP_LNKCTL,
-  tmp16);
+   pcie_capability_clear_and_set_word(root, 
PCI_EXP_LNKCTL,
+  
PCI_EXP_LNKCTL_HAWD,
+  bridge_cfg &
+  
PCI_EXP_LNKCTL_HAWD);
+   pcie_capability_clear_and_set_word(rdev->pdev, 
PCI_EXP_LNKCTL,
+  
PCI_EXP_LNKCTL_HAWD,
+  gpu_cfg &
+  
PCI_EXP_LNKCTL_HAWD);
 
/* linkctl2 */
pcie_capability_read_word(root, PCI_EXP_LNKCTL2,
diff --git a/drivers/gpu/drm/radeon/si.c b/drivers/gpu/drm/radeon/si.c
index 8d5e4b25609d..a91012447b56 100644
--- a/drivers/gpu/drm/radeon/si.c
+++ b/drivers/gpu/drm/radeon/si.c
@@ -7131,17 +7131,8 @@ static void si_pcie_gen3_enable(struct radeon_device 
*rdev)
u16 bridge_cfg2, gpu_cfg2;
u32 max_lw, current_lw, tmp;
 
-   pcie_capability_read_word(root, PCI_EXP_LNKCTL,
- &bridge_cfg);
-   pcie_capability_read_word(rdev->pdev, PCI_EXP_LNKCTL,
- &gpu_cfg);
-
-   tmp16 = bridge_cfg | PCI_EXP_LNKCTL_HAWD

[PATCH v4 06/11] drm/radeon: Use RMW accessors for changing LNKCTL

2023-07-13 Thread Ilpo Järvinen
Don't assume that only the driver would be accessing LNKCTL. ASPM
policy changes can trigger write to LNKCTL outside of driver's control.
And in the case of upstream bridge, the driver does not even own the
device it's changing the registers for.

Use RMW capability accessors which do proper locking to avoid losing
concurrent updates to the register value.

Fixes: 8a7cd27679d0 ("drm/radeon/cik: add support for pcie gen1/2/3 switching")
Fixes: b9d305dfb66c ("drm/radeon: implement pcie gen2/3 support for SI")
Suggested-by: Lukas Wunner 
Signed-off-by: Ilpo Järvinen 
Cc: sta...@vger.kernel.org
---
 drivers/gpu/drm/radeon/cik.c | 36 ++-
 drivers/gpu/drm/radeon/si.c  | 37 ++--
 2 files changed, 20 insertions(+), 53 deletions(-)

diff --git a/drivers/gpu/drm/radeon/cik.c b/drivers/gpu/drm/radeon/cik.c
index 5819737c21c6..a6f3c811ceb8 100644
--- a/drivers/gpu/drm/radeon/cik.c
+++ b/drivers/gpu/drm/radeon/cik.c
@@ -9534,17 +9534,8 @@ static void cik_pcie_gen3_enable(struct radeon_device 
*rdev)
u16 bridge_cfg2, gpu_cfg2;
u32 max_lw, current_lw, tmp;
 
-   pcie_capability_read_word(root, PCI_EXP_LNKCTL,
- &bridge_cfg);
-   pcie_capability_read_word(rdev->pdev, PCI_EXP_LNKCTL,
- &gpu_cfg);
-
-   tmp16 = bridge_cfg | PCI_EXP_LNKCTL_HAWD;
-   pcie_capability_write_word(root, PCI_EXP_LNKCTL, tmp16);
-
-   tmp16 = gpu_cfg | PCI_EXP_LNKCTL_HAWD;
-   pcie_capability_write_word(rdev->pdev, PCI_EXP_LNKCTL,
-  tmp16);
+   pcie_capability_set_word(root, PCI_EXP_LNKCTL, 
PCI_EXP_LNKCTL_HAWD);
+   pcie_capability_set_word(rdev->pdev, PCI_EXP_LNKCTL, 
PCI_EXP_LNKCTL_HAWD);
 
tmp = RREG32_PCIE_PORT(PCIE_LC_STATUS1);
max_lw = (tmp & LC_DETECTED_LINK_WIDTH_MASK) >> 
LC_DETECTED_LINK_WIDTH_SHIFT;
@@ -9591,21 +9582,14 @@ static void cik_pcie_gen3_enable(struct radeon_device 
*rdev)
msleep(100);
 
/* linkctl */
-   pcie_capability_read_word(root, PCI_EXP_LNKCTL,
- &tmp16);
-   tmp16 &= ~PCI_EXP_LNKCTL_HAWD;
-   tmp16 |= (bridge_cfg & PCI_EXP_LNKCTL_HAWD);
-   pcie_capability_write_word(root, PCI_EXP_LNKCTL,
-  tmp16);
-
-   pcie_capability_read_word(rdev->pdev,
- PCI_EXP_LNKCTL,
- &tmp16);
-   tmp16 &= ~PCI_EXP_LNKCTL_HAWD;
-   tmp16 |= (gpu_cfg & PCI_EXP_LNKCTL_HAWD);
-   pcie_capability_write_word(rdev->pdev,
-  PCI_EXP_LNKCTL,
-  tmp16);
+   pcie_capability_clear_and_set_word(root, 
PCI_EXP_LNKCTL,
+  
PCI_EXP_LNKCTL_HAWD,
+  bridge_cfg &
+  
PCI_EXP_LNKCTL_HAWD);
+   pcie_capability_clear_and_set_word(rdev->pdev, 
PCI_EXP_LNKCTL,
+  
PCI_EXP_LNKCTL_HAWD,
+  gpu_cfg &
+  
PCI_EXP_LNKCTL_HAWD);
 
/* linkctl2 */
pcie_capability_read_word(root, PCI_EXP_LNKCTL2,
diff --git a/drivers/gpu/drm/radeon/si.c b/drivers/gpu/drm/radeon/si.c
index 8d5e4b25609d..a91012447b56 100644
--- a/drivers/gpu/drm/radeon/si.c
+++ b/drivers/gpu/drm/radeon/si.c
@@ -7131,17 +7131,8 @@ static void si_pcie_gen3_enable(struct radeon_device 
*rdev)
u16 bridge_cfg2, gpu_cfg2;
u32 max_lw, current_lw, tmp;
 
-   pcie_capability_read_word(root, PCI_EXP_LNKCTL,
- &bridge_cfg);
-   pcie_capability_read_word(rdev->pdev, PCI_EXP_LNKCTL,
- &gpu_cfg);
-
-   tmp16 = bridge_cfg | PCI_EXP_LNKCTL_HAWD

[PATCH v4 05/11] drm/amdgpu: Use RMW accessors for changing LNKCTL

2023-07-13 Thread Ilpo Järvinen
Don't assume that only the driver would be accessing LNKCTL. ASPM
policy changes can trigger write to LNKCTL outside of driver's control.
And in the case of upstream bridge, the driver does not even own the
device it's changing the registers for.

Use RMW capability accessors which do proper locking to avoid losing
concurrent updates to the register value.

Fixes: a2e73f56fa62 ("drm/amdgpu: Add support for CIK parts")
Fixes: 62a37553414a ("drm/amdgpu: add si implementation v10")
Suggested-by: Lukas Wunner 
Signed-off-by: Ilpo Järvinen 
Cc: sta...@vger.kernel.org
---
 drivers/gpu/drm/amd/amdgpu/cik.c | 36 +---
 drivers/gpu/drm/amd/amdgpu/si.c  | 36 +---
 2 files changed, 20 insertions(+), 52 deletions(-)

diff --git a/drivers/gpu/drm/amd/amdgpu/cik.c b/drivers/gpu/drm/amd/amdgpu/cik.c
index 5641cf05d856..e63abdf52b6c 100644
--- a/drivers/gpu/drm/amd/amdgpu/cik.c
+++ b/drivers/gpu/drm/amd/amdgpu/cik.c
@@ -1574,17 +1574,8 @@ static void cik_pcie_gen3_enable(struct amdgpu_device 
*adev)
u16 bridge_cfg2, gpu_cfg2;
u32 max_lw, current_lw, tmp;
 
-   pcie_capability_read_word(root, PCI_EXP_LNKCTL,
- &bridge_cfg);
-   pcie_capability_read_word(adev->pdev, PCI_EXP_LNKCTL,
- &gpu_cfg);
-
-   tmp16 = bridge_cfg | PCI_EXP_LNKCTL_HAWD;
-   pcie_capability_write_word(root, PCI_EXP_LNKCTL, tmp16);
-
-   tmp16 = gpu_cfg | PCI_EXP_LNKCTL_HAWD;
-   pcie_capability_write_word(adev->pdev, PCI_EXP_LNKCTL,
-  tmp16);
+   pcie_capability_set_word(root, PCI_EXP_LNKCTL, 
PCI_EXP_LNKCTL_HAWD);
+   pcie_capability_set_word(adev->pdev, PCI_EXP_LNKCTL, 
PCI_EXP_LNKCTL_HAWD);
 
tmp = RREG32_PCIE(ixPCIE_LC_STATUS1);
max_lw = (tmp & 
PCIE_LC_STATUS1__LC_DETECTED_LINK_WIDTH_MASK) >>
@@ -1637,21 +1628,14 @@ static void cik_pcie_gen3_enable(struct amdgpu_device 
*adev)
msleep(100);
 
/* linkctl */
-   pcie_capability_read_word(root, PCI_EXP_LNKCTL,
- &tmp16);
-   tmp16 &= ~PCI_EXP_LNKCTL_HAWD;
-   tmp16 |= (bridge_cfg & PCI_EXP_LNKCTL_HAWD);
-   pcie_capability_write_word(root, PCI_EXP_LNKCTL,
-  tmp16);
-
-   pcie_capability_read_word(adev->pdev,
- PCI_EXP_LNKCTL,
- &tmp16);
-   tmp16 &= ~PCI_EXP_LNKCTL_HAWD;
-   tmp16 |= (gpu_cfg & PCI_EXP_LNKCTL_HAWD);
-   pcie_capability_write_word(adev->pdev,
-  PCI_EXP_LNKCTL,
-  tmp16);
+   pcie_capability_clear_and_set_word(root, 
PCI_EXP_LNKCTL,
+  
PCI_EXP_LNKCTL_HAWD,
+  bridge_cfg &
+  
PCI_EXP_LNKCTL_HAWD);
+   pcie_capability_clear_and_set_word(adev->pdev, 
PCI_EXP_LNKCTL,
+  
PCI_EXP_LNKCTL_HAWD,
+  gpu_cfg &
+  
PCI_EXP_LNKCTL_HAWD);
 
/* linkctl2 */
pcie_capability_read_word(root, PCI_EXP_LNKCTL2,
diff --git a/drivers/gpu/drm/amd/amdgpu/si.c b/drivers/gpu/drm/amd/amdgpu/si.c
index f64b87b11b1b..4b81f29e5fd5 100644
--- a/drivers/gpu/drm/amd/amdgpu/si.c
+++ b/drivers/gpu/drm/amd/amdgpu/si.c
@@ -2276,17 +2276,8 @@ static void si_pcie_gen3_enable(struct amdgpu_device 
*adev)
u16 bridge_cfg2, gpu_cfg2;
u32 max_lw, current_lw, tmp;
 
-   pcie_capability_read_word(root, PCI_EXP_LNKCTL,
- &bridge_cfg);
-   pcie_capability_read_word(adev->pdev, PCI_EXP_LNKCTL,
- &gpu_cfg);
-
-   tmp16 = bridge_cfg | PCI_EXP_LNKCTL_HAWD;
-   

[PATCH v5 06/11] drm/radeon: Use RMW accessors for changing LNKCTL

2023-07-17 Thread Ilpo Järvinen
Don't assume that only the driver would be accessing LNKCTL. ASPM
policy changes can trigger write to LNKCTL outside of driver's control.
And in the case of upstream bridge, the driver does not even own the
device it's changing the registers for.

Use RMW capability accessors which do proper locking to avoid losing
concurrent updates to the register value.

Fixes: 8a7cd27679d0 ("drm/radeon/cik: add support for pcie gen1/2/3 switching")
Fixes: b9d305dfb66c ("drm/radeon: implement pcie gen2/3 support for SI")
Suggested-by: Lukas Wunner 
Signed-off-by: Ilpo Järvinen 
Cc: sta...@vger.kernel.org
---
 drivers/gpu/drm/radeon/cik.c | 36 ++-
 drivers/gpu/drm/radeon/si.c  | 37 ++--
 2 files changed, 20 insertions(+), 53 deletions(-)

diff --git a/drivers/gpu/drm/radeon/cik.c b/drivers/gpu/drm/radeon/cik.c
index 5819737c21c6..a6f3c811ceb8 100644
--- a/drivers/gpu/drm/radeon/cik.c
+++ b/drivers/gpu/drm/radeon/cik.c
@@ -9534,17 +9534,8 @@ static void cik_pcie_gen3_enable(struct radeon_device 
*rdev)
u16 bridge_cfg2, gpu_cfg2;
u32 max_lw, current_lw, tmp;
 
-   pcie_capability_read_word(root, PCI_EXP_LNKCTL,
- &bridge_cfg);
-   pcie_capability_read_word(rdev->pdev, PCI_EXP_LNKCTL,
- &gpu_cfg);
-
-   tmp16 = bridge_cfg | PCI_EXP_LNKCTL_HAWD;
-   pcie_capability_write_word(root, PCI_EXP_LNKCTL, tmp16);
-
-   tmp16 = gpu_cfg | PCI_EXP_LNKCTL_HAWD;
-   pcie_capability_write_word(rdev->pdev, PCI_EXP_LNKCTL,
-  tmp16);
+   pcie_capability_set_word(root, PCI_EXP_LNKCTL, 
PCI_EXP_LNKCTL_HAWD);
+   pcie_capability_set_word(rdev->pdev, PCI_EXP_LNKCTL, 
PCI_EXP_LNKCTL_HAWD);
 
tmp = RREG32_PCIE_PORT(PCIE_LC_STATUS1);
max_lw = (tmp & LC_DETECTED_LINK_WIDTH_MASK) >> 
LC_DETECTED_LINK_WIDTH_SHIFT;
@@ -9591,21 +9582,14 @@ static void cik_pcie_gen3_enable(struct radeon_device 
*rdev)
msleep(100);
 
/* linkctl */
-   pcie_capability_read_word(root, PCI_EXP_LNKCTL,
- &tmp16);
-   tmp16 &= ~PCI_EXP_LNKCTL_HAWD;
-   tmp16 |= (bridge_cfg & PCI_EXP_LNKCTL_HAWD);
-   pcie_capability_write_word(root, PCI_EXP_LNKCTL,
-  tmp16);
-
-   pcie_capability_read_word(rdev->pdev,
- PCI_EXP_LNKCTL,
- &tmp16);
-   tmp16 &= ~PCI_EXP_LNKCTL_HAWD;
-   tmp16 |= (gpu_cfg & PCI_EXP_LNKCTL_HAWD);
-   pcie_capability_write_word(rdev->pdev,
-  PCI_EXP_LNKCTL,
-  tmp16);
+   pcie_capability_clear_and_set_word(root, 
PCI_EXP_LNKCTL,
+  
PCI_EXP_LNKCTL_HAWD,
+  bridge_cfg &
+  
PCI_EXP_LNKCTL_HAWD);
+   pcie_capability_clear_and_set_word(rdev->pdev, 
PCI_EXP_LNKCTL,
+  
PCI_EXP_LNKCTL_HAWD,
+  gpu_cfg &
+  
PCI_EXP_LNKCTL_HAWD);
 
/* linkctl2 */
pcie_capability_read_word(root, PCI_EXP_LNKCTL2,
diff --git a/drivers/gpu/drm/radeon/si.c b/drivers/gpu/drm/radeon/si.c
index 8d5e4b25609d..a91012447b56 100644
--- a/drivers/gpu/drm/radeon/si.c
+++ b/drivers/gpu/drm/radeon/si.c
@@ -7131,17 +7131,8 @@ static void si_pcie_gen3_enable(struct radeon_device 
*rdev)
u16 bridge_cfg2, gpu_cfg2;
u32 max_lw, current_lw, tmp;
 
-   pcie_capability_read_word(root, PCI_EXP_LNKCTL,
- &bridge_cfg);
-   pcie_capability_read_word(rdev->pdev, PCI_EXP_LNKCTL,
- &gpu_cfg);
-
-   tmp16 = bridge_cfg | PCI_EXP_LNKCTL_HAWD

[PATCH v5 05/11] drm/amdgpu: Use RMW accessors for changing LNKCTL

2023-07-17 Thread Ilpo Järvinen
Don't assume that only the driver would be accessing LNKCTL. ASPM
policy changes can trigger write to LNKCTL outside of driver's control.
And in the case of upstream bridge, the driver does not even own the
device it's changing the registers for.

Use RMW capability accessors which do proper locking to avoid losing
concurrent updates to the register value.

Fixes: a2e73f56fa62 ("drm/amdgpu: Add support for CIK parts")
Fixes: 62a37553414a ("drm/amdgpu: add si implementation v10")
Suggested-by: Lukas Wunner 
Signed-off-by: Ilpo Järvinen 
Cc: sta...@vger.kernel.org
---
 drivers/gpu/drm/amd/amdgpu/cik.c | 36 +---
 drivers/gpu/drm/amd/amdgpu/si.c  | 36 +---
 2 files changed, 20 insertions(+), 52 deletions(-)

diff --git a/drivers/gpu/drm/amd/amdgpu/cik.c b/drivers/gpu/drm/amd/amdgpu/cik.c
index 5641cf05d856..e63abdf52b6c 100644
--- a/drivers/gpu/drm/amd/amdgpu/cik.c
+++ b/drivers/gpu/drm/amd/amdgpu/cik.c
@@ -1574,17 +1574,8 @@ static void cik_pcie_gen3_enable(struct amdgpu_device 
*adev)
u16 bridge_cfg2, gpu_cfg2;
u32 max_lw, current_lw, tmp;
 
-   pcie_capability_read_word(root, PCI_EXP_LNKCTL,
- &bridge_cfg);
-   pcie_capability_read_word(adev->pdev, PCI_EXP_LNKCTL,
- &gpu_cfg);
-
-   tmp16 = bridge_cfg | PCI_EXP_LNKCTL_HAWD;
-   pcie_capability_write_word(root, PCI_EXP_LNKCTL, tmp16);
-
-   tmp16 = gpu_cfg | PCI_EXP_LNKCTL_HAWD;
-   pcie_capability_write_word(adev->pdev, PCI_EXP_LNKCTL,
-  tmp16);
+   pcie_capability_set_word(root, PCI_EXP_LNKCTL, 
PCI_EXP_LNKCTL_HAWD);
+   pcie_capability_set_word(adev->pdev, PCI_EXP_LNKCTL, 
PCI_EXP_LNKCTL_HAWD);
 
tmp = RREG32_PCIE(ixPCIE_LC_STATUS1);
max_lw = (tmp & 
PCIE_LC_STATUS1__LC_DETECTED_LINK_WIDTH_MASK) >>
@@ -1637,21 +1628,14 @@ static void cik_pcie_gen3_enable(struct amdgpu_device 
*adev)
msleep(100);
 
/* linkctl */
-   pcie_capability_read_word(root, PCI_EXP_LNKCTL,
- &tmp16);
-   tmp16 &= ~PCI_EXP_LNKCTL_HAWD;
-   tmp16 |= (bridge_cfg & PCI_EXP_LNKCTL_HAWD);
-   pcie_capability_write_word(root, PCI_EXP_LNKCTL,
-  tmp16);
-
-   pcie_capability_read_word(adev->pdev,
- PCI_EXP_LNKCTL,
- &tmp16);
-   tmp16 &= ~PCI_EXP_LNKCTL_HAWD;
-   tmp16 |= (gpu_cfg & PCI_EXP_LNKCTL_HAWD);
-   pcie_capability_write_word(adev->pdev,
-  PCI_EXP_LNKCTL,
-  tmp16);
+   pcie_capability_clear_and_set_word(root, 
PCI_EXP_LNKCTL,
+  
PCI_EXP_LNKCTL_HAWD,
+  bridge_cfg &
+  
PCI_EXP_LNKCTL_HAWD);
+   pcie_capability_clear_and_set_word(adev->pdev, 
PCI_EXP_LNKCTL,
+  
PCI_EXP_LNKCTL_HAWD,
+  gpu_cfg &
+  
PCI_EXP_LNKCTL_HAWD);
 
/* linkctl2 */
pcie_capability_read_word(root, PCI_EXP_LNKCTL2,
diff --git a/drivers/gpu/drm/amd/amdgpu/si.c b/drivers/gpu/drm/amd/amdgpu/si.c
index f64b87b11b1b..4b81f29e5fd5 100644
--- a/drivers/gpu/drm/amd/amdgpu/si.c
+++ b/drivers/gpu/drm/amd/amdgpu/si.c
@@ -2276,17 +2276,8 @@ static void si_pcie_gen3_enable(struct amdgpu_device 
*adev)
u16 bridge_cfg2, gpu_cfg2;
u32 max_lw, current_lw, tmp;
 
-   pcie_capability_read_word(root, PCI_EXP_LNKCTL,
- &bridge_cfg);
-   pcie_capability_read_word(adev->pdev, PCI_EXP_LNKCTL,
- &gpu_cfg);
-
-   tmp16 = bridge_cfg | PCI_EXP_LNKCTL_HAWD;
-   

Re: [PATCH v5 05/11] drm/amdgpu: Use RMW accessors for changing LNKCTL

2023-07-21 Thread Ilpo Järvinen
On Thu, 20 Jul 2023, Bjorn Helgaas wrote:

> On Mon, Jul 17, 2023 at 03:04:57PM +0300, Ilpo Järvinen wrote:
> > Don't assume that only the driver would be accessing LNKCTL. ASPM
> > policy changes can trigger write to LNKCTL outside of driver's control.
> > And in the case of upstream bridge, the driver does not even own the
> > device it's changing the registers for.
> > 
> > Use RMW capability accessors which do proper locking to avoid losing
> > concurrent updates to the register value.
> > 
> > Fixes: a2e73f56fa62 ("drm/amdgpu: Add support for CIK parts")
> > Fixes: 62a37553414a ("drm/amdgpu: add si implementation v10")
> > Suggested-by: Lukas Wunner 
> > Signed-off-by: Ilpo Järvinen 
> > Cc: sta...@vger.kernel.org
> 
> Do we have any reports of problems that are fixed by this patch (or by
> others in the series)?  If not, I'm not sure it really fits the usual
> stable kernel criteria:
> 
> https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/Documentation/process/stable-kernel-rules.rst?id=v6.4

I was on the edge with this. The answer to your direct question is no, 
there are no such reports so it would be okay to leave stable out I think. 
This applies to all patches in this series.

Basically, this series came to be after Lukas noted the potential 
concurrency issues with how LNKCTL is unprotected when reviewing 
(internally) my bandwidth controller series. Then I went to look around 
all LNKCTL usage and realized existing things might alreary have similar 
issues.

Do you want me to send another version w/o cc stable or you'll take care 
of that?

> > ---
> >  drivers/gpu/drm/amd/amdgpu/cik.c | 36 +---
> >  drivers/gpu/drm/amd/amdgpu/si.c  | 36 +---
> >  2 files changed, 20 insertions(+), 52 deletions(-)
> > 
> > diff --git a/drivers/gpu/drm/amd/amdgpu/cik.c 
> > b/drivers/gpu/drm/amd/amdgpu/cik.c
> > index 5641cf05d856..e63abdf52b6c 100644
> > --- a/drivers/gpu/drm/amd/amdgpu/cik.c
> > +++ b/drivers/gpu/drm/amd/amdgpu/cik.c
> > @@ -1574,17 +1574,8 @@ static void cik_pcie_gen3_enable(struct 
> > amdgpu_device *adev)
> > u16 bridge_cfg2, gpu_cfg2;
> > u32 max_lw, current_lw, tmp;
> >  
> > -   pcie_capability_read_word(root, PCI_EXP_LNKCTL,
> > - &bridge_cfg);
> > -   pcie_capability_read_word(adev->pdev, PCI_EXP_LNKCTL,
> > - &gpu_cfg);
> > -
> > -   tmp16 = bridge_cfg | PCI_EXP_LNKCTL_HAWD;
> > -   pcie_capability_write_word(root, PCI_EXP_LNKCTL, tmp16);
> > -
> > -   tmp16 = gpu_cfg | PCI_EXP_LNKCTL_HAWD;
> > -   pcie_capability_write_word(adev->pdev, PCI_EXP_LNKCTL,
> > -  tmp16);
> > +   pcie_capability_set_word(root, PCI_EXP_LNKCTL, 
> > PCI_EXP_LNKCTL_HAWD);
> > +   pcie_capability_set_word(adev->pdev, PCI_EXP_LNKCTL, 
> > PCI_EXP_LNKCTL_HAWD);
> >  
> > tmp = RREG32_PCIE(ixPCIE_LC_STATUS1);
> > max_lw = (tmp & 
> > PCIE_LC_STATUS1__LC_DETECTED_LINK_WIDTH_MASK) >>
> > @@ -1637,21 +1628,14 @@ static void cik_pcie_gen3_enable(struct 
> > amdgpu_device *adev)
> > msleep(100);
> >  
> > /* linkctl */
> > -   pcie_capability_read_word(root, PCI_EXP_LNKCTL,
> > - &tmp16);
> > -   tmp16 &= ~PCI_EXP_LNKCTL_HAWD;
> > -   tmp16 |= (bridge_cfg & PCI_EXP_LNKCTL_HAWD);
> > -   pcie_capability_write_word(root, PCI_EXP_LNKCTL,
> > -  tmp16);
> > -
> > -   pcie_capability_read_word(adev->pdev,
> > - PCI_EXP_LNKCTL,
> > - &tmp16);
> > -   tmp16 &= ~PCI_EXP_LNKCTL_HAWD;
> > -   tmp16 |= (gpu_cfg & PCI_EXP_LNKCTL_HAWD);
> > -   pcie_capability_write_word(adev->pdev,
> > -  PCI_EXP_LNKCTL,
> > -  tmp16);
> > +