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

2023-10-10 Thread Shyam Sundar S K



On 10/10/2023 9:56 PM, Mario Limonciello wrote:
> On 10/10/2023 07:59, 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  |   2 +-
>>   drivers/platform/x86/amd/pmf/acpi.c   |  37 +++
>>   drivers/platform/x86/amd/pmf/core.c   |  13 +++
>>   drivers/platform/x86/amd/pmf/pmf.h    | 136 
>>   drivers/platform/x86/amd/pmf/tee-if.c | 146
>> +-
>>   5 files changed, 331 insertions(+), 3 deletions(-)
>>
>> diff --git a/drivers/platform/x86/amd/pmf/Kconfig
>> b/drivers/platform/x86/amd/pmf/Kconfig
>> index 32a029e8db80..f246252bddd8 100644
>> --- a/drivers/platform/x86/amd/pmf/Kconfig
>> +++ b/drivers/platform/x86/amd/pmf/Kconfig
>> @@ -9,7 +9,7 @@ config AMD_PMF
>>   depends on POWER_SUPPLY
>>   depends on AMD_NB
>>   select ACPI_PLATFORM_PROFILE
>> -    depends on TEE
>> +    depends on TEE && AMDTEE
>>   help
>>     This driver provides support for the AMD Platform Management
>> Framework.
>>     The goal is to enhance end user experience by making AMD PCs
>> smarter,
>> diff --git a/drivers/platform/x86/amd/pmf/acpi.c
>> b/drivers/platform/x86/amd/pmf/acpi.c
>> index 3fc5e4547d9f..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;
>> + 

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

2023-10-10 Thread Shyam Sundar S K



On 10/10/2023 9:33 PM, Mario Limonciello wrote:
> On 10/10/2023 07:59, 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 
> 
> One minor nit below.
> 
> Reviewed-by: Mario Limonciello 
> 
>> ---
>>   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 | 36
>> ++-
>>   4 files changed, 70 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 ..6985bb5b9452
>> --- /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}=="0",
>> RUN+="/usr/bin/systemctl suspend"
>> +    DRIVERS=="amd-pmf", ACTION=="change", ENV{EVENT_ID}=="1",
>> RUN+="/usr/bin/systemctl hibernate"
>> +    DRIVERS=="amd-pmf", ACTION=="change", ENV{EVENT_ID}=="2",
>> RUN+="/bin/loginctl lock-sessions"
>> +
>> +EVENT_ID values:
>> +0= Put the system to S0i3/S2Idle
>> +1= Put the system to hibernate
>> +2= Lock the screen
>> +
>> diff --git a/drivers/platform/x86/amd/pmf/pmf.h
>> b/drivers/platform/x86/amd/pmf/pmf.h
>> index 20f3e16b0a32..67f3d5a7 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 */
>> @@ -440,6 +441,13 @@ struct apmf_dyn_slider_output {
>>   } __packed;
>>     /* Smart PC - TA internals */
> 
> I know that Ilpo had a comment about this in an earlier version that
> there is a "__" instead of "_".  I know this is intended behavior for
> consistency with internal usage, but maybe it's worth having a comment
> somewhere mentioning it's intended behavior?  I'm not sure where.
> 

I missed to change here.  I have changed at other places too.

>> +enum system_state {
>> +    SYSTEM_STATE__S0i3,
>> +    SYSTEM_STATE__S4,
>> +    SYSTEM_STATE__SCREEN_LOCK,
>> +    SYSTEM_STATE__MAX
>> +};
>> +
>>   enum ta_slider {
>>   TA_BEST_BATTERY,    /* Best Battery */
>>   TA_BETTER_BATTERY,    /* Better Battery */
>> @@ -471,6 +479,7 @@ enum ta_pmf_error_type {
>>   };
>>     struct pmf_action_table {
>> +    enum system_state system_state;
>>   u32 spl;    /* in mW */
>>   u32 sppt;    /* in mW */
>>   u32 sppt_apuonly;    /* in mW */
>> diff --git a/drivers/platform/x86/amd/pmf/tee-if.c
>> b/drivers/platform/x86/amd/pmf/tee-if.c
>> index 92879ae4f8f0..c08ef13a1494 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 

Re: [PATCH 2/3] drm/amdgpu/umsch: power on/off UMSCH by DLDO

2023-10-10 Thread Lang Yu
On 10/10/ , Alex Deucher wrote:
> On Tue, Oct 10, 2023 at 9:42 AM Lang Yu  wrote:
> >
> > On 10/10/ , Deucher, Alexander wrote:
> > > [Public]
> > >
> > > > -Original Message-
> > > > From: Yu, Lang 
> > > > Sent: Saturday, October 7, 2023 4:54 AM
> > > > To: amd-gfx@lists.freedesktop.org
> > > > Cc: Deucher, Alexander ; Zhang, Yifan
> > > > ; Gopalakrishnan, Veerabadhran (Veera)
> > > > ; Yu, Lang 
> > > > Subject: [PATCH 2/3] drm/amdgpu/umsch: power on/off UMSCH by DLDO
> > > >
> > > > VCN 4.0.5 uses DLDO.
> > > >
> > > > Signed-off-by: Lang Yu 
> > > > ---
> > > >  drivers/gpu/drm/amd/amdgpu/umsch_mm_v4_0.c | 26
> > > > ++
> > > >  1 file changed, 26 insertions(+)
> > > >
> > > > diff --git a/drivers/gpu/drm/amd/amdgpu/umsch_mm_v4_0.c
> > > > b/drivers/gpu/drm/amd/amdgpu/umsch_mm_v4_0.c
> > > > index a60178156c77..7e79954c833b 100644
> > > > --- a/drivers/gpu/drm/amd/amdgpu/umsch_mm_v4_0.c
> > > > +++ b/drivers/gpu/drm/amd/amdgpu/umsch_mm_v4_0.c
> > > > @@ -34,6 +34,16 @@
> > > >  #include "umsch_mm_4_0_api_def.h"
> > > >  #include "umsch_mm_v4_0.h"
> > > >
> > > > +#define regUVD_IPX_DLDO_CONFIG 0x0064
> > > > +#define regUVD_IPX_DLDO_CONFIG_BASE_IDX1
> > > > +#define regUVD_IPX_DLDO_STATUS 0x0065
> > > > +#define regUVD_IPX_DLDO_STATUS_BASE_IDX1
> > > > +
> > > > +#define UVD_IPX_DLDO_CONFIG__ONO0_PWR_CONFIG__SHIFT
> > > > 0x0002
> > > > +#define UVD_IPX_DLDO_CONFIG__ONO0_PWR_CONFIG_MASK
> > > > 0x000cUL
> > > > +#define UVD_IPX_DLDO_STATUS__ONO0_PWR_STATUS__SHIFT
> > > > 0x0001
> > > > +#define UVD_IPX_DLDO_STATUS__ONO0_PWR_STATUS_MASK
> > > > 0x0002UL
> > > > +
> > > >  static int umsch_mm_v4_0_load_microcode(struct amdgpu_umsch_mm
> > > > *umsch)  {
> > > >   struct amdgpu_device *adev = umsch->ring.adev; @@ -50,6 +60,14
> > > > @@ static int umsch_mm_v4_0_load_microcode(struct amdgpu_umsch_mm
> > > > *umsch)
> > > >
> > > >   umsch->cmd_buf_curr_ptr = umsch->cmd_buf_ptr;
> > > >
> > > > + if (adev->ip_versions[VCN_HWIP][0] == IP_VERSION(4, 0, 5)) {
> > > > + WREG32_SOC15(VCN, 0, regUVD_IPX_DLDO_CONFIG,
> > > > + 1 <<
> > > > UVD_IPX_DLDO_CONFIG__ONO0_PWR_CONFIG__SHIFT);
> > > > + SOC15_WAIT_ON_RREG(VCN, 0, regUVD_IPX_DLDO_STATUS,
> > > > + 0 <<
> > > > UVD_IPX_DLDO_STATUS__ONO0_PWR_STATUS__SHIFT,
> > > > +
> > > >   UVD_IPX_DLDO_STATUS__ONO0_PWR_STATUS_MASK);
> > > > + }
> > > > +
> > >
> > > Is this the right place for this?  umsch_mm_hw_init() only calls this for 
> > > FW_LOAD_DIRECT.  Maybe that check needs to be dropped?
> >
> > That check is dropped in [PATCH 1/3] drm/amdgpu/umsch: fix psp frontdoor 
> > loading.
> 
> Ah, I checked that, but I missed it.  Thanks.
> 
> >
> > PMFW removed DLDO programing in PPSMC_MSG_PowerUpUmsch function.
> > So driver needs to program it explicitly.
> 
> Ok.  So is the SMC message still required in addition?

Yes. Some masks need to be updated. 

Regards,
Lang

> Alex
> 
> >
> > Regards,
> > Lang
> >
> > > Alex
> > >
> > > >   data = RREG32_SOC15(VCN, 0, regUMSCH_MES_RESET_CTRL);
> > > >   data = REG_SET_FIELD(data, UMSCH_MES_RESET_CTRL,
> > > > MES_CORE_SOFT_RESET, 0);
> > > >   WREG32_SOC15_UMSCH(regUMSCH_MES_RESET_CTRL, data); @@ -
> > > > 229,6 +247,14 @@ static int umsch_mm_v4_0_ring_stop(struct
> > > > amdgpu_umsch_mm *umsch)
> > > >   data = REG_SET_FIELD(data, VCN_UMSCH_RB_DB_CTRL, EN, 0);
> > > >   WREG32_SOC15(VCN, 0, regVCN_UMSCH_RB_DB_CTRL, data);
> > > >
> > > > + if (adev->ip_versions[VCN_HWIP][0] == IP_VERSION(4, 0, 5)) {
> > > > + WREG32_SOC15(VCN, 0, regUVD_IPX_DLDO_CONFIG,
> > > > + 2 <<
> > > > UVD_IPX_DLDO_CONFIG__ONO0_PWR_CONFIG__SHIFT);
> > > > + SOC15_WAIT_ON_RREG(VCN, 0, regUVD_IPX_DLDO_STATUS,
> > > > + 1 <<
> > > > UVD_IPX_DLDO_STATUS__ONO0_PWR_STATUS__SHIFT,
> > > > +
> > > >   UVD_IPX_DLDO_STATUS__ONO0_PWR_STATUS_MASK);
> > > > + }
> > > > +
> > > >   return 0;
> > > >  }
> > > >
> > > > --
> > > > 2.25.1
> > >


RE: [PATCH] drm/amd/pm: drop most smu_cmn_get_smc_version in smu

2023-10-10 Thread Feng, Kenneth
[AMD Official Use Only - General]

Reviewed-by: Kenneth Feng 


-Original Message-
From: Zhang, Yifan 
Sent: Tuesday, October 10, 2023 10:52 PM
To: amd-gfx@lists.freedesktop.org
Cc: Deucher, Alexander ; Koenig, Christian 
; Ma, Li ; Feng, Kenneth 
; Zhang, Yifan 
Subject: [PATCH] drm/amd/pm: drop most smu_cmn_get_smc_version in smu

smu_check_fw_version is called in smu hw init, thus smu if version and version 
are garenteed to be stored in smu context. No need to call 
smu_cmn_get_smc_version again after system boot up.

Signed-off-by: Yifan Zhang 
---
 .../gpu/drm/amd/pm/swsmu/smu11/arcturus_ppt.c | 66 ---
 .../gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c   | 37 +++
 .../amd/pm/swsmu/smu11/sienna_cichlid_ppt.c   | 43 +++-
 .../gpu/drm/amd/pm/swsmu/smu11/vangogh_ppt.c  | 45 +++--
 .../drm/amd/pm/swsmu/smu13/aldebaran_ppt.c| 60 +
 .../drm/amd/pm/swsmu/smu13/smu_v13_0_0_ppt.c  | 20 ++  
.../drm/amd/pm/swsmu/smu13/smu_v13_0_6_ppt.c  | 22 ++-
 7 files changed, 61 insertions(+), 232 deletions(-)

diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu11/arcturus_ppt.c 
b/drivers/gpu/drm/amd/pm/swsmu/smu11/arcturus_ppt.c
index 44e4289b95cd..e38620e9436c 100644
--- a/drivers/gpu/drm/amd/pm/swsmu/smu11/arcturus_ppt.c
+++ b/drivers/gpu/drm/amd/pm/swsmu/smu11/arcturus_ppt.c
@@ -963,17 +963,10 @@ static int arcturus_force_clk_levels(struct smu_context 
*smu,
struct smu_11_0_dpm_context *dpm_context = smu->smu_dpm.dpm_context;
struct smu_11_0_dpm_table *single_dpm_table = NULL;
uint32_t soft_min_level, soft_max_level;
-   uint32_t smu_version;
int ret = 0;

-   ret = smu_cmn_get_smc_version(smu, NULL, _version);
-   if (ret) {
-   dev_err(smu->adev->dev, "Failed to get smu version!\n");
-   return ret;
-   }
-
-   if ((smu_version >= 0x361200) &&
-   (smu_version <= 0x361a00)) {
+   if ((smu->smc_fw_version >= 0x361200) &&
+   (smu->smc_fw_version <= 0x361a00)) {
dev_err(smu->adev->dev, "Forcing clock level is not supported 
with "
   "54.18 - 54.26(included) SMU firmwares\n");
return -EOPNOTSUPP;
@@ -1344,16 +1337,11 @@ static int arcturus_get_power_profile_mode(struct 
smu_context *smu,
uint32_t i, size = 0;
int16_t workload_type = 0;
int result = 0;
-   uint32_t smu_version;

if (!buf)
return -EINVAL;

-   result = smu_cmn_get_smc_version(smu, NULL, _version);
-   if (result)
-   return result;
-
-   if (smu_version >= 0x360d00)
+   if (smu->smc_fw_version >= 0x360d00)
size += sysfs_emit_at(buf, size, "%16s %s %s %s %s %s %s %s %s 
%s %s\n",
title[0], title[1], title[2], title[3], title[4], 
title[5],
title[6], title[7], title[8], title[9], title[10]); @@ 
-1372,7 +1360,7 @@ static int arcturus_get_power_profile_mode(struct 
smu_context *smu,
if (workload_type < 0)
continue;

-   if (smu_version >= 0x360d00) {
+   if (smu->smc_fw_version >= 0x360d00) {
result = smu_cmn_update_table(smu,
  
SMU_TABLE_ACTIVITY_MONITOR_COEFF,
  workload_type,
@@ -1387,7 +1375,7 @@ static int arcturus_get_power_profile_mode(struct 
smu_context *smu,
size += sysfs_emit_at(buf, size, "%2d %14s%s\n",
i, amdgpu_pp_profile_name[i], (i == 
smu->power_profile_mode) ? "*" : " ");

-   if (smu_version >= 0x360d00) {
+   if (smu->smc_fw_version >= 0x360d00) {
size += sysfs_emit_at(buf, size, "%19s %d(%13s) %7d %7d 
%7d %7d %7d %7d %7d %7d %7d\n",
" ",
0,
@@ -1429,19 +1417,15 @@ static int arcturus_set_power_profile_mode(struct 
smu_context *smu,
int workload_type = 0;
uint32_t profile_mode = input[size];
int ret = 0;
-   uint32_t smu_version;

if (profile_mode > PP_SMC_POWER_PROFILE_CUSTOM) {
dev_err(smu->adev->dev, "Invalid power profile mode %d\n", 
profile_mode);
return -EINVAL;
}

-   ret = smu_cmn_get_smc_version(smu, NULL, _version);
-   if (ret)
-   return ret;

if ((profile_mode == PP_SMC_POWER_PROFILE_CUSTOM) &&
-(smu_version >= 0x360d00)) {
+(smu->smc_fw_version >= 0x360d00)) {
ret = smu_cmn_update_table(smu,
   SMU_TABLE_ACTIVITY_MONITOR_COEFF,
   WORKLOAD_PPLIB_CUSTOM_BIT,
@@ -1517,15 +1501,8 @@ static int arcturus_set_power_profile_mode(struct 
smu_context *smu,  static int arcturus_set_performance_level(struct smu_context 
*smu,
  

[linux-next:master] BUILD REGRESSION c0a6edb636cba9c0d1db966a54d910a02e52e4be

2023-10-10 Thread kernel test robot
tree/branch: 
https://git.kernel.org/pub/scm/linux/kernel/git/next/linux-next.git master
branch HEAD: c0a6edb636cba9c0d1db966a54d910a02e52e4be  Add linux-next specific 
files for 20231010

Error/Warning reports:

https://lore.kernel.org/oe-kbuild-all/202309122047.cri9yjrq-...@intel.com
https://lore.kernel.org/oe-kbuild-all/202309160053.sfdnniu4-...@intel.com
https://lore.kernel.org/oe-kbuild-all/202309192314.vbsjiim5-...@intel.com
https://lore.kernel.org/oe-kbuild-all/202309202345.yprvhw8q-...@intel.com
https://lore.kernel.org/oe-kbuild-all/202309212121.cul1ptra-...@intel.com
https://lore.kernel.org/oe-kbuild-all/202309212339.hxhbu2f1-...@intel.com
https://lore.kernel.org/oe-kbuild-all/202310051547.40nm4sif-...@intel.com
https://lore.kernel.org/oe-kbuild-all/202310100409.lrbaypmk-...@intel.com

Error/Warning: (recently discovered and may have been fixed)

drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.c:274: warning: Function parameter or 
member 'gart_placement' not described in 'amdgpu_gmc_gart_location'
fs/bcachefs/bcachefs_format.h:215:25: warning: 'p' offset 3 in 'struct bkey' 
isn't aligned to 4 [-Wpacked-not-aligned]
fs/bcachefs/bcachefs_format.h:217:25: warning: 'version' offset 27 in 'struct 
bkey' isn't aligned to 4 [-Wpacked-not-aligned]
fs/bcachefs/btree_key_cache.c:113:7: warning: result of comparison of constant 
9223372036854775807 with expression of type 'u32' (aka 'unsigned int') is 
always true [-Wtautological-constant-out-of-range-compare]
include/linux/fortify-string.h:57:33: warning: writing 8 bytes into a region of 
size 0 [-Wstringop-overflow=]
kernel/bpf/helpers.c:1909:19: warning: no previous declaration for 
'bpf_percpu_obj_new_impl' [-Wmissing-declarations]
kernel/bpf/helpers.c:1945:18: warning: no previous declaration for 
'bpf_percpu_obj_drop_impl' [-Wmissing-declarations]
kernel/bpf/helpers.c:2480:18: warning: no previous declaration for 'bpf_throw' 
[-Wmissing-declarations]
lib/kunit/kunit-test.c:565:25: warning: cast from 'void (*)(const void *)' to 
'kunit_action_t *' (aka 'void (*)(void *)') converts to incompatible function 
type [-Wcast-function-type-strict]

Unverified Error/Warning (likely false positive, please contact us if 
interested):

arch/x86/kvm/x86.c:9016 x86_emulate_instruction() warn: missing error code? 'r'
drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c:538:25-29: ERROR: 
aconnector is NULL but dereferenced.

Error/Warning ids grouped by kconfigs:

gcc_recent_errors
|-- alpha-allyesconfig
|   `-- 
drivers-gpu-drm-amd-amdgpu-amdgpu_gmc.c:warning:Function-parameter-or-member-gart_placement-not-described-in-amdgpu_gmc_gart_location
|-- arc-allmodconfig
|   |-- 
drivers-gpu-drm-amd-amdgpu-amdgpu_gmc.c:warning:Function-parameter-or-member-gart_placement-not-described-in-amdgpu_gmc_gart_location
|   |-- 
fs-bcachefs-bcachefs_format.h:warning:p-offset-in-struct-bkey-isn-t-aligned-to
|   `-- 
fs-bcachefs-bcachefs_format.h:warning:version-offset-in-struct-bkey-isn-t-aligned-to
|-- arc-allyesconfig
|   |-- 
drivers-gpu-drm-amd-amdgpu-amdgpu_gmc.c:warning:Function-parameter-or-member-gart_placement-not-described-in-amdgpu_gmc_gart_location
|   |-- 
fs-bcachefs-bcachefs_format.h:warning:p-offset-in-struct-bkey-isn-t-aligned-to
|   `-- 
fs-bcachefs-bcachefs_format.h:warning:version-offset-in-struct-bkey-isn-t-aligned-to
|-- arm-allmodconfig
|   `-- 
drivers-gpu-drm-amd-amdgpu-amdgpu_gmc.c:warning:Function-parameter-or-member-gart_placement-not-described-in-amdgpu_gmc_gart_location
|-- arm-allyesconfig
|   `-- 
drivers-gpu-drm-amd-amdgpu-amdgpu_gmc.c:warning:Function-parameter-or-member-gart_placement-not-described-in-amdgpu_gmc_gart_location
|-- arm64-allmodconfig
|   |-- 
drivers-gpu-drm-amd-amdgpu-amdgpu_gmc.c:warning:Function-parameter-or-member-gart_placement-not-described-in-amdgpu_gmc_gart_location
|   `-- 
include-linux-fortify-string.h:warning:writing-bytes-into-a-region-of-size
|-- arm64-allyesconfig
|   |-- 
drivers-gpu-drm-amd-amdgpu-amdgpu_gmc.c:warning:Function-parameter-or-member-gart_placement-not-described-in-amdgpu_gmc_gart_location
|   `-- 
include-linux-fortify-string.h:warning:writing-bytes-into-a-region-of-size
|-- csky-allmodconfig
|   `-- 
drivers-gpu-drm-amd-amdgpu-amdgpu_gmc.c:warning:Function-parameter-or-member-gart_placement-not-described-in-amdgpu_gmc_gart_location
|-- csky-allyesconfig
|   `-- 
drivers-gpu-drm-amd-amdgpu-amdgpu_gmc.c:warning:Function-parameter-or-member-gart_placement-not-described-in-amdgpu_gmc_gart_location
|-- i386-allmodconfig
|   `-- 
drivers-gpu-drm-amd-amdgpu-amdgpu_gmc.c:warning:Function-parameter-or-member-gart_placement-not-described-in-amdgpu_gmc_gart_location
|-- i386-allyesconfig
|   `-- 
drivers-gpu-drm-amd-amdgpu-amdgpu_gmc.c:warning:Function-parameter-or-member-gart_placement-not-described-in-amdgpu_gmc_gart_location
|-- i386-randconfig-051-20231010
|   `-- 
drivers-gpu-drm-amd-amdgpu-amdgpu_gmc.c:warning:Function-parameter-or-member-gart_placement-not-described-in-amdgpu_gmc_gart_location
|-- loongarch

Re: [PATCH] drm/amd/pm: Fix a memory leak on an error path

2023-10-10 Thread Alex Deucher
Applied.  Thanks!

Alex

On Tue, Oct 10, 2023 at 2:32 AM Wang, Yang(Kevin)
 wrote:
>
> [AMD Official Use Only - General]
>
> Reviewed-by: Yang Wang 
>
> Best Regards,
> Kevin
>
> -Original Message-
> From: Kunwu.Chan 
> Sent: Tuesday, October 10, 2023 2:11 PM
> To: Wang, Yang(Kevin) 
> Cc: Deucher, Alexander ; Kamal, Asad 
> ; Koenig, Christian ; Zhang, 
> Hawking ; Ma, Le ; Lazar, Lijo 
> ; Pan, Xinhui ; airl...@gmail.com; 
> amd-gfx@lists.freedesktop.org; chen...@kylinos.cn; dan.carpen...@linaro.org; 
> dan...@ffwll.ch; dri-de...@lists.freedesktop.org; evan.q...@amd.com; 
> kunwu.c...@hotmail.com; linux-ker...@vger.kernel.org
> Subject: [PATCH] drm/amd/pm: Fix a memory leak on an error path
>
> Add missing free on an error path.
>
> Fixes: 511a95552ec8 ("drm/amd/pm: Add SMU 13.0.6 support")
> Signed-off-by: Kunwu.Chan 
> ---
>  drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_6_ppt.c | 4 +++-
>  1 file changed, 3 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_6_ppt.c 
> b/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_6_ppt.c
> index ce971a93d28b..c26e12ff532c 100644
> --- a/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_6_ppt.c
> +++ b/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_6_ppt.c
> @@ -1981,8 +1981,10 @@ static ssize_t smu_v13_0_6_get_gpu_metrics(struct 
> smu_context *smu, void **table
>
> metrics = kzalloc(sizeof(MetricsTable_t), GFP_KERNEL);
> ret = smu_v13_0_6_get_metrics_table(smu, metrics, true);
> -   if (ret)
> +   if (ret) {
> +   kfree(metrics);
> return ret;
> +   }
>
> smu_cmn_init_soft_gpu_metrics(gpu_metrics, 1, 3);
>
> --
> 2.25.1
>


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

2023-10-10 Thread Mario Limonciello

On 10/10/2023 07:59, 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  |   2 +-
  drivers/platform/x86/amd/pmf/acpi.c   |  37 +++
  drivers/platform/x86/amd/pmf/core.c   |  13 +++
  drivers/platform/x86/amd/pmf/pmf.h| 136 
  drivers/platform/x86/amd/pmf/tee-if.c | 146 +-
  5 files changed, 331 insertions(+), 3 deletions(-)

diff --git a/drivers/platform/x86/amd/pmf/Kconfig 
b/drivers/platform/x86/amd/pmf/Kconfig
index 32a029e8db80..f246252bddd8 100644
--- a/drivers/platform/x86/amd/pmf/Kconfig
+++ b/drivers/platform/x86/amd/pmf/Kconfig
@@ -9,7 +9,7 @@ config AMD_PMF
depends on POWER_SUPPLY
depends on AMD_NB
select ACPI_PLATFORM_PROFILE
-   depends on TEE
+   depends on TEE && AMDTEE
help
  This driver provides support for the AMD Platform Management 
Framework.
  The goal is to enhance end user experience by making AMD PCs smarter,
diff --git a/drivers/platform/x86/amd/pmf/acpi.c 
b/drivers/platform/x86/amd/pmf/acpi.c
index 3fc5e4547d9f..d0512af2cd42 100644
--- a/drivers/platform/x86/amd/pmf/acpi.c
+++ b/drivers/platform/x86/amd/pmf/acpi.c
@@ -286,6 +286,43 @@ int apmf_install_handler(struct amd_pmf_dev *pmf_dev)
return 0;
  }
  
+static acpi_status apmf_walk_resources(struct acpi_resource *res, void *data)

+{
+   struct amd_pmf_dev *dev = data;
+
+   switch (res->type) {
+   case ACPI_RESOURCE_TYPE_ADDRESS64:
+   dev->policy_addr = res->data.address64.address.minimum;
+   dev->policy_sz = res->data.address64.address.address_length;
+   break;
+   case ACPI_RESOURCE_TYPE_FIXED_MEMORY32:
+   dev->policy_addr = res->data.fixed_memory32.address;
+   dev->policy_sz = res->data.fixed_memory32.address_length;
+   break;
+   }
+
+   if (!dev->policy_addr || dev->policy_sz > POLICY_BUF_MAX_SZ || 
dev->policy_sz == 0) {
+   pr_err("Incorrect Policy params, possibly a SBIOS bug\n");
+   return AE_ERROR;
+   }
+
+   return AE_OK;
+}
+
+int apmf_check_smart_pc(struct amd_pmf_dev *pmf_dev)
+{
+   acpi_handle ahandle = ACPI_HANDLE(pmf_dev->dev);
+   acpi_status status;
+
+   status = acpi_walk_resources(ahandle, METHOD_NAME__CRS, 
apmf_walk_resources, pmf_dev);
+  

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

2023-10-10 Thread Mario Limonciello

On 10/10/2023 07:59, 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 


One minor nit below.

Reviewed-by: Mario Limonciello 


---
  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 | 36 ++-
  4 files changed, 70 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 ..6985bb5b9452
--- /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}=="0", 
RUN+="/usr/bin/systemctl suspend"
+DRIVERS=="amd-pmf", ACTION=="change", ENV{EVENT_ID}=="1", 
RUN+="/usr/bin/systemctl hibernate"
+DRIVERS=="amd-pmf", ACTION=="change", ENV{EVENT_ID}=="2", 
RUN+="/bin/loginctl lock-sessions"
+
+EVENT_ID values:
+0= Put the system to S0i3/S2Idle
+1= Put the system to hibernate
+2= Lock the screen
+
diff --git a/drivers/platform/x86/amd/pmf/pmf.h 
b/drivers/platform/x86/amd/pmf/pmf.h
index 20f3e16b0a32..67f3d5a7 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_MIN6
  #define PMF_POLICY_STT_SKINTEMP_APU   7
  #define PMF_POLICY_STT_SKINTEMP_HS2   8
+#define PMF_POLICY_SYSTEM_STATE9
  #define PMF_POLICY_P3T38
  
  /* TA macros */

@@ -440,6 +441,13 @@ struct apmf_dyn_slider_output {
  } __packed;
  
  /* Smart PC - TA internals */


I know that Ilpo had a comment about this in an earlier version that 
there is a "__" instead of "_".  I know this is intended behavior for 
consistency with internal usage, but maybe it's worth having a comment 
somewhere mentioning it's intended behavior?  I'm not sure where.



+enum system_state {
+   SYSTEM_STATE__S0i3,
+   SYSTEM_STATE__S4,
+   SYSTEM_STATE__SCREEN_LOCK,
+   SYSTEM_STATE__MAX
+};
+
  enum ta_slider {
TA_BEST_BATTERY,/* Best Battery */
TA_BETTER_BATTERY,  /* Better Battery */
@@ -471,6 +479,7 @@ enum ta_pmf_error_type {
  };
  
  struct pmf_action_table {

+   enum system_state system_state;
u32 spl;/* in mW */
u32 sppt;   /* in mW */
u32 sppt_apuonly;   /* in mW */
diff --git a/drivers/platform/x86/amd/pmf/tee-if.c 
b/drivers/platform/x86/amd/pmf/tee-if.c
index 92879ae4f8f0..c08ef13a1494 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,
 

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

2023-10-10 Thread Mario Limonciello

On 10/10/2023 07:59, 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 


Reviewed-by: Mario Limonciello 


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




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

2023-10-10 Thread Mario Limonciello

On 10/10/2023 07:59, 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.

make amd_sfh_float_to_int() as non-static function so that this can
be called outside of the current file.

Co-developed-by: Shyam Sundar S K 
Signed-off-by: Shyam Sundar S K 
Signed-off-by: Basavaraj Natikar 


Reviewed-by: Mario Limonciello 


---
  drivers/hid/amd-sfh-hid/amd_sfh_common.h  |  1 +
  drivers/hid/amd-sfh-hid/sfh1_1/amd_sfh_desc.c |  2 +-
  drivers/hid/amd-sfh-hid/sfh1_1/amd_sfh_init.c |  6 ++
  .../amd-sfh-hid/sfh1_1/amd_sfh_interface.c| 20 +++
  .../amd-sfh-hid/sfh1_1/amd_sfh_interface.h|  1 +
  drivers/platform/x86/amd/pmf/spc.c|  7 +++
  include/linux/amd-pmf-io.h|  2 ++
  7 files changed, 38 insertions(+), 1 deletion(-)

diff --git a/drivers/hid/amd-sfh-hid/amd_sfh_common.h 
b/drivers/hid/amd-sfh-hid/amd_sfh_common.h
index cd57037bf217..a1950bc6e6ce 100644
--- a/drivers/hid/amd-sfh-hid/amd_sfh_common.h
+++ b/drivers/hid/amd-sfh-hid/amd_sfh_common.h
@@ -39,6 +39,7 @@ struct amd_mp2_sensor_info {
  
  struct sfh_dev_status {

bool is_hpd_present;
+   bool is_als_present;
  };
  
  struct amd_mp2_dev {

diff --git a/drivers/hid/amd-sfh-hid/sfh1_1/amd_sfh_desc.c 
b/drivers/hid/amd-sfh-hid/sfh1_1/amd_sfh_desc.c
index 47a87b28e00e..dbc8c6943ca1 100644
--- a/drivers/hid/amd-sfh-hid/sfh1_1/amd_sfh_desc.c
+++ b/drivers/hid/amd-sfh-hid/sfh1_1/amd_sfh_desc.c
@@ -132,7 +132,7 @@ static void get_common_inputs(struct common_input_property 
*common, int report_i
common->event_type = HID_USAGE_SENSOR_EVENT_DATA_UPDATED_ENUM;
  }
  
-static int amd_sfh_float_to_int(u32 flt32_val)

+int amd_sfh_float_to_int(u32 flt32_val)


This change might roll into patch 14, but I don't think it's that big of 
a deal.



  {
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 3dc652d41d7d..f2890d329459 100644
--- a/drivers/hid/amd-sfh-hid/sfh1_1/amd_sfh_init.c
+++ b/drivers/hid/amd-sfh-hid/sfh1_1/amd_sfh_init.c
@@ -77,6 +77,9 @@ static int amd_sfh_hid_client_deinit(struct amd_mp2_dev 
*privdata)
case HPD_IDX:
privdata->dev_en.is_hpd_present = false;
break;
+   case ALS_IDX:
+   privdata->dev_en.is_als_present = false;
+   break;
}
  
  		if (cl_data->sensor_sts[i] == SENSOR_ENABLED) {

@@ -188,6 +191,9 @@ static int amd_sfh1_1_hid_client_init(struct amd_mp2_dev 
*privdata)
case HPD_IDX:
privdata->dev_en.is_hpd_present = true;
break;
+   case ALS_IDX:
+   privdata->dev_en.is_als_present = true;
+   break;
}
}
dev_dbg(dev, "sid 0x%x (%s) status 0x%x\n",
diff --git a/drivers/hid/amd-sfh-hid/sfh1_1/amd_sfh_interface.c 
b/drivers/hid/amd-sfh-hid/sfh1_1/amd_sfh_interface.c
index 7637da0dec6f..48a7a450e029 100644
--- a/drivers/hid/amd-sfh-hid/sfh1_1/amd_sfh_interface.c
+++ b/drivers/hid/amd-sfh-hid/sfh1_1/amd_sfh_interface.c
@@ -94,12 +94,32 @@ static int amd_sfh_hpd_info(u8 *user_present)
return -ENODEV;
  }
  
+static int amd_sfh_als_info(u32 *ambient_light)

+{
+   if (emp2 && emp2->dev_en.is_als_present) {
+   struct sfh_als_data als_data;
+   void __iomem *sensoraddr;
+
+   sensoraddr = emp2->vsbase +
+   (ALS_IDX * SENSOR_DATA_MEM_SIZE_DEFAULT) +
+   OFFSET_SENSOR_DATA_DEFAULT;
+   memcpy_fromio(_data, sensoraddr, sizeof(struct 
sfh_als_data));
+   *ambient_light = amd_sfh_float_to_int(als_data.lux);
+
+   return 0;
+   }
+
+   return -ENODEV;
+}
+
  int amd_get_sfh_info(struct amd_sfh_info *sfh_info, enum sfh_message_type op)
  {
if (sfh_info) {
switch (op) {
case MT_HPD:
return amd_sfh_hpd_info(_info->user_present);
+   case MT_ALS:
+   return amd_sfh_als_info(_info->ambient_light);
}
}
return -EINVAL;
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..7ecddad430e4 100644
--- a/drivers/hid/amd-sfh-hid/sfh1_1/amd_sfh_interface.h
+++ b/drivers/hid/amd-sfh-hid/sfh1_1/amd_sfh_interface.h
@@ -149,6 +149,7 @@ struct hpd_status {
};
  };
  
+int amd_sfh_float_to_int(u32 flt32_val);

  void sfh_interface_init(struct amd_mp2_dev *mp2);
  void amd_sfh1_1_set_desc_ops(struct 

Re: [PATCH] drm/amdkfd: Make EXT_COHERENT parameter affect APU svm memory

2023-10-10 Thread Philip Yang

  


On 2023-10-10 10:32, Francis, David
  wrote:


  
  
  
[AMD Official Use Only - General]
  
  
  

  [AMD Official Use Only - General]



  
By the
  intended semantics of the EXT_COHERENT parameter,
it should
  cause the driver to use MTYPE_UC instead of
MTYPE_NC on
  non-local gfx9.4.3 APU memory.

Signed-off-by:
  David Francis 
---
 drivers/gpu/drm/amd/amdkfd/kfd_svm.c
  | 2 +-
 1 file
  changed, 1 insertion(+), 1 deletion(-)

diff --git
  a/drivers/gpu/drm/amd/amdkfd/kfd_svm.c
  b/drivers/gpu/drm/amd/amdkfd/kfd_svm.c
index
  7b81233bc9ae..d9ef937308ed 100644
---
  a/drivers/gpu/drm/amd/amdkfd/kfd_svm.c
+++
  b/drivers/gpu/drm/amd/amdkfd/kfd_svm.c
@@ -1286,7
  +1286,7 @@ svm_range_get_pte_flags(struct kfd_node *node,

  if (num_possible_nodes() <= 1)

  mapping_flags |= mtype_local;

  else
-  
  mapping_flags |= AMDGPU_VM_MTYPE_NC;
+  
  mapping_flags |= ext_coherent ? AMDGPU_VM_MTYPE_UC :
  AMDGPU_VM_MTYPE_NC;
  

  

Thanks for finding this bug, I think on NUMA system with
  ext_coherent, we should use CC for local and UC for remote memory
  from another NUMA node.
The NUMA locality check is done in
  amdgpu_gmc_override_vm_pte_flag now, seems we need refactor and
  move the check here in order to use the prange->flags.


Regards,
Philip


  

  

  /* system memory accessed by the dGPU */

  } else {

  mapping_flags |= AMDGPU_VM_MTYPE_UC;
--
2.34.1
  

  

  



RE: [PATCH] drm/amd/swsmu: update smu v14_0_0 header files and metrics table

2023-10-10 Thread Deucher, Alexander
[Public]

> -Original Message-
> From: Ma, Li 
> Sent: Tuesday, October 10, 2023 9:48 AM
> To: amd-gfx@lists.freedesktop.org; Feng, Kenneth
> 
> Cc: Deucher, Alexander ; Zhang, Yifan
> ; Ma, Li 
> Subject: [PATCH] drm/amd/swsmu: update smu v14_0_0 header files and
> metrics table
>
> Update driver if, pmfw and ppsmc header files.
> Add new gpu_metrics_v3_0 for metrics table updated in driver if and reserve
> legacy metrics table to maintain backward compatibility.
>
> Signed-off-by: Li Ma 
> Reviewed-by: Yifan Zhang 

Acked-by: Alex Deucher 



[PATCH] drm/amd/pm: drop most smu_cmn_get_smc_version in smu

2023-10-10 Thread Yifan Zhang
smu_check_fw_version is called in smu hw init, thus smu if version
and version are garenteed to be stored in smu context. No need to
call smu_cmn_get_smc_version again after system boot up.

Signed-off-by: Yifan Zhang 
---
 .../gpu/drm/amd/pm/swsmu/smu11/arcturus_ppt.c | 66 ---
 .../gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c   | 37 +++
 .../amd/pm/swsmu/smu11/sienna_cichlid_ppt.c   | 43 +++-
 .../gpu/drm/amd/pm/swsmu/smu11/vangogh_ppt.c  | 45 +++--
 .../drm/amd/pm/swsmu/smu13/aldebaran_ppt.c| 60 +
 .../drm/amd/pm/swsmu/smu13/smu_v13_0_0_ppt.c  | 20 ++
 .../drm/amd/pm/swsmu/smu13/smu_v13_0_6_ppt.c  | 22 ++-
 7 files changed, 61 insertions(+), 232 deletions(-)

diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu11/arcturus_ppt.c 
b/drivers/gpu/drm/amd/pm/swsmu/smu11/arcturus_ppt.c
index 44e4289b95cd..e38620e9436c 100644
--- a/drivers/gpu/drm/amd/pm/swsmu/smu11/arcturus_ppt.c
+++ b/drivers/gpu/drm/amd/pm/swsmu/smu11/arcturus_ppt.c
@@ -963,17 +963,10 @@ static int arcturus_force_clk_levels(struct smu_context 
*smu,
struct smu_11_0_dpm_context *dpm_context = smu->smu_dpm.dpm_context;
struct smu_11_0_dpm_table *single_dpm_table = NULL;
uint32_t soft_min_level, soft_max_level;
-   uint32_t smu_version;
int ret = 0;
 
-   ret = smu_cmn_get_smc_version(smu, NULL, _version);
-   if (ret) {
-   dev_err(smu->adev->dev, "Failed to get smu version!\n");
-   return ret;
-   }
-
-   if ((smu_version >= 0x361200) &&
-   (smu_version <= 0x361a00)) {
+   if ((smu->smc_fw_version >= 0x361200) &&
+   (smu->smc_fw_version <= 0x361a00)) {
dev_err(smu->adev->dev, "Forcing clock level is not supported 
with "
   "54.18 - 54.26(included) SMU firmwares\n");
return -EOPNOTSUPP;
@@ -1344,16 +1337,11 @@ static int arcturus_get_power_profile_mode(struct 
smu_context *smu,
uint32_t i, size = 0;
int16_t workload_type = 0;
int result = 0;
-   uint32_t smu_version;
 
if (!buf)
return -EINVAL;
 
-   result = smu_cmn_get_smc_version(smu, NULL, _version);
-   if (result)
-   return result;
-
-   if (smu_version >= 0x360d00)
+   if (smu->smc_fw_version >= 0x360d00)
size += sysfs_emit_at(buf, size, "%16s %s %s %s %s %s %s %s %s 
%s %s\n",
title[0], title[1], title[2], title[3], title[4], 
title[5],
title[6], title[7], title[8], title[9], title[10]);
@@ -1372,7 +1360,7 @@ static int arcturus_get_power_profile_mode(struct 
smu_context *smu,
if (workload_type < 0)
continue;
 
-   if (smu_version >= 0x360d00) {
+   if (smu->smc_fw_version >= 0x360d00) {
result = smu_cmn_update_table(smu,
  
SMU_TABLE_ACTIVITY_MONITOR_COEFF,
  workload_type,
@@ -1387,7 +1375,7 @@ static int arcturus_get_power_profile_mode(struct 
smu_context *smu,
size += sysfs_emit_at(buf, size, "%2d %14s%s\n",
i, amdgpu_pp_profile_name[i], (i == 
smu->power_profile_mode) ? "*" : " ");
 
-   if (smu_version >= 0x360d00) {
+   if (smu->smc_fw_version >= 0x360d00) {
size += sysfs_emit_at(buf, size, "%19s %d(%13s) %7d %7d 
%7d %7d %7d %7d %7d %7d %7d\n",
" ",
0,
@@ -1429,19 +1417,15 @@ static int arcturus_set_power_profile_mode(struct 
smu_context *smu,
int workload_type = 0;
uint32_t profile_mode = input[size];
int ret = 0;
-   uint32_t smu_version;
 
if (profile_mode > PP_SMC_POWER_PROFILE_CUSTOM) {
dev_err(smu->adev->dev, "Invalid power profile mode %d\n", 
profile_mode);
return -EINVAL;
}
 
-   ret = smu_cmn_get_smc_version(smu, NULL, _version);
-   if (ret)
-   return ret;
 
if ((profile_mode == PP_SMC_POWER_PROFILE_CUSTOM) &&
-(smu_version >= 0x360d00)) {
+(smu->smc_fw_version >= 0x360d00)) {
ret = smu_cmn_update_table(smu,
   SMU_TABLE_ACTIVITY_MONITOR_COEFF,
   WORKLOAD_PPLIB_CUSTOM_BIT,
@@ -1517,15 +1501,8 @@ static int arcturus_set_power_profile_mode(struct 
smu_context *smu,
 static int arcturus_set_performance_level(struct smu_context *smu,
  enum amd_dpm_forced_level level)
 {
-   uint32_t smu_version;
int ret;
 
-   ret = smu_cmn_get_smc_version(smu, NULL, _version);
-   if (ret) {
-   dev_err(smu->adev->dev, "Failed to get smu version!\n");
-   return ret;
-   }
-
switch (level) {

[PATCH v2 4/7] amd/amdkfd: Unmap range from GPUs based on granularity

2023-10-10 Thread Philip Yang
When migrating the range to unmap the range from GPUs, align unmap start
and last address to the range granularity boundary. Skip unmap from
GPU if range is already unmapped from GPUs based on bitmap_mapped flag.

This optimizes the TLB flush and also solve the rocgdb CWSR migration
related issue.

Signed-off-by: Philip Yang 
---
 drivers/gpu/drm/amd/amdkfd/kfd_svm.c | 35 
 1 file changed, 31 insertions(+), 4 deletions(-)

diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_svm.c 
b/drivers/gpu/drm/amd/amdkfd/kfd_svm.c
index 4e1af4b181ea..daa996d7039d 100644
--- a/drivers/gpu/drm/amd/amdkfd/kfd_svm.c
+++ b/drivers/gpu/drm/amd/amdkfd/kfd_svm.c
@@ -2066,6 +2066,26 @@ static void svm_range_restore_work(struct work_struct 
*work)
mmput(mm);
 }
 
+static unsigned long
+svm_range_align_start(struct svm_range *prange, unsigned long start)
+{
+   unsigned long start_align;
+
+   start_align = ALIGN_DOWN(start, 1UL << prange->granularity);
+   start_align = max_t(unsigned long, start_align, prange->start);
+   return start_align;
+}
+
+static unsigned long
+svm_range_align_last(struct svm_range *prange, unsigned long last)
+{
+   unsigned long last_align;
+
+   last_align = ALIGN(last + 1, 1UL << prange->granularity) - 1;
+   last_align = min_t(unsigned long, last_align, prange->last);
+   return last_align;
+}
+
 /**
  * svm_range_evict - evict svm range
  * @prange: svm range structure
@@ -2126,6 +2146,12 @@ svm_range_evict(struct svm_range *prange, struct 
mm_struct *mm,
unsigned long s, l;
uint32_t trigger;
 
+   if (!svm_range_partial_mapped(prange, start, last)) {
+   pr_debug("svms 0x%p [0x%lx 0x%lx] unmapped already\n",
+   prange->svms, start, last);
+   return 0;
+   }
+
if (event == MMU_NOTIFY_MIGRATE)
trigger = KFD_SVM_UNMAP_TRIGGER_MMU_NOTIFY_MIGRATE;
else
@@ -2133,16 +2159,17 @@ svm_range_evict(struct svm_range *prange, struct 
mm_struct *mm,
 
pr_debug("invalidate unmap svms 0x%p [0x%lx 0x%lx] from GPUs\n",
 prange->svms, start, last);
+
list_for_each_entry(pchild, >child_list, child_list) {
mutex_lock_nested(>lock, 1);
-   s = max(start, pchild->start);
-   l = min(last, pchild->last);
+   s = svm_range_align_start(pchild, start);
+   l = svm_range_align_last(pchild, last);
if (l >= s)
svm_range_unmap_from_gpus(pchild, s, l, 
trigger);
mutex_unlock(>lock);
}
-   s = max(start, prange->start);
-   l = min(last, prange->last);
+   s = svm_range_align_start(prange, start);
+   l = svm_range_align_last(prange, last);
if (l >= s)
svm_range_unmap_from_gpus(prange, s, l, trigger);
}
-- 
2.35.1



[PATCH v2 2/7] drm/amdkfd: Add helper function svm_range_need_access_gpus

2023-10-10 Thread Philip Yang
Refactor svm_range_validate_and_map to add and use the helper function
to get all GPUs bitmap that need access the svm range. No functional
change. This helper will be used in the following patch.

Signed-off-by: Philip Yang 
---
 drivers/gpu/drm/amd/amdkfd/kfd_svm.c | 55 +---
 1 file changed, 34 insertions(+), 21 deletions(-)

diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_svm.c 
b/drivers/gpu/drm/amd/amdkfd/kfd_svm.c
index e195106a77cb..fb22b857adbc 100644
--- a/drivers/gpu/drm/amd/amdkfd/kfd_svm.c
+++ b/drivers/gpu/drm/amd/amdkfd/kfd_svm.c
@@ -1191,6 +1191,34 @@ svm_range_split_by_granularity(struct kfd_process *p, 
struct mm_struct *mm,
}
return 0;
 }
+
+static int
+svm_range_need_access_gpus(unsigned long *bitmap, struct svm_range *prange)
+{
+   struct kfd_process *p = container_of(prange->svms, struct kfd_process, 
svms);
+   uint32_t gpuidx;
+
+   if (p->xnack_enabled) {
+   bitmap_copy(bitmap, prange->bitmap_aip, MAX_GPU_INSTANCE);
+
+   /* If prefetch range to GPU, or GPU retry fault migrate range to
+* GPU, which has ACCESS attribute to the range, create mapping
+* on that GPU.
+*/
+   if (prange->actual_loc) {
+   gpuidx = kfd_process_gpuidx_from_gpuid(p, 
prange->actual_loc);
+   if (gpuidx < 0)
+   return -EINVAL;
+   if (test_bit(gpuidx, prange->bitmap_access))
+   bitmap_set(bitmap, gpuidx, 1);
+   }
+   } else {
+   bitmap_or(bitmap, prange->bitmap_access, prange->bitmap_aip,
+ MAX_GPU_INSTANCE);
+   }
+   return 0;
+}
+
 static bool
 svm_nodes_in_same_hive(struct kfd_node *node_a, struct kfd_node *node_b)
 {
@@ -1631,28 +1659,13 @@ static int svm_range_validate_and_map(struct mm_struct 
*mm,
if (gpuidx < MAX_GPU_INSTANCE) {
bitmap_zero(ctx->bitmap, MAX_GPU_INSTANCE);
bitmap_set(ctx->bitmap, gpuidx, 1);
-   } else if (ctx->process->xnack_enabled) {
-   bitmap_copy(ctx->bitmap, prange->bitmap_aip, MAX_GPU_INSTANCE);
-
-   /* If prefetch range to GPU, or GPU retry fault migrate range to
-* GPU, which has ACCESS attribute to the range, create mapping
-* on that GPU.
-*/
-   if (prange->actual_loc) {
-   gpuidx = kfd_process_gpuidx_from_gpuid(ctx->process,
-   prange->actual_loc);
-   if (gpuidx < 0) {
-   WARN_ONCE(1, "failed get device by id 0x%x\n",
-prange->actual_loc);
-   r = -EINVAL;
-   goto free_ctx;
-   }
-   if (test_bit(gpuidx, prange->bitmap_access))
-   bitmap_set(ctx->bitmap, gpuidx, 1);
-   }
} else {
-   bitmap_or(ctx->bitmap, prange->bitmap_access,
- prange->bitmap_aip, MAX_GPU_INSTANCE);
+   r = svm_range_need_access_gpus(ctx->bitmap, prange);
+   if (r) {
+   WARN_ONCE(1, "failed get device by id 0x%x\n",
+prange->actual_loc);
+   goto free_ctx;
+   }
}
 
if (bitmap_empty(ctx->bitmap, MAX_GPU_INSTANCE)) {
-- 
2.35.1



[PATCH v2 5/7] drm/amdkfd: Check bitmap_mapped flag to skip retry fault

2023-10-10 Thread Philip Yang
Remove prange validate_timestamp which is not accurate for multiple
GPUs.

Use the bitmap_mapped flag to skip the retry fault from different pages
of the same range if the range is already mapped on the specific GPU.

Signed-off-by: Philip Yang 
Reviewed-by: Felix Kuehling 
---
 drivers/gpu/drm/amd/amdkfd/kfd_svm.c | 24 
 drivers/gpu/drm/amd/amdkfd/kfd_svm.h |  1 -
 2 files changed, 8 insertions(+), 17 deletions(-)

diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_svm.c 
b/drivers/gpu/drm/amd/amdkfd/kfd_svm.c
index daa996d7039d..0ee5633c8972 100644
--- a/drivers/gpu/drm/amd/amdkfd/kfd_svm.c
+++ b/drivers/gpu/drm/amd/amdkfd/kfd_svm.c
@@ -43,10 +43,6 @@
 
 #define AMDGPU_SVM_RANGE_RESTORE_DELAY_MS 1
 
-/* Long enough to ensure no retry fault comes after svm range is restored and
- * page table is updated.
- */
-#define AMDGPU_SVM_RANGE_RETRY_FAULT_PENDING   (2UL * NSEC_PER_MSEC)
 #if IS_ENABLED(CONFIG_DYNAMIC_DEBUG)
 #define dynamic_svm_range_dump(svms) \
_dynamic_func_call_no_desc("svm_range_dump", svm_range_debug_dump, svms)
@@ -369,7 +365,6 @@ svm_range *svm_range_new(struct svm_range_list *svms, 
uint64_t start,
INIT_LIST_HEAD(>deferred_list);
INIT_LIST_HEAD(>child_list);
atomic_set(>invalid, 0);
-   prange->validate_timestamp = 0;
prange->vram_pages = 0;
mutex_init(>migrate_mutex);
mutex_init(>lock);
@@ -1938,8 +1933,6 @@ static int svm_range_validate_and_map(struct mm_struct 
*mm,
}
 
svm_range_unreserve_bos(ctx);
-   if (!r)
-   prange->validate_timestamp = ktime_get_boottime();
 
 free_ctx:
kfree(ctx);
@@ -3214,15 +3207,6 @@ svm_range_restore_pages(struct amdgpu_device *adev, 
unsigned int pasid,
goto out_unlock_range;
}
 
-   /* skip duplicate vm fault on different pages of same range */
-   if (ktime_before(timestamp, ktime_add_ns(prange->validate_timestamp,
-   AMDGPU_SVM_RANGE_RETRY_FAULT_PENDING))) {
-   pr_debug("svms 0x%p [0x%lx %lx] already restored\n",
-svms, prange->start, prange->last);
-   r = 0;
-   goto out_unlock_range;
-   }
-
/* __do_munmap removed VMA, return success as we are handling stale
 * retry fault.
 */
@@ -3248,6 +3232,14 @@ svm_range_restore_pages(struct amdgpu_device *adev, 
unsigned int pasid,
goto out_unlock_range;
}
 
+   /* skip duplicate vm fault on different pages of same granularity range 
*/
+   if (svm_range_partial_mapped_dev(gpuidx, prange, addr, addr)) {
+   pr_debug("svms 0x%p [0x%lx %lx] addr 0x%llx already mapped on 
gpu %d\n",
+svms, prange->start, prange->last, addr, gpuidx);
+   r = 0;
+   goto out_unlock_range;
+   }
+
pr_debug("svms %p [0x%lx 0x%lx] best restore 0x%x, actual loc 0x%x\n",
 svms, prange->start, prange->last, best_loc,
 prange->actual_loc);
diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_svm.h 
b/drivers/gpu/drm/amd/amdkfd/kfd_svm.h
index 7e165854bc0e..7a12be42cf16 100644
--- a/drivers/gpu/drm/amd/amdkfd/kfd_svm.h
+++ b/drivers/gpu/drm/amd/amdkfd/kfd_svm.h
@@ -129,7 +129,6 @@ struct svm_range {
uint32_tactual_loc;
uint8_t granularity;
atomic_tinvalid;
-   ktime_t validate_timestamp;
struct mmu_interval_notifiernotifier;
struct svm_work_list_item   work_item;
struct list_headdeferred_list;
-- 
2.35.1



[PATCH v2 7/7] drm/amdkfd: Changing range granularity update bitmap_mapped

2023-10-10 Thread Philip Yang
When changing the svm range granularity, update the svm range
bitmap_mapped accordingly.

Signed-off-by: Philip Yang 
---
 drivers/gpu/drm/amd/amdkfd/kfd_svm.c | 49 +++-
 1 file changed, 48 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_svm.c 
b/drivers/gpu/drm/amd/amdkfd/kfd_svm.c
index e1392b277399..55b806048925 100644
--- a/drivers/gpu/drm/amd/amdkfd/kfd_svm.c
+++ b/drivers/gpu/drm/amd/amdkfd/kfd_svm.c
@@ -739,6 +739,53 @@ svm_range_check_attr(struct kfd_process *p,
return 0;
 }
 
+static void
+svm_range_change_granularity(struct svm_range *prange, uint8_t value)
+{
+   struct kfd_process *p = container_of(prange->svms, struct kfd_process, 
svms);
+   unsigned int nbits_new, nbits_old, i, n;
+   unsigned long *bits_new, *bits_old;
+   int gpuidx;
+
+   if (prange->granularity == value)
+   return;
+
+   nbits_old = svm_range_mapped_nbits(prange->start, prange->last, 
prange->granularity);
+   nbits_new = svm_range_mapped_nbits(prange->start, prange->last, value);
+   if (nbits_new > nbits_old) {
+   n = nbits_new / nbits_old;
+   if (nbits_new % nbits_old)
+   n++;
+   } else {
+   n = nbits_old / nbits_new;
+   if (nbits_old % nbits_new)
+   n++;
+   }
+
+   pr_debug("prange 0x%p [0x%lx 0x%lx] bitmap_mapped nbits %d -> %d\n",
+prange, prange->start, prange->last, nbits_old, nbits_new);
+
+   for_each_set_bit(gpuidx, p->svms.bitmap_supported, p->n_pdds) {
+   bits_old = prange->bitmap_mapped[gpuidx];
+   if (bitmap_empty(bits_old, nbits_old))
+   continue;
+
+   bits_new = bitmap_zalloc(nbits_new, GFP_KERNEL);
+   if (!bits_new)
+   return;
+
+   for_each_set_bit(i, bits_old, nbits_old) {
+   if (nbits_new > nbits_old)
+   bitmap_set(bits_new, i * n, n);
+   else
+   bitmap_set(bits_new, i / n, 1);
+   }
+   bitmap_free(bits_old);
+   prange->bitmap_mapped[gpuidx] = bits_new;
+   }
+   prange->granularity = value;
+}
+
 static void
 svm_range_apply_attrs(struct kfd_process *p, struct svm_range *prange,
  uint32_t nattr, struct kfd_ioctl_svm_attribute *attrs,
@@ -783,7 +830,7 @@ svm_range_apply_attrs(struct kfd_process *p, struct 
svm_range *prange,
prange->flags &= ~attrs[i].value;
break;
case KFD_IOCTL_SVM_ATTR_GRANULARITY:
-   prange->granularity = attrs[i].value;
+   svm_range_change_granularity(prange, attrs[i].value);
break;
default:
WARN_ONCE(1, "svm_range_check_attrs wasn't called?");
-- 
2.35.1



[PATCH v2 6/7] drm/amdkfd: Unmap from cpu split the range and bitmap_mapped

2023-10-10 Thread Philip Yang
Unmap the svm range from cpu will unmap and remove ranges, this cannot
align the start and last address to range granularity. If we unmap
from GPUs first, the bitmap_mapped flag is updated, split may get
incorrect bitmap_mapped for the remaining ranges.

We should split the range and bitmap_mapped first, then unmap the range
from GPUs.

Signed-off-by: Philip Yang 
---
 drivers/gpu/drm/amd/amdkfd/kfd_svm.c | 26 +-
 1 file changed, 17 insertions(+), 9 deletions(-)

diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_svm.c 
b/drivers/gpu/drm/amd/amdkfd/kfd_svm.c
index 0ee5633c8972..e1392b277399 100644
--- a/drivers/gpu/drm/amd/amdkfd/kfd_svm.c
+++ b/drivers/gpu/drm/amd/amdkfd/kfd_svm.c
@@ -2672,24 +2672,32 @@ svm_range_unmap_from_cpu(struct mm_struct *mm, struct 
svm_range *prange,
 
list_for_each_entry(pchild, >child_list, child_list) {
mutex_lock_nested(>lock, 1);
-   s = max(start, pchild->start);
-   l = min(last, pchild->last);
-   if (l >= s)
-   svm_range_unmap_from_gpus(pchild, s, l, trigger);
svm_range_unmap_split(mm, prange, pchild, start, last);
mutex_unlock(>lock);
}
-   s = max(start, prange->start);
-   l = min(last, prange->last);
-   if (l >= s)
-   svm_range_unmap_from_gpus(prange, s, l, trigger);
svm_range_unmap_split(mm, prange, prange, start, last);
-
if (unmap_parent)
svm_range_add_list_work(svms, prange, mm, SVM_OP_UNMAP_RANGE);
else
svm_range_add_list_work(svms, prange, mm,
SVM_OP_UPDATE_RANGE_NOTIFIER);
+
+   list_for_each_entry(pchild, >child_list, child_list) {
+   if (pchild->work_item.op != SVM_OP_UNMAP_RANGE)
+   continue;
+
+   s = max(start, pchild->start);
+   l = min(last, pchild->last);
+   if (l >= s)
+   svm_range_unmap_from_gpus(pchild, s, l, trigger);
+   }
+   if (prange->work_item.op == SVM_OP_UNMAP_RANGE) {
+   s = max(start, prange->start);
+   l = min(last, prange->last);
+   if (l >= s)
+   svm_range_unmap_from_gpus(prange, s, l, trigger);
+   }
+
schedule_deferred_list_work(svms);
 
kfd_unref_process(p);
-- 
2.35.1



[PATCH v2 3/7] amd/amdkfd: Add granularity bitmap mapped to gpu flag

2023-10-10 Thread Philip Yang
Replace prange->mapped_to_gpu with prange->bitmap_mapped[], which is per
GPU flag and based on prange granularity, updated when map to GPUS or
unmap from GPUs, to optimize multiple GPU map, unmap and retry fault
recover.

svm_range_partial_mapped is false only if no part of the range mapping
on any GPUs.

Signed-off-by: Philip Yang 
---
 drivers/gpu/drm/amd/amdkfd/kfd_svm.c | 256 +--
 drivers/gpu/drm/amd/amdkfd/kfd_svm.h |   8 +-
 2 files changed, 213 insertions(+), 51 deletions(-)

diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_svm.c 
b/drivers/gpu/drm/amd/amdkfd/kfd_svm.c
index fb22b857adbc..4e1af4b181ea 100644
--- a/drivers/gpu/drm/amd/amdkfd/kfd_svm.c
+++ b/drivers/gpu/drm/amd/amdkfd/kfd_svm.c
@@ -296,12 +296,12 @@ static void svm_range_free(struct svm_range *prange, bool 
do_unmap)
KFD_IOC_ALLOC_MEM_FLAGS_USERPTR, 0);
}
 
-   /* free dma_addr array for each gpu */
+   /* free dma_addr array, bitmap_mapped for each gpu */
for (gpuidx = 0; gpuidx < MAX_GPU_INSTANCE; gpuidx++) {
-   if (prange->dma_addr[gpuidx]) {
+   if (prange->dma_addr[gpuidx])
kvfree(prange->dma_addr[gpuidx]);
-   prange->dma_addr[gpuidx] = NULL;
-   }
+   if (prange->bitmap_mapped[gpuidx])
+   bitmap_free(prange->bitmap_mapped[gpuidx]);
}
 
mutex_destroy(>lock);
@@ -327,19 +327,38 @@ svm_range *svm_range_new(struct svm_range_list *svms, 
uint64_t start,
uint64_t size = last - start + 1;
struct svm_range *prange;
struct kfd_process *p;
-
-   prange = kzalloc(sizeof(*prange), GFP_KERNEL);
-   if (!prange)
-   return NULL;
+   unsigned int nbits;
+   uint32_t gpuidx;
 
p = container_of(svms, struct kfd_process, svms);
if (!p->xnack_enabled && update_mem_usage &&
amdgpu_amdkfd_reserve_mem_limit(NULL, size << PAGE_SHIFT,
KFD_IOC_ALLOC_MEM_FLAGS_USERPTR, 0)) {
pr_info("SVM mapping failed, exceeds resident system memory 
limit\n");
-   kfree(prange);
return NULL;
}
+
+   prange = kzalloc(sizeof(*prange), GFP_KERNEL);
+   if (!prange)
+   return NULL;
+
+   svm_range_set_default_attributes(>preferred_loc,
+>prefetch_loc,
+>granularity, >flags);
+
+   nbits = svm_range_mapped_nbits(start, last, prange->granularity);
+   pr_debug("prange 0x%p [0x%llx 0x%llx] bitmap_mapped nbits %d\n", prange,
+start, last, nbits);
+   for_each_set_bit(gpuidx, p->svms.bitmap_supported, p->n_pdds) {
+   prange->bitmap_mapped[gpuidx] = bitmap_zalloc(nbits, 
GFP_KERNEL);
+   if (!prange->bitmap_mapped[gpuidx]) {
+   while (gpuidx--)
+   bitmap_free(prange->bitmap_mapped[gpuidx]);
+   kfree(prange);
+   return NULL;
+   }
+   }
+
prange->npages = size;
prange->svms = svms;
prange->start = start;
@@ -359,10 +378,6 @@ svm_range *svm_range_new(struct svm_range_list *svms, 
uint64_t start,
bitmap_copy(prange->bitmap_access, svms->bitmap_supported,
MAX_GPU_INSTANCE);
 
-   svm_range_set_default_attributes(>preferred_loc,
->prefetch_loc,
->granularity, >flags);
-
pr_debug("svms 0x%p [0x%llx 0x%llx]\n", svms, start, last);
 
return prange;
@@ -984,6 +999,47 @@ svm_range_split_nodes(struct svm_range *new, struct 
svm_range *old,
return 0;
 }
 
+static int
+svm_range_split_bitmap_mapped(struct svm_range *new, struct svm_range *old,
+ uint64_t start, uint64_t last)
+{
+   struct kfd_process *p = container_of(new->svms, struct kfd_process, 
svms);
+   unsigned int nbits, old_nbits, old_nbits2;
+   unsigned long *bits;
+   uint32_t gpuidx;
+
+   nbits = svm_range_mapped_nbits(new->start, new->last, new->granularity);
+   old_nbits = svm_range_mapped_nbits(old->start, old->last, 
old->granularity);
+   old_nbits2 = svm_range_mapped_nbits(start, last, old->granularity);
+
+   pr_debug("old 0x%p [0x%lx 0x%lx] => [0x%llx 0x%llx] nbits %d => %d\n",
+old, old->start, old->last, start, last, old_nbits, 
old_nbits2);
+   pr_debug("new 0x%p [0x%lx 0x%lx] nbits %d\n", new, new->start, 
new->last,
+nbits);
+
+   for_each_set_bit(gpuidx, p->svms.bitmap_supported, p->n_pdds) {
+   bits = bitmap_alloc(old_nbits2, GFP_KERNEL);
+   if (!bits)
+   return -ENOMEM;
+
+   if (start == old->start) {
+   

[PATCH v2 1/7] drm/amdkfd: Wait vm update fence after retry fault recovered

2023-10-10 Thread Philip Yang
If using sdma update GPU page table, kfd flush tlb does nothing if vm
update fence callback doesn't update vm->tlb_seq. This works now because
retry fault keep coming and will be handled to update page table again
after AMDGPU_SVM_RANGE_RETRY_FAULT_PENDING timeout and flush tlb.

With the following patch to add bitmap_mapped flag, the retry fault
recover will only update GPU page table once, need wait vm udate fence
and then flush tlb.

No change if using CPU update GPU page table because no vm update fence.

Remove wait parameter in svm_range_validate_and_map because it is
always called with true now.

Signed-off-by: Philip Yang 
---
 drivers/gpu/drm/amd/amdkfd/kfd_svm.c | 15 +++
 1 file changed, 7 insertions(+), 8 deletions(-)

diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_svm.c 
b/drivers/gpu/drm/amd/amdkfd/kfd_svm.c
index 2b4ccc0531e8..e195106a77cb 100644
--- a/drivers/gpu/drm/amd/amdkfd/kfd_svm.c
+++ b/drivers/gpu/drm/amd/amdkfd/kfd_svm.c
@@ -1454,7 +1454,7 @@ svm_range_map_to_gpu(struct kfd_process_device *pdd, 
struct svm_range *prange,
 static int
 svm_range_map_to_gpus(struct svm_range *prange, unsigned long offset,
  unsigned long npages, bool readonly,
- unsigned long *bitmap, bool wait, bool flush_tlb)
+ unsigned long *bitmap, bool flush_tlb)
 {
struct kfd_process_device *pdd;
struct amdgpu_device *bo_adev = NULL;
@@ -1487,8 +1487,7 @@ svm_range_map_to_gpus(struct svm_range *prange, unsigned 
long offset,
 
r = svm_range_map_to_gpu(pdd, prange, offset, npages, readonly,
 prange->dma_addr[gpuidx],
-bo_adev, wait ?  : NULL,
-flush_tlb);
+bo_adev, , flush_tlb);
if (r)
break;
 
@@ -1612,7 +1611,7 @@ static void *kfd_svm_page_owner(struct kfd_process *p, 
int32_t gpuidx)
  */
 static int svm_range_validate_and_map(struct mm_struct *mm,
  struct svm_range *prange, int32_t gpuidx,
- bool intr, bool wait, bool flush_tlb)
+ bool intr, bool flush_tlb)
 {
struct svm_validate_context *ctx;
unsigned long start, end, addr;
@@ -1741,7 +1740,7 @@ static int svm_range_validate_and_map(struct mm_struct 
*mm,
 
if (!r)
r = svm_range_map_to_gpus(prange, offset, npages, 
readonly,
- ctx->bitmap, wait, flush_tlb);
+ ctx->bitmap, flush_tlb);
 
if (!r && next == end)
prange->mapped_to_gpu = true;
@@ -1848,7 +1847,7 @@ static void svm_range_restore_work(struct work_struct 
*work)
mutex_lock(>migrate_mutex);
 
r = svm_range_validate_and_map(mm, prange, MAX_GPU_INSTANCE,
-  false, true, false);
+  false, false);
if (r)
pr_debug("failed %d to map 0x%lx to gpus\n", r,
 prange->start);
@@ -3094,7 +3093,7 @@ svm_range_restore_pages(struct amdgpu_device *adev, 
unsigned int pasid,
}
}
 
-   r = svm_range_validate_and_map(mm, prange, gpuidx, false, false, false);
+   r = svm_range_validate_and_map(mm, prange, gpuidx, false, false);
if (r)
pr_debug("failed %d to map svms 0x%p [0x%lx 0x%lx] to gpus\n",
 r, svms, prange->start, prange->last);
@@ -3643,7 +3642,7 @@ svm_range_set_attr(struct kfd_process *p, struct 
mm_struct *mm,
flush_tlb = !migrated && update_mapping && 
prange->mapped_to_gpu;
 
r = svm_range_validate_and_map(mm, prange, MAX_GPU_INSTANCE,
-  true, true, flush_tlb);
+  true, flush_tlb);
if (r)
pr_debug("failed %d to map svm range\n", r);
 
-- 
2.35.1



Re: [PATCH] drm/amd/display: Enable fast plane updates on DCN3.2 and above when state->allow_modeset = true

2023-10-10 Thread Aurabindo Pillai




On 10/9/2023 6:36 PM, Mario Limonciello wrote:

On 10/7/2023 00:41, Tianci Yin wrote:

From: tiancyin 

[why]
When cursor moves across screen boarder, lag cursor observed,
since subvp settings need to sync up with vblank, that cause
cursor updates being delayed.

[how]
Enable fast plane updates on DCN3.2 to fix it.

Signed-off-by: tiancyin 
---
  drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 3 ++-
  1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c 
b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c

index c21726bdbca2..25a0bd314fe5 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
@@ -9879,6 +9879,7 @@ static bool should_reset_plane(struct 
drm_atomic_state *state,

  struct drm_plane *other;
  struct drm_plane_state *old_other_state, *new_other_state;
  struct drm_crtc_state *new_crtc_state;
+    struct amdgpu_device *adev = drm_to_adev(plane->dev);
  int i;
  /*
@@ -9886,7 +9887,7 @@ static bool should_reset_plane(struct 
drm_atomic_state *state,

   * enough to determine when we need to reset all the planes on
   * the stream.
   */
-    if (state->allow_modeset)
+    if (adev->ip_versions[DCE_HWIP][0] < IP_VERSION(3, 2, 0) && 
state->allow_modeset)

  return true;
  /* Exit early if we know that we're adding or removing the 
plane. */


The comment associated with this says that this hack should go when 
there are sufficient checks.


If there are enough checks for DCN3.2, isn't it likely there are enough 
for earlier products too?  None of the rest of the code checks a 
specific IP version.


Maybe the whole commit/block should go?



The lag issue was only seen on DCN32 though. We could potentially try to 
enable it for all asic, but its very likely to create regressions. I'm 
okay with adding a TODO comment for now, stating that this needs to be 
enabled on other DCN version too. So just DCN32+ looks like a good start.


With the TODO comment added, the patch is:

Reviewed-by: Aurabindo Pillai 


[PATCH] drm/amdkfd: Make EXT_COHERENT parameter affect APU svm memory

2023-10-10 Thread Francis, David
[AMD Official Use Only - General]

By the intended semantics of the EXT_COHERENT parameter,
it should cause the driver to use MTYPE_UC instead of
MTYPE_NC on non-local gfx9.4.3 APU memory.

Signed-off-by: David Francis 
---
 drivers/gpu/drm/amd/amdkfd/kfd_svm.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_svm.c 
b/drivers/gpu/drm/amd/amdkfd/kfd_svm.c
index 7b81233bc9ae..d9ef937308ed 100644
--- a/drivers/gpu/drm/amd/amdkfd/kfd_svm.c
+++ b/drivers/gpu/drm/amd/amdkfd/kfd_svm.c
@@ -1286,7 +1286,7 @@ svm_range_get_pte_flags(struct kfd_node *node,
 if (num_possible_nodes() <= 1)
 mapping_flags |= mtype_local;
 else
-   mapping_flags |= AMDGPU_VM_MTYPE_NC;
+   mapping_flags |= ext_coherent ? 
AMDGPU_VM_MTYPE_UC : AMDGPU_VM_MTYPE_NC;
 /* system memory accessed by the dGPU */
 } else {
 mapping_flags |= AMDGPU_VM_MTYPE_UC;
--
2.34.1


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 2/3] drm/amdgpu/umsch: power on/off UMSCH by DLDO

2023-10-10 Thread Alex Deucher
On Tue, Oct 10, 2023 at 9:42 AM Lang Yu  wrote:
>
> On 10/10/ , Deucher, Alexander wrote:
> > [Public]
> >
> > > -Original Message-
> > > From: Yu, Lang 
> > > Sent: Saturday, October 7, 2023 4:54 AM
> > > To: amd-gfx@lists.freedesktop.org
> > > Cc: Deucher, Alexander ; Zhang, Yifan
> > > ; Gopalakrishnan, Veerabadhran (Veera)
> > > ; Yu, Lang 
> > > Subject: [PATCH 2/3] drm/amdgpu/umsch: power on/off UMSCH by DLDO
> > >
> > > VCN 4.0.5 uses DLDO.
> > >
> > > Signed-off-by: Lang Yu 
> > > ---
> > >  drivers/gpu/drm/amd/amdgpu/umsch_mm_v4_0.c | 26
> > > ++
> > >  1 file changed, 26 insertions(+)
> > >
> > > diff --git a/drivers/gpu/drm/amd/amdgpu/umsch_mm_v4_0.c
> > > b/drivers/gpu/drm/amd/amdgpu/umsch_mm_v4_0.c
> > > index a60178156c77..7e79954c833b 100644
> > > --- a/drivers/gpu/drm/amd/amdgpu/umsch_mm_v4_0.c
> > > +++ b/drivers/gpu/drm/amd/amdgpu/umsch_mm_v4_0.c
> > > @@ -34,6 +34,16 @@
> > >  #include "umsch_mm_4_0_api_def.h"
> > >  #include "umsch_mm_v4_0.h"
> > >
> > > +#define regUVD_IPX_DLDO_CONFIG 0x0064
> > > +#define regUVD_IPX_DLDO_CONFIG_BASE_IDX1
> > > +#define regUVD_IPX_DLDO_STATUS 0x0065
> > > +#define regUVD_IPX_DLDO_STATUS_BASE_IDX1
> > > +
> > > +#define UVD_IPX_DLDO_CONFIG__ONO0_PWR_CONFIG__SHIFT
> > > 0x0002
> > > +#define UVD_IPX_DLDO_CONFIG__ONO0_PWR_CONFIG_MASK
> > > 0x000cUL
> > > +#define UVD_IPX_DLDO_STATUS__ONO0_PWR_STATUS__SHIFT
> > > 0x0001
> > > +#define UVD_IPX_DLDO_STATUS__ONO0_PWR_STATUS_MASK
> > > 0x0002UL
> > > +
> > >  static int umsch_mm_v4_0_load_microcode(struct amdgpu_umsch_mm
> > > *umsch)  {
> > >   struct amdgpu_device *adev = umsch->ring.adev; @@ -50,6 +60,14
> > > @@ static int umsch_mm_v4_0_load_microcode(struct amdgpu_umsch_mm
> > > *umsch)
> > >
> > >   umsch->cmd_buf_curr_ptr = umsch->cmd_buf_ptr;
> > >
> > > + if (adev->ip_versions[VCN_HWIP][0] == IP_VERSION(4, 0, 5)) {
> > > + WREG32_SOC15(VCN, 0, regUVD_IPX_DLDO_CONFIG,
> > > + 1 <<
> > > UVD_IPX_DLDO_CONFIG__ONO0_PWR_CONFIG__SHIFT);
> > > + SOC15_WAIT_ON_RREG(VCN, 0, regUVD_IPX_DLDO_STATUS,
> > > + 0 <<
> > > UVD_IPX_DLDO_STATUS__ONO0_PWR_STATUS__SHIFT,
> > > +
> > >   UVD_IPX_DLDO_STATUS__ONO0_PWR_STATUS_MASK);
> > > + }
> > > +
> >
> > Is this the right place for this?  umsch_mm_hw_init() only calls this for 
> > FW_LOAD_DIRECT.  Maybe that check needs to be dropped?
>
> That check is dropped in [PATCH 1/3] drm/amdgpu/umsch: fix psp frontdoor 
> loading.

Ah, I checked that, but I missed it.  Thanks.

>
> PMFW removed DLDO programing in PPSMC_MSG_PowerUpUmsch function.
> So driver needs to program it explicitly.

Ok.  So is the SMC message still required in addition?

Alex

>
> Regards,
> Lang
>
> > Alex
> >
> > >   data = RREG32_SOC15(VCN, 0, regUMSCH_MES_RESET_CTRL);
> > >   data = REG_SET_FIELD(data, UMSCH_MES_RESET_CTRL,
> > > MES_CORE_SOFT_RESET, 0);
> > >   WREG32_SOC15_UMSCH(regUMSCH_MES_RESET_CTRL, data); @@ -
> > > 229,6 +247,14 @@ static int umsch_mm_v4_0_ring_stop(struct
> > > amdgpu_umsch_mm *umsch)
> > >   data = REG_SET_FIELD(data, VCN_UMSCH_RB_DB_CTRL, EN, 0);
> > >   WREG32_SOC15(VCN, 0, regVCN_UMSCH_RB_DB_CTRL, data);
> > >
> > > + if (adev->ip_versions[VCN_HWIP][0] == IP_VERSION(4, 0, 5)) {
> > > + WREG32_SOC15(VCN, 0, regUVD_IPX_DLDO_CONFIG,
> > > + 2 <<
> > > UVD_IPX_DLDO_CONFIG__ONO0_PWR_CONFIG__SHIFT);
> > > + SOC15_WAIT_ON_RREG(VCN, 0, regUVD_IPX_DLDO_STATUS,
> > > + 1 <<
> > > UVD_IPX_DLDO_STATUS__ONO0_PWR_STATUS__SHIFT,
> > > +
> > >   UVD_IPX_DLDO_STATUS__ONO0_PWR_STATUS_MASK);
> > > + }
> > > +
> > >   return 0;
> > >  }
> > >
> > > --
> > > 2.25.1
> >


[PATCH] drm/amd/swsmu: update smu v14_0_0 header files and metrics table

2023-10-10 Thread Li Ma
Update driver if, pmfw and ppsmc header files.
Add new gpu_metrics_v3_0 for metrics table updated in driver if
and reserve legacy metrics table to maintain backward compatibility.

Signed-off-by: Li Ma 
Reviewed-by: Yifan Zhang 
---
 .../gpu/drm/amd/include/kgd_pp_interface.h|  68 
 .../inc/pmfw_if/smu14_driver_if_v14_0_0.h |  66 ++--
 .../pm/swsmu/inc/pmfw_if/smu_v14_0_0_pmfw.h   |  24 +-
 .../pm/swsmu/inc/pmfw_if/smu_v14_0_0_ppsmc.h  |   6 +-
 .../drm/amd/pm/swsmu/smu14/smu_v14_0_0_ppt.c  | 345 ++
 5 files changed, 393 insertions(+), 116 deletions(-)

diff --git a/drivers/gpu/drm/amd/include/kgd_pp_interface.h 
b/drivers/gpu/drm/amd/include/kgd_pp_interface.h
index cdba7ba11e44..2d54c89b1bd2 100644
--- a/drivers/gpu/drm/amd/include/kgd_pp_interface.h
+++ b/drivers/gpu/drm/amd/include/kgd_pp_interface.h
@@ -893,4 +893,72 @@ struct gpu_metrics_v2_3 {
uint16_taverage_temperature_core[8]; // average 
CPU core temperature on APUs
uint16_taverage_temperature_l3[2];
 };
+
+struct gpu_metrics_v3_0 {
+   struct metrics_table_header common_header;
+
+   /* Temperature */
+   /* gfx temperature on APUs */
+   uint16_ttemperature_gfx;
+   /* soc temperature on APUs */
+   uint16_ttemperature_soc;
+   /* CPU core temperature on APUs */
+   uint16_ttemperature_core[16];
+   /* skin temperature on APUs */
+   uint16_ttemperature_skin;
+
+   /* Utilization */
+   /* time filtered GFX busy % [0-100] */
+   uint16_taverage_gfx_activity;
+   /* time filtered VCN busy % [0-100] */
+   uint16_taverage_vcn_activity;
+   /* time filtered IPU per-column busy % [0-100] */
+   uint16_taverage_ipu_activity[8];
+   /* time filtered per-core C0 residency % [0-100]*/
+   uint16_taverage_core_c0_activity[16];
+   /* time filtered DRAM read bandwidth [GB/sec] */
+   uint16_taverage_dram_reads;
+   /* time filtered DRAM write bandwidth [GB/sec] */
+   uint16_taverage_dram_writes;
+
+   /* Driver attached timestamp (in ns) */
+   uint64_tsystem_clock_counter;
+
+   /* Power/Energy */
+   /* average dGPU + APU power on A + A platform */
+   uint16_taverage_socket_power;
+   /* average IPU power [W] */
+   uint16_taverage_ipu_power;
+   /* average APU power [W] */
+   uint16_taverage_apu_power;
+   /* average dGPU power [W] */
+   uint16_taverage_dgpu_power;
+   /* sum of core power across all cores in the socket [W] */
+   uint16_taverage_core_power;
+   /* calculated core power [W] */
+   uint16_tcore_power[16];
+   /* maximum IRM defined STAPM power limit [W] */
+   uint16_tstapm_power_limit;
+   /* time filtered STAPM power limit [W] */
+   uint16_tcurrent_stapm_power_limit;
+
+   /* Average clocks */
+   uint16_taverage_gfxclk_frequency;
+   uint16_taverage_socclk_frequency;
+   uint16_taverage_vpeclk_frequency;
+   uint16_taverage_ipuclk_frequency;
+   uint16_taverage_fclk_frequency;
+   uint16_taverage_vclk_frequency;
+
+   /* Current clocks */
+   /* target core frequency */
+   uint16_tcurrent_coreclk[16];
+   /* CCLK frequency limit enforced on classic cores [MHz] */
+   uint16_tcurrent_core_maxfreq;
+   /* GFXCLK frequency limit enforced on GFX [MHz] */
+   uint16_tcurrent_gfx_maxfreq;
+
+   /* Metrics table alpha filter time constant [us] */
+   uint32_ttime_filter_alphavalue;
+};
 #endif
diff --git a/drivers/gpu/drm/amd/pm/swsmu/inc/pmfw_if/smu14_driver_if_v14_0_0.h 
b/drivers/gpu/drm/amd/pm/swsmu/inc/pmfw_if/smu14_driver_if_v14_0_0.h
index 61f007987b35..83a2ca1e5947 100644
--- a/drivers/gpu/drm/amd/pm/swsmu/inc/pmfw_if/smu14_driver_if_v14_0_0.h
+++ b/drivers/gpu/drm/amd/pm/swsmu/inc/pmfw_if/smu14_driver_if_v14_0_0.h
@@ -149,23 +149,37 @@ typedef struct {
   uint32_t MaxGfxClk;
 } DpmClocks_t;
 
-
-// Throttler Status Bitmask
-#define THROTTLER_STATUS_BIT_SPL  0
-#define THROTTLER_STATUS_BIT_FPPT 1
-#define THROTTLER_STATUS_BIT_SPPT 2
-#define THROTTLER_STATUS_BIT_SPPT_APU 3
-#define THROTTLER_STATUS_BIT_THM_CORE 4
-#define THROTTLER_STATUS_BIT_THM_GFX  5

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

2023-10-10 Thread Shyam Sundar S K



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().

Thanks,
Shyam

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


Re: [PATCH] drm/amd/display: add missing NULL check for DML2

2023-10-10 Thread Alex Deucher
On Tue, Oct 10, 2023 at 2:07 AM Bob Zhou  wrote:
>
> Recently, the driver introduce DML2 for future ASIC support.
> But, some ASIC's hubbub pointer is null before calling.
> It cause the below null pointer issue, so add null check to fix it.
>
> BUG: kernel NULL pointer dereference, address: 
> RIP: 0010:dc_create_resource_pool+0xc1/0x2c0 [amdgpu] Call Trace:
>  
>  ? show_regs.cold+0x1a/0x1f
>  ? __die_body+0x20/0x70
>  ? __die+0x2b/0x37
>  ? page_fault_oops+0x136/0x2c0
>  ? do_user_addr_fault+0x303/0x660
>  ? exc_page_fault+0x77/0x170
>  ? asm_exc_page_fault+0x27/0x30
>  ? dc_create_resource_pool+0xc1/0x2c0 [amdgpu]  ? 
> dc_create_resource_pool+0x243/0x2c0 [amdgpu]
>  dc_create+0x23f/0x6b0 [amdgpu]
>  ? dmi_matches+0xa3/0x200
>  amdgpu_dm_init+0x2bd/0x22a0 [amdgpu]
>
> Fixes: a2815ada8616 ("drm/amd/display: Introduce DML2")
>
> Signed-off-by: Bob Zhou 

Acked-by: Alex Deucher 

> ---
>  drivers/gpu/drm/amd/display/dc/core/dc_resource.c | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
>
> diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c 
> b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c
> index 25562b262555..d20e01226353 100644
> --- a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c
> +++ b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c
> @@ -321,7 +321,7 @@ struct resource_pool *dc_create_resource_pool(struct dc  
> *dc,
> res_pool->ref_clocks.xtalin_clock_inKhz;
> res_pool->ref_clocks.dchub_ref_clock_inKhz =
> res_pool->ref_clocks.xtalin_clock_inKhz;
> -   if ((res_pool->hubbub->funcs->get_dchub_ref_freq))
> +   if (res_pool->hubbub && 
> res_pool->hubbub->funcs->get_dchub_ref_freq)
> 
> res_pool->hubbub->funcs->get_dchub_ref_freq(res_pool->hubbub,
> 
> res_pool->ref_clocks.dccg_ref_clock_inKhz,
> 
> _pool->ref_clocks.dchub_ref_clock_inKhz);
> --
> 2.34.1
>


Re: [PATCH 2/2] drm/amd/pm: Add reset option for fan_ctrl on smu 13.0.7

2023-10-10 Thread Alex Deucher
On Tue, Oct 10, 2023 at 6:17 AM Ma Jun  wrote:
>
> Add reset option for fan_ctrl interfaces on the smu v13.0.7
> User can use command "echo r > interface_name" to reset the
> interface to boot value
>
> Signed-off-by: Ma Jun 

Series is:
Acked-by: Alex Deucher 

> ---
>  .../drm/amd/pm/swsmu/smu13/smu_v13_0_7_ppt.c  | 69 +--
>  1 file changed, 64 insertions(+), 5 deletions(-)
>
> 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 b8a7a1d853df..3c5526babb14 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
> @@ -1497,6 +1497,59 @@ static int smu_v13_0_7_print_clk_levels(struct 
> smu_context *smu,
> return size;
>  }
>
> +static int smu_v13_0_7_od_restore_table_single(struct smu_context *smu, long 
> input)
> +{
> +   struct smu_table_context *table_context = >smu_table;
> +   OverDriveTableExternal_t *boot_overdrive_table =
> +   (OverDriveTableExternal_t 
> *)table_context->boot_overdrive_table;
> +   OverDriveTableExternal_t *od_table =
> +   (OverDriveTableExternal_t *)table_context->overdrive_table;
> +   struct amdgpu_device *adev = smu->adev;
> +   int i;
> +
> +   switch (input) {
> +   case PP_OD_EDIT_FAN_CURVE:
> +   for (i = 0; i < NUM_OD_FAN_MAX_POINTS; i++) {
> +   od_table->OverDriveTable.FanLinearTempPoints[i] =
> +   
> boot_overdrive_table->OverDriveTable.FanLinearTempPoints[i];
> +   od_table->OverDriveTable.FanLinearPwmPoints[i] =
> +   
> boot_overdrive_table->OverDriveTable.FanLinearPwmPoints[i];
> +   }
> +   od_table->OverDriveTable.FanMode = FAN_MODE_AUTO;
> +   od_table->OverDriveTable.FeatureCtrlMask |= 
> BIT(PP_OD_FEATURE_FAN_CURVE_BIT);
> +   break;
> +   case PP_OD_EDIT_ACOUSTIC_LIMIT:
> +   od_table->OverDriveTable.AcousticLimitRpmThreshold =
> +   
> boot_overdrive_table->OverDriveTable.AcousticLimitRpmThreshold;
> +   od_table->OverDriveTable.FanMode = FAN_MODE_AUTO;
> +   od_table->OverDriveTable.FeatureCtrlMask |= 
> BIT(PP_OD_FEATURE_FAN_CURVE_BIT);
> +   break;
> +   case PP_OD_EDIT_ACOUSTIC_TARGET:
> +   od_table->OverDriveTable.AcousticTargetRpmThreshold =
> +   
> boot_overdrive_table->OverDriveTable.AcousticTargetRpmThreshold;
> +   od_table->OverDriveTable.FanMode = FAN_MODE_AUTO;
> +   od_table->OverDriveTable.FeatureCtrlMask |= 
> BIT(PP_OD_FEATURE_FAN_CURVE_BIT);
> +   break;
> +   case PP_OD_EDIT_FAN_TARGET_TEMPERATURE:
> +   od_table->OverDriveTable.FanTargetTemperature =
> +   
> boot_overdrive_table->OverDriveTable.FanTargetTemperature;
> +   od_table->OverDriveTable.FanMode = FAN_MODE_AUTO;
> +   od_table->OverDriveTable.FeatureCtrlMask |= 
> BIT(PP_OD_FEATURE_FAN_CURVE_BIT);
> +   break;
> +   case PP_OD_EDIT_FAN_MINIMUM_PWM:
> +   od_table->OverDriveTable.FanMinimumPwm =
> +   
> boot_overdrive_table->OverDriveTable.FanMinimumPwm;
> +   od_table->OverDriveTable.FanMode = FAN_MODE_AUTO;
> +   od_table->OverDriveTable.FeatureCtrlMask |= 
> BIT(PP_OD_FEATURE_FAN_CURVE_BIT);
> +   break;
> +   default:
> +   dev_info(adev->dev, "Invalid table index: %ld\n", input);
> +   return -EINVAL;
> +   }
> +
> +   return 0;
> +}
> +
>  static int smu_v13_0_7_od_edit_dpm_table(struct smu_context *smu,
>  enum PP_OD_DPM_TABLE_COMMAND type,
>  long input[],
> @@ -1783,11 +1836,17 @@ static int smu_v13_0_7_od_edit_dpm_table(struct 
> smu_context *smu,
> break;
>
> case PP_OD_RESTORE_DEFAULT_TABLE:
> -   feature_ctrlmask = od_table->OverDriveTable.FeatureCtrlMask;
> -   memcpy(od_table,
> -  table_context->boot_overdrive_table,
> -  sizeof(OverDriveTableExternal_t));
> -   od_table->OverDriveTable.FeatureCtrlMask = feature_ctrlmask;
> +   if (size == 1) {
> +   ret = smu_v13_0_7_od_restore_table_single(smu, 
> input[0]);
> +   if (ret)
> +   return ret;
> +   } else {
> +   feature_ctrlmask = 
> od_table->OverDriveTable.FeatureCtrlMask;
> +   memcpy(od_table,
> +   table_context->boot_overdrive_table,
> +   

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.



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

2023-10-10 Thread Shyam Sundar S K
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.

make amd_sfh_float_to_int() as non-static function so that this can
be called outside of the current file.

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_desc.c |  2 +-
 drivers/hid/amd-sfh-hid/sfh1_1/amd_sfh_init.c |  6 ++
 .../amd-sfh-hid/sfh1_1/amd_sfh_interface.c| 20 +++
 .../amd-sfh-hid/sfh1_1/amd_sfh_interface.h|  1 +
 drivers/platform/x86/amd/pmf/spc.c|  7 +++
 include/linux/amd-pmf-io.h|  2 ++
 7 files changed, 38 insertions(+), 1 deletion(-)

diff --git a/drivers/hid/amd-sfh-hid/amd_sfh_common.h 
b/drivers/hid/amd-sfh-hid/amd_sfh_common.h
index cd57037bf217..a1950bc6e6ce 100644
--- a/drivers/hid/amd-sfh-hid/amd_sfh_common.h
+++ b/drivers/hid/amd-sfh-hid/amd_sfh_common.h
@@ -39,6 +39,7 @@ struct amd_mp2_sensor_info {
 
 struct sfh_dev_status {
bool is_hpd_present;
+   bool is_als_present;
 };
 
 struct amd_mp2_dev {
diff --git a/drivers/hid/amd-sfh-hid/sfh1_1/amd_sfh_desc.c 
b/drivers/hid/amd-sfh-hid/sfh1_1/amd_sfh_desc.c
index 47a87b28e00e..dbc8c6943ca1 100644
--- a/drivers/hid/amd-sfh-hid/sfh1_1/amd_sfh_desc.c
+++ b/drivers/hid/amd-sfh-hid/sfh1_1/amd_sfh_desc.c
@@ -132,7 +132,7 @@ static void get_common_inputs(struct common_input_property 
*common, int report_i
common->event_type = HID_USAGE_SENSOR_EVENT_DATA_UPDATED_ENUM;
 }
 
-static int amd_sfh_float_to_int(u32 flt32_val)
+int amd_sfh_float_to_int(u32 flt32_val)
 {
int fraction, shift, mantissa, sign, exp, zeropre;
 
diff --git a/drivers/hid/amd-sfh-hid/sfh1_1/amd_sfh_init.c 
b/drivers/hid/amd-sfh-hid/sfh1_1/amd_sfh_init.c
index 3dc652d41d7d..f2890d329459 100644
--- a/drivers/hid/amd-sfh-hid/sfh1_1/amd_sfh_init.c
+++ b/drivers/hid/amd-sfh-hid/sfh1_1/amd_sfh_init.c
@@ -77,6 +77,9 @@ static int amd_sfh_hid_client_deinit(struct amd_mp2_dev 
*privdata)
case HPD_IDX:
privdata->dev_en.is_hpd_present = false;
break;
+   case ALS_IDX:
+   privdata->dev_en.is_als_present = false;
+   break;
}
 
if (cl_data->sensor_sts[i] == SENSOR_ENABLED) {
@@ -188,6 +191,9 @@ static int amd_sfh1_1_hid_client_init(struct amd_mp2_dev 
*privdata)
case HPD_IDX:
privdata->dev_en.is_hpd_present = true;
break;
+   case ALS_IDX:
+   privdata->dev_en.is_als_present = true;
+   break;
}
}
dev_dbg(dev, "sid 0x%x (%s) status 0x%x\n",
diff --git a/drivers/hid/amd-sfh-hid/sfh1_1/amd_sfh_interface.c 
b/drivers/hid/amd-sfh-hid/sfh1_1/amd_sfh_interface.c
index 7637da0dec6f..48a7a450e029 100644
--- a/drivers/hid/amd-sfh-hid/sfh1_1/amd_sfh_interface.c
+++ b/drivers/hid/amd-sfh-hid/sfh1_1/amd_sfh_interface.c
@@ -94,12 +94,32 @@ static int amd_sfh_hpd_info(u8 *user_present)
return -ENODEV;
 }
 
+static int amd_sfh_als_info(u32 *ambient_light)
+{
+   if (emp2 && emp2->dev_en.is_als_present) {
+   struct sfh_als_data als_data;
+   void __iomem *sensoraddr;
+
+   sensoraddr = emp2->vsbase +
+   (ALS_IDX * SENSOR_DATA_MEM_SIZE_DEFAULT) +
+   OFFSET_SENSOR_DATA_DEFAULT;
+   memcpy_fromio(_data, sensoraddr, sizeof(struct 
sfh_als_data));
+   *ambient_light = amd_sfh_float_to_int(als_data.lux);
+
+   return 0;
+   }
+
+   return -ENODEV;
+}
+
 int amd_get_sfh_info(struct amd_sfh_info *sfh_info, enum sfh_message_type op)
 {
if (sfh_info) {
switch (op) {
case MT_HPD:
return amd_sfh_hpd_info(_info->user_present);
+   case MT_ALS:
+   return amd_sfh_als_info(_info->ambient_light);
}
}
return -EINVAL;
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..7ecddad430e4 100644
--- a/drivers/hid/amd-sfh-hid/sfh1_1/amd_sfh_interface.h
+++ b/drivers/hid/amd-sfh-hid/sfh1_1/amd_sfh_interface.h
@@ -149,6 +149,7 @@ struct hpd_status {
};
 };
 
+int amd_sfh_float_to_int(u32 flt32_val);
 void sfh_interface_init(struct amd_mp2_dev *mp2);
 void amd_sfh1_1_set_desc_ops(struct amd_mp2_ops *mp2_ops);
 #endif
diff --git a/drivers/platform/x86/amd/pmf/spc.c 
b/drivers/platform/x86/amd/pmf/spc.c
index e33bbf8a3de4..b6cf6d7e6ef5 100644
--- 

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

2023-10-10 Thread Shyam Sundar S K
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 = _sfh_ops;
+   emp2 = mp2;
+}
+
+static int amd_sfh_hpd_info(u8 *user_present)
+{
+   if (emp2 && emp2->dev_en.is_hpd_present) {
+   struct hpd_status hpdstatus;
+
+   hpdstatus.val = readl(emp2->mmio + AMD_C2P_MSG(4));
+   *user_present = hpdstatus.shpd.presence;
+   return 0;
+   }
+   return -ENODEV;
+}
+
+int amd_get_sfh_info(struct amd_sfh_info *sfh_info, enum sfh_message_type op)
+{
+   if (sfh_info) {
+   switch (op) {
+   case MT_HPD:
+   return amd_sfh_hpd_info(_info->user_present);
+   }
+   }
+   return -EINVAL;
 }
+EXPORT_SYMBOL_GPL(amd_get_sfh_info);
diff --git a/drivers/platform/x86/amd/pmf/Kconfig 
b/drivers/platform/x86/amd/pmf/Kconfig
index 7f430de7af44..d368d35a49ac 100644
--- a/drivers/platform/x86/amd/pmf/Kconfig
+++ b/drivers/platform/x86/amd/pmf/Kconfig
@@ -11,6 +11,7 @@ config AMD_PMF
select ACPI_PLATFORM_PROFILE
depends on TEE && AMDTEE
depends on DRM_AMDGPU
+   depends on AMD_SFH_HID
help
  This driver provides support for the AMD Platform Management 
Framework.
  The goal is to enhance end user experience by making AMD PCs smarter,
diff --git a/drivers/platform/x86/amd/pmf/spc.c 
b/drivers/platform/x86/amd/pmf/spc.c
index 58b51e11e424..e33bbf8a3de4 100644
--- 

[PATCH v3 14/16] HID: amd_sfh: rename float_to_int() to amd_sfh_float_to_int()

2023-10-10 Thread Shyam Sundar S K
From: Basavaraj Natikar 

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

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

Co-developed-by: Shyam Sundar S K 
Signed-off-by: Shyam Sundar S K 
Signed-off-by: Basavaraj Natikar 
---
 drivers/hid/amd-sfh-hid/sfh1_1/amd_sfh_desc.c | 22 +--
 1 file changed, 11 insertions(+), 11 deletions(-)

diff --git a/drivers/hid/amd-sfh-hid/sfh1_1/amd_sfh_desc.c 
b/drivers/hid/amd-sfh-hid/sfh1_1/amd_sfh_desc.c
index 06bdcf072d10..47a87b28e00e 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)
+static int amd_sfh_float_to_int(u32 flt32_val)
 {
int fraction, shift, mantissa, sign, exp, zeropre;
 
@@ -200,9 +200,9 @@ static u8 get_input_rep(u8 current_index, int sensor_idx, 
int report_id,
 OFFSET_SENSOR_DATA_DEFAULT;
memcpy_fromio(_data, sensoraddr, sizeof(struct 
sfh_accel_data));
get_common_inputs(_input.common_property, report_id);
-   acc_input.in_accel_x_value = 
float_to_int(accel_data.acceldata.x) / 100;
-   acc_input.in_accel_y_value = 
float_to_int(accel_data.acceldata.y) / 100;
-   acc_input.in_accel_z_value = 
float_to_int(accel_data.acceldata.z) / 100;
+   acc_input.in_accel_x_value = 
amd_sfh_float_to_int(accel_data.acceldata.x) / 100;
+   acc_input.in_accel_y_value = 
amd_sfh_float_to_int(accel_data.acceldata.y) / 100;
+   acc_input.in_accel_z_value = 
amd_sfh_float_to_int(accel_data.acceldata.z) / 100;
memcpy(input_report, _input, sizeof(acc_input));
report_size = sizeof(acc_input);
break;
@@ -211,9 +211,9 @@ static u8 get_input_rep(u8 current_index, int sensor_idx, 
int report_id,
 OFFSET_SENSOR_DATA_DEFAULT;
memcpy_fromio(_data, sensoraddr, sizeof(struct 
sfh_gyro_data));
get_common_inputs(_input.common_property, report_id);
-   gyro_input.in_angel_x_value = 
float_to_int(gyro_data.gyrodata.x) / 1000;
-   gyro_input.in_angel_y_value = 
float_to_int(gyro_data.gyrodata.y) / 1000;
-   gyro_input.in_angel_z_value = 
float_to_int(gyro_data.gyrodata.z) / 1000;
+   gyro_input.in_angel_x_value = 
amd_sfh_float_to_int(gyro_data.gyrodata.x) / 1000;
+   gyro_input.in_angel_y_value = 
amd_sfh_float_to_int(gyro_data.gyrodata.y) / 1000;
+   gyro_input.in_angel_z_value = 
amd_sfh_float_to_int(gyro_data.gyrodata.z) / 1000;
memcpy(input_report, _input, sizeof(gyro_input));
report_size = sizeof(gyro_input);
break;
@@ -222,9 +222,9 @@ static u8 get_input_rep(u8 current_index, int sensor_idx, 
int report_id,
 OFFSET_SENSOR_DATA_DEFAULT;
memcpy_fromio(_data, sensoraddr, sizeof(struct 
sfh_mag_data));
get_common_inputs(_input.common_property, report_id);
-   magno_input.in_magno_x = float_to_int(mag_data.magdata.x) / 100;
-   magno_input.in_magno_y = float_to_int(mag_data.magdata.y) / 100;
-   magno_input.in_magno_z = float_to_int(mag_data.magdata.z) / 100;
+   magno_input.in_magno_x = 
amd_sfh_float_to_int(mag_data.magdata.x) / 100;
+   magno_input.in_magno_y = 
amd_sfh_float_to_int(mag_data.magdata.y) / 100;
+   magno_input.in_magno_z = 
amd_sfh_float_to_int(mag_data.magdata.z) / 100;
magno_input.in_magno_accuracy = mag_data.accuracy / 100;
memcpy(input_report, _input, sizeof(magno_input));
report_size = sizeof(magno_input);
@@ -234,7 +234,7 @@ static u8 get_input_rep(u8 current_index, int sensor_idx, 
int report_id,
 OFFSET_SENSOR_DATA_DEFAULT;
memcpy_fromio(_data, sensoraddr, sizeof(struct 
sfh_als_data));
get_common_inputs(_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, _input, sizeof(als_input));
break;
-- 
2.25.1



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

2023-10-10 Thread Shyam Sundar S K
For the Smart PC Solution to fully work, it has to enact to the actions
coming from TA. Add the initial code path for set interface to AMDGPU.

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

Co-developed-by: Mario Limonciello 
Signed-off-by: Mario Limonciello 
Signed-off-by: Shyam Sundar S K 
---
 drivers/gpu/drm/amd/amdgpu/amdgpu_pmf.c | 18 ++
 drivers/platform/x86/amd/pmf/pmf.h  |  2 ++
 drivers/platform/x86/amd/pmf/tee-if.c   | 21 +++--
 3 files changed, 39 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_pmf.c 
b/drivers/gpu/drm/amd/amdgpu/amdgpu_pmf.c
index 45a079c028d3..803e6bb66914 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_pmf.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_pmf.c
@@ -61,6 +61,23 @@ int amd_pmf_get_gfx_data(struct amd_gpu_pmf_data *pmf)
 }
 EXPORT_SYMBOL_GPL(amd_pmf_get_gfx_data);
 
+static int amd_pmf_gpu_set_cur_state(struct thermal_cooling_device 
*cooling_dev,
+unsigned long state)
+{
+   struct backlight_device *bd;
+
+   if (!acpi_video_backlight_use_native())
+   return -ENODEV;
+
+   bd = backlight_device_get_by_type(BACKLIGHT_RAW);
+   if (!bd)
+   return -ENODEV;
+
+   backlight_device_set_brightness(bd, state);
+
+   return 0;
+}
+
 static int amd_pmf_gpu_get_cur_state(struct thermal_cooling_device 
*cooling_dev,
 unsigned long *state)
 {
@@ -101,6 +118,7 @@ static int amd_pmf_gpu_get_max_state(struct 
thermal_cooling_device *cooling_dev,
 static const struct thermal_cooling_device_ops bd_cooling_ops = {
.get_max_state = amd_pmf_gpu_get_max_state,
.get_cur_state = amd_pmf_gpu_get_cur_state,
+   .set_cur_state = amd_pmf_gpu_set_cur_state,
 };
 
 int amd_pmf_gpu_init(struct amd_gpu_pmf_data *pmf)
diff --git a/drivers/platform/x86/amd/pmf/pmf.h 
b/drivers/platform/x86/amd/pmf/pmf.h
index 0f1c0e0bc86a..d61cebc44d2b 100644
--- a/drivers/platform/x86/amd/pmf/pmf.h
+++ b/drivers/platform/x86/amd/pmf/pmf.h
@@ -75,6 +75,7 @@
 #define PMF_POLICY_STT_SKINTEMP_APU7
 #define PMF_POLICY_STT_SKINTEMP_HS28
 #define PMF_POLICY_SYSTEM_STATE9
+#define PMF_POLICY_DISPLAY_BRIGHTNESS  12
 #define PMF_POLICY_P3T 38
 
 /* TA macros */
@@ -483,6 +484,7 @@ enum ta_pmf_error_type {
 };
 
 struct pmf_action_table {
+   unsigned long display_brightness;
enum system_state system_state;
u32 spl;/* in mW */
u32 sppt;   /* in mW */
diff --git a/drivers/platform/x86/amd/pmf/tee-if.c 
b/drivers/platform/x86/amd/pmf/tee-if.c
index e9a257a91325..4f5de7f816d3 100644
--- a/drivers/platform/x86/amd/pmf/tee-if.c
+++ b/drivers/platform/x86/amd/pmf/tee-if.c
@@ -77,8 +77,10 @@ static int amd_pmf_update_uevents(struct amd_pmf_dev *dev, 
u16 event)
return 0;
 }
 
-static void amd_pmf_apply_policies(struct amd_pmf_dev *dev, struct 
ta_pmf_enact_result *out)
+static int amd_pmf_apply_policies(struct amd_pmf_dev *dev, struct 
ta_pmf_enact_result *out)
 {
+   struct thermal_cooling_device *cdev = dev->gfx_data.cooling_dev;
+   unsigned long state;
u32 val, event = 0;
int idx;
 
@@ -154,8 +156,21 @@ static void amd_pmf_apply_policies(struct amd_pmf_dev 
*dev, struct ta_pmf_enact_
dev_dbg(dev->dev, "update SYSTEM_STATE : %s\n",
amd_pmf_uevent_as_str(event));
break;
+
+   case PMF_POLICY_DISPLAY_BRIGHTNESS:
+   if (!dev->gfx_data.gpu_dev_en)
+   return -ENODEV;
+
+   cdev->ops->get_cur_state(cdev, );
+   if (state != val) {
+   cdev->ops->set_cur_state(cdev, val);
+   dev_dbg(dev->dev, "update DISPLAY_BRIGHTNESS : 
%u\n", val);
+   }
+   break;
}
}
+
+   return 0;
 }
 
 static int amd_pmf_invoke_cmd_enact(struct amd_pmf_dev *dev)
@@ -192,7 +207,9 @@ static int amd_pmf_invoke_cmd_enact(struct amd_pmf_dev *dev)
amd_pmf_dump_ta_inputs(dev, in);
dev_dbg(dev->dev, "action count:%u result:%x\n", 
out->actions_count,
ta_sm->pmf_result);
-   amd_pmf_apply_policies(dev, out);
+   ret = amd_pmf_apply_policies(dev, out);
+   if (ret)
+   return ret;
}
 
return 0;
-- 
2.25.1



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

2023-10-10 Thread Shyam Sundar S K
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 3d98d9bea96b..9b84121344f4 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 80252309575b..994daf945795 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,
@@ -268,6 +274,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, 
_fops);
+   if (!file)
+   return -EINVAL;
+
+   return 0;
+}
+
+static void amd_pmf_remove_pb(struct amd_pmf_dev *dev)
+{
+   debugfs_remove_recursive(dev->esbin);
+}
+#else
+static int amd_pmf_open_pb(struct amd_pmf_dev *dev, struct dentry 
*debugfs_root)
+{
+   return 0;
+}
+
+static void amd_pmf_remove_pb(struct amd_pmf_dev *dev) {}
+#endif
+
 static int amd_pmf_get_bios_buffer(struct amd_pmf_dev *dev)
 {
dev->policy_buf = kzalloc(dev->policy_sz, GFP_KERNEL);
@@ -280,6 +341,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);
 }
 
@@ -381,6 +445,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(>pb_work);
-- 
2.25.1



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

2023-10-10 Thread Shyam Sundar S K
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 | 136 
 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, 218 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 ..45a079c028d3
--- /dev/null
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_pmf.c
@@ -0,0 +1,136 @@
+/*
+ * 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 = _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(_config->mutex);
+   drm_connector_list_iter_begin(drm_dev, );
+   drm_for_each_connector_iter(connector, ) {
+   if (connector->status == connector_status_connected) {
+   pmf->con_status[i] = connector->status;
+   pmf->connector_type[i] = connector->connector_type;
+   pmf->display_count++;
+   }
+   i++;
+
+   if (i > MAX_SUPPORTED)
+   break;
+   }
+   drm_connector_list_iter_end();
+   mutex_unlock(_config->mutex);
+
+   return 0;
+}
+EXPORT_SYMBOL_GPL(amd_pmf_get_gfx_data);
+
+static int amd_pmf_gpu_get_cur_state(struct thermal_cooling_device 
*cooling_dev,
+unsigned long *state)
+{
+   struct backlight_device *bd;
+
+   if (!acpi_video_backlight_use_native())
+   return -ENODEV;
+
+   bd = backlight_device_get_by_type(BACKLIGHT_RAW);
+   if (!bd)
+   return -ENODEV;
+
+   *state = backlight_get_brightness(bd);
+
+   return 0;
+}
+
+static int amd_pmf_gpu_get_max_state(struct thermal_cooling_device 
*cooling_dev,
+

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

2023-10-10 Thread Shyam Sundar S K
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);
+}
+
 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);
 
-- 
2.25.1



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

2023-10-10 Thread Shyam Sundar S K
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/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 | 36 ++-
 4 files changed, 70 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 ..6985bb5b9452
--- /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}=="0", 
RUN+="/usr/bin/systemctl suspend"
+DRIVERS=="amd-pmf", ACTION=="change", ENV{EVENT_ID}=="1", 
RUN+="/usr/bin/systemctl hibernate"
+DRIVERS=="amd-pmf", ACTION=="change", ENV{EVENT_ID}=="2", 
RUN+="/bin/loginctl lock-sessions"
+
+EVENT_ID values:
+0= Put the system to S0i3/S2Idle
+1= Put the system to hibernate
+2= Lock the screen
+
diff --git a/drivers/platform/x86/amd/pmf/pmf.h 
b/drivers/platform/x86/amd/pmf/pmf.h
index 20f3e16b0a32..67f3d5a7 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_APU7
 #define PMF_POLICY_STT_SKINTEMP_HS28
+#define PMF_POLICY_SYSTEM_STATE9
 #define PMF_POLICY_P3T 38
 
 /* TA macros */
@@ -440,6 +441,13 @@ struct apmf_dyn_slider_output {
 } __packed;
 
 /* Smart PC - TA internals */
+enum system_state {
+   SYSTEM_STATE__S0i3,
+   SYSTEM_STATE__S4,
+   SYSTEM_STATE__SCREEN_LOCK,
+   SYSTEM_STATE__MAX
+};
+
 enum ta_slider {
TA_BEST_BATTERY,/* Best Battery */
TA_BETTER_BATTERY,  /* Better Battery */
@@ -471,6 +479,7 @@ enum ta_pmf_error_type {
 };
 
 struct pmf_action_table {
+   enum system_state system_state;
u32 spl;/* in mW */
u32 sppt;   /* in mW */
u32 sppt_apuonly;   /* in mW */
diff --git a/drivers/platform/x86/amd/pmf/tee-if.c 
b/drivers/platform/x86/amd/pmf/tee-if.c
index 92879ae4f8f0..c08ef13a1494 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;
+
+   

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

2023-10-10 Thread Shyam Sundar S K
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 67f3d5a7..3d98d9bea96b 100644
--- a/drivers/platform/x86/amd/pmf/pmf.h
+++ b/drivers/platform/x86/amd/pmf/pmf.h
@@ -596,6 +596,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 *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);
@@ -626,4 +627,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 91a7f1da911c..5cb70f183825 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");
+   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..781fde00e0e7 100644
--- a/drivers/platform/x86/amd/pmf/sps.c
+++ b/drivers/platform/x86/amd/pmf/sps.c
@@ -27,7 +27,7 @@ static const char *slider_as_str(unsigned int state)
}
 }
 
-static const char *source_as_str(unsigned int state)
+const char *amd_pmf_source_as_str(unsigned int state)
 {
switch (state) {
case POWER_SOURCE_AC:
diff --git a/drivers/platform/x86/amd/pmf/tee-if.c 
b/drivers/platform/x86/amd/pmf/tee-if.c
index c08ef13a1494..80252309575b 100644
--- a/drivers/platform/x86/amd/pmf/tee-if.c
+++ b/drivers/platform/x86/amd/pmf/tee-if.c
@@ -182,6 +182,7 @@ static int amd_pmf_invoke_cmd_enact(struct amd_pmf_dev *dev)
}
 
if (ta_sm->pmf_result == TA_PMF_TYPE_SUCCESS && out->actions_count) {
+   amd_pmf_dump_ta_inputs(dev, in);
dev_dbg(dev->dev, "action count:%u result:%x\n", 
out->actions_count,
ta_sm->pmf_result);
amd_pmf_apply_policies(dev, out);
-- 
2.25.1



[PATCH v3 07/16] platform/x86/amd/pmf: Add support update p3t limit

2023-10-10 Thread Shyam Sundar S K
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 88ee3c705913..20f3e16b0a32 100644
--- a/drivers/platform/x86/amd/pmf/pmf.h
+++ b/drivers/platform/x86/amd/pmf/pmf.h
@@ -49,6 +49,7 @@
 #define GET_STT_MIN_LIMIT  0x1F
 #define GET_STT_LIMIT_APU  0x20
 #define GET_STT_LIMIT_HS2  0x21
+#define SET_P3T0x23 /* P3T: Peak Package Power 
Limit */
 
 /* OS slider update notification */
 #define DC_BEST_PERF   0
@@ -72,6 +73,7 @@
 #define PMF_POLICY_STT_MIN 6
 #define PMF_POLICY_STT_SKINTEMP_APU7
 #define PMF_POLICY_STT_SKINTEMP_HS28
+#define PMF_POLICY_P3T 38
 
 /* TA macros */
 #define PMF_TA_IF_VERSION_MAJOR1
@@ -476,6 +478,7 @@ struct pmf_action_table {
u32 stt_minlimit;   /* in mW */
u32 stt_skintemp_apu;   /* in C */
u32 stt_skintemp_hs2;   /* in C */
+   u32 p3t_limit;  /* in mW */
 };
 
 /* Input conditions */
diff --git a/drivers/platform/x86/amd/pmf/tee-if.c 
b/drivers/platform/x86/amd/pmf/tee-if.c
index 277103e4346d..92879ae4f8f0 100644
--- a/drivers/platform/x86/amd/pmf/tee-if.c
+++ b/drivers/platform/x86/amd/pmf/tee-if.c
@@ -105,6 +105,14 @@ static void amd_pmf_apply_policies(struct amd_pmf_dev 
*dev, struct ta_pmf_enact_
dev->prev_data->stt_skintemp_hs2 = val;
}
break;
+
+   case PMF_POLICY_P3T:
+   if (dev->prev_data->p3t_limit != val) {
+   amd_pmf_send_cmd(dev, SET_P3T, false, val, 
NULL);
+   dev_dbg(dev->dev, "update P3T : %u\n", val);
+   dev->prev_data->p3t_limit = val;
+   }
+   break;
}
}
 }
-- 
2.25.1



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

2023-10-10 Thread Shyam Sundar S K
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(>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);
+   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;
+
+   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, );
+   if (ret) {
+   power_supply_put(psy);
+   return ret;
+   }
+   }
+
+   return value.intval;
+}
+
+static int amd_pmf_get_battery_info(struct amd_pmf_dev *dev, struct 
ta_pmf_enact_table *in)
+{
+   int val;
+
+   val = amd_pmf_get_battery_prop(POWER_SUPPLY_PROP_PRESENT);
+   if (val != 1)
+   return -EINVAL;
+
+   in->ev_info.bat_percentage = 
amd_pmf_get_battery_prop(POWER_SUPPLY_PROP_CAPACITY);
+   /* all values in mWh metrics */
+   in->ev_info.bat_design = 

[PATCH v3 05/16] platform/x86/amd/pmf: change amd_pmf_init_features() call sequence

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

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

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

Reviewed-by: Mario Limonciello 
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 96a41e7d4e7d..64af6ddc23ae 100644
--- a/drivers/platform/x86/amd/pmf/core.c
+++ b/drivers/platform/x86/amd/pmf/core.c
@@ -447,9 +447,9 @@ static int amd_pmf_probe(struct platform_device *pdev)
 
apmf_acpi_init(dev);
platform_set_drvdata(pdev, dev);
+   amd_pmf_dbgfs_register(dev);
amd_pmf_init_features(dev);
apmf_install_handler(dev);
-   amd_pmf_dbgfs_register(dev);
 
dev_info(dev->dev, "registered PMF device successfully\n");
 
-- 
2.25.1



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

2023-10-10 Thread Shyam Sundar S K
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  |   2 +-
 drivers/platform/x86/amd/pmf/acpi.c   |  37 +++
 drivers/platform/x86/amd/pmf/core.c   |  13 +++
 drivers/platform/x86/amd/pmf/pmf.h| 136 
 drivers/platform/x86/amd/pmf/tee-if.c | 146 +-
 5 files changed, 331 insertions(+), 3 deletions(-)

diff --git a/drivers/platform/x86/amd/pmf/Kconfig 
b/drivers/platform/x86/amd/pmf/Kconfig
index 32a029e8db80..f246252bddd8 100644
--- a/drivers/platform/x86/amd/pmf/Kconfig
+++ b/drivers/platform/x86/amd/pmf/Kconfig
@@ -9,7 +9,7 @@ config AMD_PMF
depends on POWER_SUPPLY
depends on AMD_NB
select ACPI_PLATFORM_PROFILE
-   depends on TEE
+   depends on TEE && AMDTEE
help
  This driver provides support for the AMD Platform Management 
Framework.
  The goal is to enhance end user experience by making AMD PCs smarter,
diff --git a/drivers/platform/x86/amd/pmf/acpi.c 
b/drivers/platform/x86/amd/pmf/acpi.c
index 3fc5e4547d9f..d0512af2cd42 100644
--- a/drivers/platform/x86/amd/pmf/acpi.c
+++ b/drivers/platform/x86/amd/pmf/acpi.c
@@ -286,6 +286,43 @@ int apmf_install_handler(struct amd_pmf_dev *pmf_dev)
return 0;
 }
 
+static acpi_status apmf_walk_resources(struct acpi_resource *res, void *data)
+{
+   struct amd_pmf_dev *dev = data;
+
+   switch (res->type) {
+   case ACPI_RESOURCE_TYPE_ADDRESS64:
+   dev->policy_addr = res->data.address64.address.minimum;
+   dev->policy_sz = res->data.address64.address.address_length;
+   break;
+   case ACPI_RESOURCE_TYPE_FIXED_MEMORY32:
+   dev->policy_addr = res->data.fixed_memory32.address;
+   dev->policy_sz = res->data.fixed_memory32.address_length;
+   break;
+   }
+
+   if (!dev->policy_addr || dev->policy_sz > POLICY_BUF_MAX_SZ || 
dev->policy_sz == 0) {
+   pr_err("Incorrect Policy params, possibly a SBIOS bug\n");
+   return AE_ERROR;
+   }
+
+   return AE_OK;
+}
+
+int apmf_check_smart_pc(struct amd_pmf_dev *pmf_dev)
+{
+   acpi_handle ahandle = ACPI_HANDLE(pmf_dev->dev);
+   acpi_status status;
+
+   status = acpi_walk_resources(ahandle, METHOD_NAME__CRS, 
apmf_walk_resources, pmf_dev);
+   if (ACPI_FAILURE(status)) {
+   

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

2023-10-10 Thread Shyam Sundar S K
In the current code, the metrics table information was required only
for auto-mode or CnQF at a given time. Hence keeping the return type
of amd_pmf_set_dram_addr() as static made sense.

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

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

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

Reviewed-by: Mario Limonciello 
Signed-off-by: Shyam Sundar S K 
---
 drivers/platform/x86/amd/pmf/core.c | 42 ++---
 drivers/platform/x86/amd/pmf/pmf.h  |  1 +
 2 files changed, 34 insertions(+), 9 deletions(-)

diff --git a/drivers/platform/x86/amd/pmf/core.c 
b/drivers/platform/x86/amd/pmf/core.c
index d57ed038f0c9..ffb78e9709d9 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(>work_buffer, amd_pmf_get_metrics);
 
-   amd_pmf_set_dram_addr(dev);
+   ret = amd_pmf_set_dram_addr(dev);
+   if (ret)
+   return ret;
 
/*
 * Start collecting the metrics data after a small delay
@@ -284,17 +290,35 @@ int amd_pmf_init_metrics_table(struct amd_pmf_dev *dev)
return 0;
 }
 
+static int amd_pmf_suspend_handler(struct device *dev)
+{
+   struct amd_pmf_dev *pdev = dev_get_drvdata(dev);
+
+   /*
+* Free the buffer allocated for storing the metrics table
+* information, as will have to allocate it freshly after
+* resume.
+*/
+   kfree(pdev->buf);
+
+   return 0;
+}
+
 static int amd_pmf_resume_handler(struct device *dev)
 {
struct amd_pmf_dev *pdev = dev_get_drvdata(dev);
+   int ret;
 
-   if (pdev->buf)
-   amd_pmf_set_dram_addr(pdev);
+   if (pdev->buf) {
+   ret = amd_pmf_set_dram_addr(pdev);
+   if (ret)
+   return ret;
+   }
 
return 0;
 }
 
-static DEFINE_SIMPLE_DEV_PM_OPS(amd_pmf_pm, NULL, amd_pmf_resume_handler);
+static DEFINE_SIMPLE_DEV_PM_OPS(amd_pmf_pm, amd_pmf_suspend_handler, 
amd_pmf_resume_handler);
 
 static void amd_pmf_init_features(struct amd_pmf_dev *dev)
 {
diff --git a/drivers/platform/x86/amd/pmf/pmf.h 
b/drivers/platform/x86/amd/pmf/pmf.h
index 4da5c4eb053c..a91c22d9b532 100644
--- a/drivers/platform/x86/amd/pmf/pmf.h
+++ b/drivers/platform/x86/amd/pmf/pmf.h
@@ -421,6 +421,7 @@ int amd_pmf_init_metrics_table(struct amd_pmf_dev *dev);
 int amd_pmf_get_power_source(void);
 int apmf_install_handler(struct amd_pmf_dev *pmf_dev);
 int apmf_os_power_slider_update(struct amd_pmf_dev *dev, u8 flag);
+int amd_pmf_set_dram_addr(struct amd_pmf_dev *dev);
 
 /* SPS Layer */
 int amd_pmf_get_pprof_modes(struct amd_pmf_dev *pmf);
-- 
2.25.1



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

2023-10-10 Thread Shyam Sundar S K
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 bd40458937ba..4da5c4eb053c 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_MAJOR1
+
 /* 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 6ec8c3726624..4036f435f1e2 100644
--- a/drivers/platform/x86/amd/pmf/tee-if.c
+++ b/drivers/platform/x86/amd/pmf/tee-if.c
@@ -13,9 +13,96 @@
 #include "pmf.h"
 
 #define MAX_TEE_PARAM  4
+
+/* Policy binary actions sampling frequency (in ms) */
+static int pb_actions_ms = MSEC_PER_SEC;
+#ifdef CONFIG_AMD_PMF_DEBUG
+module_param(pb_actions_ms, int, 0644);
+MODULE_PARM_DESC(pb_actions_ms, "Policy binary actions sampling frequency 
(default = 1000ms)");
+#endif
+
 static const uuid_t amd_pmf_ta_uuid = UUID_INIT(0x6fd93b77, 0x3fb8, 0x524d,
0xb1, 0x2d, 0xc5, 0x29, 0xb1, 
0x3d, 0x85, 0x43);
 
+static void amd_pmf_prepare_args(struct amd_pmf_dev *dev, int cmd,
+struct tee_ioctl_invoke_arg *arg,
+struct tee_param *param)
+{
+   memset(arg, 0, sizeof(*arg));
+   memset(param, 0, MAX_TEE_PARAM * sizeof(*param));
+
+   arg->func = cmd;
+   arg->session = dev->session_id;
+   arg->num_params = MAX_TEE_PARAM;
+
+   /* Fill invoke cmd params */
+   param[0].u.memref.size = sizeof(struct ta_pmf_shared_memory);
+   param[0].attr = TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INOUT;
+   param[0].u.memref.shm = dev->fw_shm_pool;
+   param[0].u.memref.shm_offs = 0;
+}
+
+static int amd_pmf_invoke_cmd_enact(struct amd_pmf_dev *dev)
+{
+   struct ta_pmf_shared_memory *ta_sm = NULL;
+   struct tee_param param[MAX_TEE_PARAM];
+   struct tee_ioctl_invoke_arg arg;
+   int ret = 0;
+
+   if (!dev->tee_ctx)
+   return -ENODEV;
+
+   ta_sm = dev->shbuf;
+   memset(ta_sm, 0, sizeof(*ta_sm));
+   ta_sm->command_id = TA_PMF_COMMAND_POLICY_BUILDER_ENACT_POLICIES;
+   ta_sm->if_version = PMF_TA_IF_VERSION_MAJOR;
+
+   amd_pmf_prepare_args(dev, TA_PMF_COMMAND_POLICY_BUILDER_ENACT_POLICIES, 
, param);
+
+   ret = tee_client_invoke_func(dev->tee_ctx, , param);
+   if (ret < 0 || arg.ret != 0) {
+   dev_err(dev->dev, "TEE enact cmd failed. err: %x, ret:%d\n", 
arg.ret, ret);
+   return ret;
+   }
+
+   return 0;
+}
+
+static int amd_pmf_invoke_cmd_init(struct amd_pmf_dev *dev)
+{
+   struct ta_pmf_shared_memory *ta_sm = NULL;
+   struct tee_param param[MAX_TEE_PARAM];
+   struct tee_ioctl_invoke_arg arg;
+   int ret = 0;
+
+   if (!dev->tee_ctx) {
+   dev_err(dev->dev, "Failed to get TEE context\n");
+   return -ENODEV;
+   }
+
+   ta_sm = dev->shbuf;
+   ta_sm->command_id = TA_PMF_COMMAND_POLICY_BUILDER_INITIALIZE;
+   ta_sm->if_version = PMF_TA_IF_VERSION_MAJOR;
+
+   amd_pmf_prepare_args(dev, TA_PMF_COMMAND_POLICY_BUILDER_INITIALIZE, 
, param);
+
+   ret = tee_client_invoke_func(dev->tee_ctx, , param);
+   

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

2023-10-10 Thread Shyam Sundar S K
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/Kconfig  |   1 +
 drivers/platform/x86/amd/pmf/Makefile |   3 +-
 drivers/platform/x86/amd/pmf/core.c   |  10 ++-
 drivers/platform/x86/amd/pmf/pmf.h|  16 
 drivers/platform/x86/amd/pmf/tee-if.c | 105 ++
 5 files changed, 130 insertions(+), 5 deletions(-)
 create mode 100644 drivers/platform/x86/amd/pmf/tee-if.c

diff --git a/drivers/platform/x86/amd/pmf/Kconfig 
b/drivers/platform/x86/amd/pmf/Kconfig
index 3064bc8ea167..32a029e8db80 100644
--- a/drivers/platform/x86/amd/pmf/Kconfig
+++ b/drivers/platform/x86/amd/pmf/Kconfig
@@ -9,6 +9,7 @@ config AMD_PMF
depends on POWER_SUPPLY
depends on AMD_NB
select ACPI_PLATFORM_PROFILE
+   depends on TEE
help
  This driver provides support for the AMD Platform Management 
Framework.
  The goal is to enhance end user experience by making AMD PCs smarter,
diff --git a/drivers/platform/x86/amd/pmf/Makefile 
b/drivers/platform/x86/amd/pmf/Makefile
index fdededf54392..d2746ee7369f 100644
--- a/drivers/platform/x86/amd/pmf/Makefile
+++ b/drivers/platform/x86/amd/pmf/Makefile
@@ -6,4 +6,5 @@
 
 obj-$(CONFIG_AMD_PMF) += amd-pmf.o
 amd-pmf-objs := core.o acpi.o sps.o \
-   auto-mode.o cnqf.o
+   auto-mode.o cnqf.o \
+   tee-if.o
diff --git a/drivers/platform/x86/amd/pmf/core.c 
b/drivers/platform/x86/amd/pmf/core.c
index 78ed3ee22555..d57ed038f0c9 100644
--- a/drivers/platform/x86/amd/pmf/core.c
+++ b/drivers/platform/x86/amd/pmf/core.c
@@ -309,13 +309,13 @@ static void amd_pmf_init_features(struct amd_pmf_dev *dev)
dev_dbg(dev->dev, "SPS enabled and Platform Profiles 
registered\n");
}
 
-   /* Enable Auto Mode */
-   if (is_apmf_func_supported(dev, APMF_FUNC_AUTO_MODE)) {
+   if (amd_pmf_init_smart_pc(dev)) {
+   dev_dbg(dev->dev, "Smart PC Solution Enabled\n");
+   } else if (is_apmf_func_supported(dev, APMF_FUNC_AUTO_MODE)) {
amd_pmf_init_auto_mode(dev);
dev_dbg(dev->dev, "Auto Mode Init done\n");
} else if (is_apmf_func_supported(dev, APMF_FUNC_DYN_SLIDER_AC) ||
  is_apmf_func_supported(dev, APMF_FUNC_DYN_SLIDER_DC)) 
{
-   /* Enable Cool n Quiet Framework (CnQF) */
ret = amd_pmf_init_cnqf(dev);
if (ret)
dev_warn(dev->dev, "CnQF Init failed\n");
@@ -330,7 +330,9 @@ static void amd_pmf_deinit_features(struct amd_pmf_dev *dev)
amd_pmf_deinit_sps(dev);
}
 
-   if (is_apmf_func_supported(dev, APMF_FUNC_AUTO_MODE)) {
+   if (dev->smart_pc_enabled) {
+   amd_pmf_deinit_smart_pc(dev);
+   } else if (is_apmf_func_supported(dev, APMF_FUNC_AUTO_MODE)) {
amd_pmf_deinit_auto_mode(dev);
} else if (is_apmf_func_supported(dev, APMF_FUNC_DYN_SLIDER_AC) ||
  is_apmf_func_supported(dev, APMF_FUNC_DYN_SLIDER_DC)) 
{
diff --git a/drivers/platform/x86/amd/pmf/pmf.h 
b/drivers/platform/x86/amd/pmf/pmf.h
index deba88e6e4c8..bd40458937ba 100644
--- a/drivers/platform/x86/amd/pmf/pmf.h
+++ b/drivers/platform/x86/amd/pmf/pmf.h
@@ -179,6 +179,12 @@ struct amd_pmf_dev {
bool cnqf_enabled;
bool cnqf_supported;
struct notifier_block pwr_src_notifier;
+   /* Smart PC solution builder */
+   struct tee_context *tee_ctx;
+   struct tee_shm *fw_shm_pool;
+   u32 session_id;
+   void *shbuf;
+   bool smart_pc_enabled;
 };
 
 struct apmf_sps_prop_granular {
@@ -389,6 +395,13 @@ struct apmf_dyn_slider_output {
struct apmf_cnqf_power_set ps[APMF_CNQF_MAX];
 } __packed;
 
+struct ta_pmf_shared_memory {
+   int command_id;
+   int resp_id;
+   u32 pmf_result;
+   u32 if_version;
+};
+
 /* Core Layer */
 int apmf_acpi_init(struct amd_pmf_dev *pmf_dev);
 void apmf_acpi_deinit(struct amd_pmf_dev *pmf_dev);
@@ -433,4 +446,7 @@ void amd_pmf_deinit_cnqf(struct amd_pmf_dev *dev);
 int amd_pmf_trans_cnqf(struct amd_pmf_dev *dev, int socket_power, ktime_t 
time_lapsed_ms);
 extern const struct attribute_group cnqf_feature_attribute_group;
 
+/* Smart PC builder Layer */
+int amd_pmf_init_smart_pc(struct amd_pmf_dev *dev);
+void amd_pmf_deinit_smart_pc(struct amd_pmf_dev *dev);
 #endif /* PMF_H */
diff --git a/drivers/platform/x86/amd/pmf/tee-if.c 
b/drivers/platform/x86/amd/pmf/tee-if.c
new file mode 100644
index ..6ec8c3726624
--- /dev/null
+++ b/drivers/platform/x86/amd/pmf/tee-if.c
@@ -0,0 +1,105 @@
+// 

[PATCH v3 00/16] Introduce PMF Smart PC Solution Builder Feature

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

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

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

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

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

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


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

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

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

 Documentation/admin-guide/index.rst   |   1 +
 Documentation/admin-guide/pmf.rst |  25 +
 drivers/gpu/drm/amd/amdgpu/Makefile   |   2 +
 drivers/gpu/drm/amd/amdgpu/amdgpu.h   |   1 +
 drivers/gpu/drm/amd/amdgpu/amdgpu_pmf.c   | 154 ++
 drivers/hid/amd-sfh-hid/amd_sfh_common.h  |   6 +
 drivers/hid/amd-sfh-hid/sfh1_1/amd_sfh_desc.c |  22 +-
 drivers/hid/amd-sfh-hid/sfh1_1/amd_sfh_init.c |  17 +
 .../amd-sfh-hid/sfh1_1/amd_sfh_interface.c|  48 ++
 .../amd-sfh-hid/sfh1_1/amd_sfh_interface.h|   1 +
 drivers/platform/x86/amd/pmf/Kconfig  |   3 +
 drivers/platform/x86/amd/pmf/Makefile |   3 +-
 drivers/platform/x86/amd/pmf/acpi.c   |  37 ++
 drivers/platform/x86/amd/pmf/core.c   |  68 ++-
 drivers/platform/x86/amd/pmf/pmf.h| 202 +++
 drivers/platform/x86/amd/pmf/spc.c| 197 +++
 drivers/platform/x86/amd/pmf/sps.c|   2 +-
 drivers/platform/x86/amd/pmf/tee-if.c | 507 ++
 include/linux/amd-pmf-io.h|  55 ++
 19 files changed, 1324 insertions(+), 27 deletions(-)
 create mode 100644 Documentation/admin-guide/pmf.rst
 create mode 100644 drivers/gpu/drm/amd/amdgpu/amdgpu_pmf.c
 create mode 100644 drivers/platform/x86/amd/pmf/spc.c
 create mode 100644 drivers/platform/x86/amd/pmf/tee-if.c
 create mode 100644 include/linux/amd-pmf-io.h

-- 
2.25.1



[PATCH v7 11/12] drm/amdgpu: introduce userqueue eviction fence

2023-10-10 Thread Shashank Sharma
This patch adds support for userqueue eviction fences. In general, when
a process wants to map VRAM memory but TTM can't find enough space, it
attempts to evict BOs from its LRU list. This fence will prevent the TTM
manager from evicting the process's BOs from VRAM.

The general idea behind this is:
- Eviction fence is initialized during the uq_mgr init and saved in
  fpriv->uq_mgr.
- This fence is attached to every userqueue object (MQD, ctx, doorbell
  and wptr) in a shared way, during the queue creation.
- The fence is signaled during the queue destruction.

Cc: Alex Deucher 
Cc: Christian Koenig 
Cc: Felix Kuehling 
Signed-off-by: Shashank Sharma 
Signed-off-by: Arvind Yadav 
---
 drivers/gpu/drm/amd/amdgpu/amdgpu_userqueue.c | 82 ++-
 drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c|  7 ++
 .../gpu/drm/amd/include/amdgpu_userqueue.h| 15 
 3 files changed, 103 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_userqueue.c 
b/drivers/gpu/drm/amd/amdgpu/amdgpu_userqueue.c
index 6bae014b248e..26cdd54acd74 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_userqueue.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_userqueue.c
@@ -21,7 +21,7 @@
  * OTHER DEALINGS IN THE SOFTWARE.
  *
  */
-
+#include 
 #include "amdgpu.h"
 #include "amdgpu_vm.h"
 #include "amdgpu_userqueue.h"
@@ -45,6 +45,66 @@ amdgpu_userqueue_find(struct amdgpu_userq_mgr *uq_mgr, int 
qid)
return idr_find(_mgr->userq_idr, qid);
 }
 
+static const char *
+amdgpu_userqueue_fence_get_driver_name(struct dma_fence *fence)
+{
+   return "amdgpu";
+}
+
+static const char *
+amdgpu_userqueue_fence_get_timeline_name(struct dma_fence *f)
+{
+   struct amdgpu_userq_fence *ef = container_of(f, struct 
amdgpu_userq_fence, base);
+
+   return ef->timeline_name;
+}
+
+static const struct dma_fence_ops amdgpu_userqueue_eviction_fence_ops = {
+   .use_64bit_seqno = true,
+   .get_driver_name = amdgpu_userqueue_fence_get_driver_name,
+   .get_timeline_name = amdgpu_userqueue_fence_get_timeline_name,
+};
+
+static void
+amdgpu_userqueue_init_eviction_fence(struct amdgpu_userq_mgr *uq_mgr)
+{
+   struct amdgpu_userq_fence *fence = _mgr->eviction_fence;
+   atomic_t seq = ATOMIC_INIT(0);
+
+   spin_lock_init(>lock);
+   fence->fence_ctx = dma_fence_context_alloc(1);
+   fence->seq = seq;
+   get_task_comm(fence->timeline_name, current);
+   dma_fence_init(>base, _userqueue_eviction_fence_ops,
+   >lock, fence->fence_ctx,
+   atomic_inc_return(>seq));
+}
+
+struct dma_fence *
+amdgpu_userqueue_attach_eviction_fence(struct amdgpu_userq_mgr *uq_mgr,
+  struct amdgpu_bo *bo)
+{
+   struct dma_fence *ef = _mgr->eviction_fence.base;
+   struct dma_resv *resv = bo->tbo.base.resv;
+   int ret;
+
+   ret = dma_resv_reserve_fences(resv, 1);
+   if (ret) {
+   dma_fence_wait(ef, false);
+   return NULL;
+   }
+
+   dma_resv_add_fence(resv, ef, DMA_RESV_USAGE_READ);
+   return dma_fence_get(ef);
+}
+
+void
+amdgpu_userqueue_signal_eviction_fence(struct dma_fence *ef)
+{
+   dma_fence_signal(ef);
+   dma_fence_put(ef);
+}
+
 int amdgpu_userqueue_create_object(struct amdgpu_userq_mgr *uq_mgr,
   struct amdgpu_userq_obj *userq_obj,
   int size)
@@ -88,6 +148,13 @@ int amdgpu_userqueue_create_object(struct amdgpu_userq_mgr 
*uq_mgr,
}
 
userq_obj->gpu_addr = amdgpu_bo_gpu_offset(userq_obj->obj);
+   userq_obj->ev_fence = amdgpu_userqueue_attach_eviction_fence(uq_mgr, 
userq_obj->obj);
+   if (!userq_obj->ev_fence) {
+   DRM_ERROR("Failed to attach eviction fence to FW object\n");
+   r = -EFAULT;
+   goto unresv;
+   }
+
amdgpu_bo_unreserve(userq_obj->obj);
memset(userq_obj->cpu_ptr, 0, size);
return 0;
@@ -103,6 +170,7 @@ int amdgpu_userqueue_create_object(struct amdgpu_userq_mgr 
*uq_mgr,
 void amdgpu_userqueue_destroy_object(struct amdgpu_userq_mgr *uq_mgr,
   struct amdgpu_userq_obj *userq_obj)
 {
+   amdgpu_userqueue_signal_eviction_fence(userq_obj->ev_fence);
amdgpu_bo_kunmap(userq_obj->obj);
amdgpu_bo_unref(_obj->obj);
 }
@@ -140,11 +208,21 @@ amdgpu_userqueue_get_doorbell_index(struct 
amdgpu_userq_mgr *uq_mgr,
goto unpin_bo;
}
 
+   db_obj->ev_fence = amdgpu_userqueue_attach_eviction_fence(uq_mgr, 
db_obj->obj);
+   if (!db_obj->ev_fence) {
+   DRM_ERROR("[Usermode queues] Failed to attach eviction fence 
with db_bo\n");
+   r = -EFAULT;
+   goto unres_bo;
+   }
+
index = amdgpu_doorbell_index_on_bar(uq_mgr->adev, db_obj->obj, 
doorbell_offset);
DRM_DEBUG_DRIVER("[Usermode queues] doorbell index=%lld\n", index);

[PATCH v7 12/12] drm/amdgpu: [REVERTME] block usermode queue IOCTL

2023-10-10 Thread Shashank Sharma
This patch blocks the amdgpu usermode queue IOCTL function until
a valid userspace client gets merged upstream. This patch must be
reverted as soon as we have the mesa-3D consumer stack available.

Cc: Alex Deucher 
Cc: Christian Koenig 
Signed-off-by: Shashank Sharma 
---
 drivers/gpu/drm/amd/amdgpu/amdgpu_userqueue.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_userqueue.c 
b/drivers/gpu/drm/amd/amdgpu/amdgpu_userqueue.c
index 26cdd54acd74..22daeee5bf7c 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_userqueue.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_userqueue.c
@@ -330,6 +330,9 @@ int amdgpu_userq_ioctl(struct drm_device *dev, void *data,
union drm_amdgpu_userq *args = data;
int r = 0;
 
+   DRM_ERROR("Usermode queue is not ready to use\n");
+   return -EOPNOTSUPP;
+
switch (args->in.op) {
case AMDGPU_USERQ_OP_CREATE:
r = amdgpu_userqueue_create(filp, args);
-- 
2.42.0



[PATCH v7 09/12] drm/amdgpu: generate doorbell index for userqueue

2023-10-10 Thread Shashank Sharma
The userspace sends us the doorbell object and the relative doobell
index in the object to be used for the usermode queue, but the FW
expects the absolute doorbell index on the PCI BAR in the MQD. This
patch adds a function to convert this relative doorbell index to
absolute doorbell index.

This patch is dependent on the doorbell manager series which is
expected to be merged soon:
Link: https://patchwork.freedesktop.org/series/115802/

V5: Fix the db object reference leak (Christian)
V6: Pin the doorbell bo in userqueue_create() function, and unpin it
in userqueue destoy (Christian)
V7: Added missing kfree for queue in error cases
Added Alex's R-B

Cc: Alex Deucher 
Cc: Christian Koenig 
Reviewed-by: Alex Deucher 
Signed-off-by: Shashank Sharma 
---
 drivers/gpu/drm/amd/amdgpu/amdgpu_userqueue.c | 58 +++
 drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c|  1 +
 .../gpu/drm/amd/include/amdgpu_userqueue.h|  1 +
 3 files changed, 60 insertions(+)

diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_userqueue.c 
b/drivers/gpu/drm/amd/amdgpu/amdgpu_userqueue.c
index 141808e9296b..ec49c10f7511 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_userqueue.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_userqueue.c
@@ -94,6 +94,52 @@ void amdgpu_userqueue_destroy_object(struct amdgpu_userq_mgr 
*uq_mgr,
amdgpu_bo_unref(_obj->obj);
 }
 
+static uint64_t
+amdgpu_userqueue_get_doorbell_index(struct amdgpu_userq_mgr *uq_mgr,
+struct amdgpu_usermode_queue *queue,
+struct drm_file *filp,
+uint32_t doorbell_offset)
+{
+   uint64_t index;
+   struct drm_gem_object *gobj;
+   struct amdgpu_userq_obj *db_obj = >db_obj;
+   int r;
+
+   gobj = drm_gem_object_lookup(filp, queue->doorbell_handle);
+   if (gobj == NULL) {
+   DRM_ERROR("Can't find GEM object for doorbell\n");
+   return -EINVAL;
+   }
+
+   db_obj->obj = amdgpu_bo_ref(gem_to_amdgpu_bo(gobj));
+   drm_gem_object_put(gobj);
+
+   /* Pin the BO before generating the index, unpin in queue destroy */
+   r = amdgpu_bo_pin(db_obj->obj, AMDGPU_GEM_DOMAIN_DOORBELL);
+   if (r) {
+   DRM_ERROR("[Usermode queues] Failed to pin doorbell object\n");
+   goto unref_bo;
+   }
+
+   r = amdgpu_bo_reserve(db_obj->obj, true);
+   if (r) {
+   DRM_ERROR("[Usermode queues] Failed to pin doorbell object\n");
+   goto unpin_bo;
+   }
+
+   index = amdgpu_doorbell_index_on_bar(uq_mgr->adev, db_obj->obj, 
doorbell_offset);
+   DRM_DEBUG_DRIVER("[Usermode queues] doorbell index=%lld\n", index);
+   amdgpu_bo_unreserve(db_obj->obj);
+   return index;
+
+unpin_bo:
+   amdgpu_bo_unpin(db_obj->obj);
+
+unref_bo:
+   amdgpu_bo_unref(_obj->obj);
+   return r;
+}
+
 static int
 amdgpu_userqueue_destroy(struct drm_file *filp, int queue_id)
 {
@@ -114,6 +160,8 @@ amdgpu_userqueue_destroy(struct drm_file *filp, int 
queue_id)
 
uq_funcs = adev->userq_funcs[queue->queue_type];
uq_funcs->mqd_destroy(uq_mgr, queue);
+   amdgpu_bo_unpin(queue->db_obj.obj);
+   amdgpu_bo_unref(>db_obj.obj);
idr_remove(_mgr->userq_idr, queue_id);
kfree(queue);
 
@@ -129,6 +177,7 @@ amdgpu_userqueue_create(struct drm_file *filp, union 
drm_amdgpu_userq *args)
struct amdgpu_device *adev = uq_mgr->adev;
const struct amdgpu_userq_funcs *uq_funcs;
struct amdgpu_usermode_queue *queue;
+   uint64_t index;
int qid, r = 0;
 
/* Usermode queues are only supported for GFX/SDMA engines as of now */
@@ -158,6 +207,15 @@ amdgpu_userqueue_create(struct drm_file *filp, union 
drm_amdgpu_userq *args)
queue->flags = args->in.flags;
queue->vm = >vm;
 
+   /* Convert relative doorbell offset into absolute doorbell index */
+   index = amdgpu_userqueue_get_doorbell_index(uq_mgr, queue, filp, 
args->in.doorbell_offset);
+   if (index == (uint64_t)-EINVAL) {
+   DRM_ERROR("Failed to get doorbell for queue\n");
+   kfree(queue);
+   goto unlock;
+   }
+   queue->doorbell_index = index;
+
r = uq_funcs->mqd_create(uq_mgr, >in, queue);
if (r) {
DRM_ERROR("Failed to create Queue\n");
diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c 
b/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c
index 8c62a51025af..33de65a0d974 100644
--- a/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c
@@ -6605,6 +6605,7 @@ static int gfx_v11_0_userq_mqd_create(struct 
amdgpu_userq_mgr *uq_mgr,
userq_props.queue_size = mqd_user->queue_size;
userq_props.hqd_base_gpu_addr = mqd_user->queue_va;
userq_props.mqd_gpu_addr = queue->mqd.gpu_addr;
+   userq_props.doorbell_index = queue->doorbell_index;
userq_props.use_doorbell = true;
 
r 

[PATCH v7 08/12] drm/amdgpu: map wptr BO into GART

2023-10-10 Thread Shashank Sharma
To support oversubscription, MES FW expects WPTR BOs to
be mapped into GART, before they are submitted to usermode
queues. This patch adds a function for the same.

V4: fix the wptr value before mapping lookup (Bas, Christian).

V5: Addressed review comments from Christian:
- Either pin object or allocate from GART, but not both.
- All the handling must be done with the VM locks held.

V7: Addressed review comments from Christian:
- Do not take vm->eviction_lock
- Use amdgpu_bo_gpu_offset to get the wptr_bo GPU offset

Cc: Alex Deucher 
Cc: Christian Koenig 
Signed-off-by: Shashank Sharma 
Signed-off-by: Arvind Yadav 
---
 drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c| 76 +++
 .../gpu/drm/amd/include/amdgpu_userqueue.h|  1 +
 2 files changed, 77 insertions(+)

diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c 
b/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c
index d7d374822352..8c62a51025af 100644
--- a/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c
@@ -6405,6 +6405,74 @@ const struct amdgpu_ip_block_version gfx_v11_0_ip_block =
.funcs = _v11_0_ip_funcs,
 };
 
+static int
+gfx_v11_0_map_gtt_bo_to_gart(struct amdgpu_device *adev, struct amdgpu_bo *bo)
+{
+   int ret;
+
+   ret = amdgpu_bo_reserve(bo, true);
+   if (ret) {
+   DRM_ERROR("Failed to reserve bo. ret %d\n", ret);
+   goto err_reserve_bo_failed;
+   }
+
+   ret = amdgpu_ttm_alloc_gart(>tbo);
+   if (ret) {
+   DRM_ERROR("Failed to bind bo to GART. ret %d\n", ret);
+   goto err_map_bo_gart_failed;
+   }
+
+   amdgpu_bo_unreserve(bo);
+   bo = amdgpu_bo_ref(bo);
+
+   return 0;
+
+err_map_bo_gart_failed:
+   amdgpu_bo_unreserve(bo);
+err_reserve_bo_failed:
+   return ret;
+}
+
+static int
+gfx_v11_0_create_wptr_mapping(struct amdgpu_userq_mgr *uq_mgr,
+ struct amdgpu_usermode_queue *queue,
+ uint64_t wptr)
+{
+   struct amdgpu_device *adev = uq_mgr->adev;
+   struct amdgpu_bo_va_mapping *wptr_mapping;
+   struct amdgpu_vm *wptr_vm;
+   struct amdgpu_userq_obj *wptr_obj = >wptr_obj;
+   int ret;
+
+   wptr_vm = queue->vm;
+   ret = amdgpu_bo_reserve(wptr_vm->root.bo, false);
+   if (ret)
+   return ret;
+
+   wptr &= AMDGPU_GMC_HOLE_MASK;
+   wptr_mapping = amdgpu_vm_bo_lookup_mapping(wptr_vm, wptr >> PAGE_SHIFT);
+   amdgpu_bo_unreserve(wptr_vm->root.bo);
+   if (!wptr_mapping) {
+   DRM_ERROR("Failed to lookup wptr bo\n");
+   return -EINVAL;
+   }
+
+   wptr_obj->obj = wptr_mapping->bo_va->base.bo;
+   if (wptr_obj->obj->tbo.base.size > PAGE_SIZE) {
+   DRM_ERROR("Requested GART mapping for wptr bo larger than one 
page\n");
+   return -EINVAL;
+   }
+
+   ret = gfx_v11_0_map_gtt_bo_to_gart(adev, wptr_obj->obj);
+   if (ret) {
+   DRM_ERROR("Failed to map wptr bo to GART\n");
+   return ret;
+   }
+
+   queue->wptr_obj.gpu_addr = amdgpu_bo_gpu_offset_no_check(wptr_obj->obj);
+   return 0;
+}
+
 static int gfx_v11_0_userq_map(struct amdgpu_userq_mgr *uq_mgr,
   struct amdgpu_usermode_queue *queue,
   struct amdgpu_mqd_prop *userq_props)
@@ -6434,6 +6502,7 @@ static int gfx_v11_0_userq_map(struct amdgpu_userq_mgr 
*uq_mgr,
queue_input.queue_size = userq_props->queue_size >> 2;
queue_input.doorbell_offset = userq_props->doorbell_index;
queue_input.page_table_base_addr = 
amdgpu_gmc_pd_addr(queue->vm->root.bo);
+   queue_input.wptr_mc_addr = queue->wptr_obj.gpu_addr;
 
amdgpu_mes_lock(>mes);
r = adev->mes.funcs->add_hw_queue(>mes, _input);
@@ -6551,6 +6620,13 @@ static int gfx_v11_0_userq_mqd_create(struct 
amdgpu_userq_mgr *uq_mgr,
goto free_mqd;
}
 
+   /* FW expects WPTR BOs to be mapped into GART */
+   r = gfx_v11_0_create_wptr_mapping(uq_mgr, queue, 
userq_props.wptr_gpu_addr);
+   if (r) {
+   DRM_ERROR("Failed to create WPTR mapping\n");
+   goto free_ctx;
+   }
+
/* Map userqueue into FW using MES */
r = gfx_v11_0_userq_map(uq_mgr, queue, _props);
if (r) {
diff --git a/drivers/gpu/drm/amd/include/amdgpu_userqueue.h 
b/drivers/gpu/drm/amd/include/amdgpu_userqueue.h
index 643f31474bd8..ffe8a3d73756 100644
--- a/drivers/gpu/drm/amd/include/amdgpu_userqueue.h
+++ b/drivers/gpu/drm/amd/include/amdgpu_userqueue.h
@@ -45,6 +45,7 @@ struct amdgpu_usermode_queue {
struct amdgpu_vm*vm;
struct amdgpu_userq_obj mqd;
struct amdgpu_userq_obj fw_obj;
+   struct amdgpu_userq_obj wptr_obj;
 };
 
 struct amdgpu_userq_funcs {
-- 
2.42.0



[PATCH v7 10/12] drm/amdgpu: cleanup leftover queues

2023-10-10 Thread Shashank Sharma
This patch adds code to cleanup any leftover userqueues which
a user might have missed to destroy due to a crash or any other
programming error.

V7: Added Alex's R-B

Cc: Alex Deucher 
Cc: Christian Koenig 
Reviewed-by: Alex Deucher 
Suggested-by: Bas Nieuwenhuizen 
Signed-off-by: Bas Nieuwenhuizen 
Signed-off-by: Shashank Sharma 
---
 drivers/gpu/drm/amd/amdgpu/amdgpu_userqueue.c | 27 ++-
 1 file changed, 20 insertions(+), 7 deletions(-)

diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_userqueue.c 
b/drivers/gpu/drm/amd/amdgpu/amdgpu_userqueue.c
index ec49c10f7511..6bae014b248e 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_userqueue.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_userqueue.c
@@ -26,6 +26,19 @@
 #include "amdgpu_vm.h"
 #include "amdgpu_userqueue.h"
 
+static void
+amdgpu_userqueue_cleanup(struct amdgpu_userq_mgr *uq_mgr,
+struct amdgpu_usermode_queue *queue,
+int queue_id)
+{
+   struct amdgpu_device *adev = uq_mgr->adev;
+   const struct amdgpu_userq_funcs *uq_funcs = 
adev->userq_funcs[queue->queue_type];
+
+   uq_funcs->mqd_destroy(uq_mgr, queue);
+   idr_remove(_mgr->userq_idr, queue_id);
+   kfree(queue);
+}
+
 static struct amdgpu_usermode_queue *
 amdgpu_userqueue_find(struct amdgpu_userq_mgr *uq_mgr, int qid)
 {
@@ -145,8 +158,6 @@ amdgpu_userqueue_destroy(struct drm_file *filp, int 
queue_id)
 {
struct amdgpu_fpriv *fpriv = filp->driver_priv;
struct amdgpu_userq_mgr *uq_mgr = >userq_mgr;
-   struct amdgpu_device *adev = uq_mgr->adev;
-   const struct amdgpu_userq_funcs *uq_funcs;
struct amdgpu_usermode_queue *queue;
 
mutex_lock(_mgr->userq_mutex);
@@ -158,13 +169,9 @@ amdgpu_userqueue_destroy(struct drm_file *filp, int 
queue_id)
return -EINVAL;
}
 
-   uq_funcs = adev->userq_funcs[queue->queue_type];
-   uq_funcs->mqd_destroy(uq_mgr, queue);
amdgpu_bo_unpin(queue->db_obj.obj);
amdgpu_bo_unref(>db_obj.obj);
-   idr_remove(_mgr->userq_idr, queue_id);
-   kfree(queue);
-
+   amdgpu_userqueue_cleanup(uq_mgr, queue, queue_id);
mutex_unlock(_mgr->userq_mutex);
return 0;
 }
@@ -276,6 +283,12 @@ int amdgpu_userq_mgr_init(struct amdgpu_userq_mgr 
*userq_mgr, struct amdgpu_devi
 
 void amdgpu_userq_mgr_fini(struct amdgpu_userq_mgr *userq_mgr)
 {
+   uint32_t queue_id;
+   struct amdgpu_usermode_queue *queue;
+
+   idr_for_each_entry(_mgr->userq_idr, queue, queue_id)
+   amdgpu_userqueue_cleanup(userq_mgr, queue, queue_id);
+
idr_destroy(_mgr->userq_idr);
mutex_destroy(_mgr->userq_mutex);
 }
-- 
2.42.0



[PATCH v7 07/12] drm/amdgpu: map usermode queue into MES

2023-10-10 Thread Shashank Sharma
This patch adds new functions to map/unmap a usermode queue into
the FW, using the MES ring. As soon as this mapping is done, the
queue would  be considered ready to accept the workload.

V1: Addressed review comments from Alex on the RFC patch series
- Map/Unmap should be IP specific.
V2:
Addressed review comments from Christian:
- Fix the wptr_mc_addr calculation (moved into another patch)
Addressed review comments from Alex:
- Do not add fptrs for map/unmap

V3: Integration with doorbell manager
V4: Rebase
V5: Use gfx_v11_0 for function names (Alex)
V6: Removed queue->proc/gang/fw_ctx_address variables and doing the
address calculations locally to keep the queue structure GEN
independent (Alex)
V7: Added R-B from Alex

Cc: Alex Deucher 
Cc: Christian Koenig 
Reviewed-by: Alex Deucher 
Signed-off-by: Shashank Sharma 
---
 drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c | 72 ++
 1 file changed, 72 insertions(+)

diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c 
b/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c
index 4b0c3fc63411..d7d374822352 100644
--- a/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c
@@ -6405,6 +6405,67 @@ const struct amdgpu_ip_block_version gfx_v11_0_ip_block =
.funcs = _v11_0_ip_funcs,
 };
 
+static int gfx_v11_0_userq_map(struct amdgpu_userq_mgr *uq_mgr,
+  struct amdgpu_usermode_queue *queue,
+  struct amdgpu_mqd_prop *userq_props)
+{
+   struct amdgpu_device *adev = uq_mgr->adev;
+   struct amdgpu_userq_obj *ctx = >fw_obj;
+   struct mes_add_queue_input queue_input;
+   int r;
+
+   memset(_input, 0x0, sizeof(struct mes_add_queue_input));
+
+   queue_input.process_va_start = 0;
+   queue_input.process_va_end = (adev->vm_manager.max_pfn - 1) << 
AMDGPU_GPU_PAGE_SHIFT;
+   queue_input.process_quantum = 10; /* 10ms */
+   queue_input.gang_quantum = 1; /* 1ms */
+   queue_input.paging = false;
+
+   queue_input.process_context_addr = ctx->gpu_addr;
+   queue_input.gang_context_addr = ctx->gpu_addr + 
AMDGPU_USERQ_PROC_CTX_SZ;
+   queue_input.inprocess_gang_priority = AMDGPU_MES_PRIORITY_LEVEL_NORMAL;
+   queue_input.gang_global_priority_level = 
AMDGPU_MES_PRIORITY_LEVEL_NORMAL;
+
+   queue_input.process_id = queue->vm->pasid;
+   queue_input.queue_type = queue->queue_type;
+   queue_input.mqd_addr = queue->mqd.gpu_addr;
+   queue_input.wptr_addr = userq_props->wptr_gpu_addr;
+   queue_input.queue_size = userq_props->queue_size >> 2;
+   queue_input.doorbell_offset = userq_props->doorbell_index;
+   queue_input.page_table_base_addr = 
amdgpu_gmc_pd_addr(queue->vm->root.bo);
+
+   amdgpu_mes_lock(>mes);
+   r = adev->mes.funcs->add_hw_queue(>mes, _input);
+   amdgpu_mes_unlock(>mes);
+   if (r) {
+   DRM_ERROR("Failed to map queue in HW, err (%d)\n", r);
+   return r;
+   }
+
+   DRM_DEBUG_DRIVER("Queue (doorbell:%d) mapped successfully\n", 
userq_props->doorbell_index);
+   return 0;
+}
+
+static void gfx_v11_0_userq_unmap(struct amdgpu_userq_mgr *uq_mgr,
+ struct amdgpu_usermode_queue *queue)
+{
+   struct amdgpu_device *adev = uq_mgr->adev;
+   struct mes_remove_queue_input queue_input;
+   struct amdgpu_userq_obj *ctx = >fw_obj;
+   int r;
+
+   memset(_input, 0x0, sizeof(struct mes_remove_queue_input));
+   queue_input.doorbell_offset = queue->doorbell_index;
+   queue_input.gang_context_addr = ctx->gpu_addr + 
AMDGPU_USERQ_PROC_CTX_SZ;
+
+   amdgpu_mes_lock(>mes);
+   r = adev->mes.funcs->remove_hw_queue(>mes, _input);
+   amdgpu_mes_unlock(>mes);
+   if (r)
+   DRM_ERROR("Failed to unmap queue in HW, err (%d)\n", r);
+}
+
 static int gfx_v11_0_userq_create_ctx_space(struct amdgpu_userq_mgr *uq_mgr,
struct amdgpu_usermode_queue *queue,
struct 
drm_amdgpu_userq_mqd_gfx_v11_0 *mqd_user)
@@ -6490,8 +6551,18 @@ static int gfx_v11_0_userq_mqd_create(struct 
amdgpu_userq_mgr *uq_mgr,
goto free_mqd;
}
 
+   /* Map userqueue into FW using MES */
+   r = gfx_v11_0_userq_map(uq_mgr, queue, _props);
+   if (r) {
+   DRM_ERROR("Failed to init MQD\n");
+   goto free_ctx;
+   }
+
return 0;
 
+free_ctx:
+   amdgpu_userqueue_destroy_object(uq_mgr, >fw_obj);
+
 free_mqd:
amdgpu_userqueue_destroy_object(uq_mgr, >mqd);
kfree(mqd_user);
@@ -6501,6 +6572,7 @@ static int gfx_v11_0_userq_mqd_create(struct 
amdgpu_userq_mgr *uq_mgr,
 static void
 gfx_v11_0_userq_mqd_destroy(struct amdgpu_userq_mgr *uq_mgr, struct 
amdgpu_usermode_queue *queue)
 {
+   gfx_v11_0_userq_unmap(uq_mgr, queue);
amdgpu_userqueue_destroy_object(uq_mgr, >fw_obj);

[PATCH v7 06/12] drm/amdgpu: create context space for usermode queue

2023-10-10 Thread Shashank Sharma
The FW expects us to allocate at least one page as context
space to process gang, process, GDS and FW  related work.
This patch creates a joint object for the same, and calculates
GPU space offsets of these spaces.

V1: Addressed review comments on RFC patch:
Alex: Make this function IP specific

V2: Addressed review comments from Christian
- Allocate only one object for total FW space, and calculate
  offsets for each of these objects.

V3: Integration with doorbell manager

V4: Review comments:
- Remove shadow from FW space list from cover letter (Alex)
- Alignment of macro (Luben)

V5: Merged patches 5 and 6 into this single patch
Addressed review comments:
- Use lower_32_bits instead of mask (Christian)
- gfx_v11_0 instead of gfx_v11 in function names (Alex)
- Shadow and GDS objects are now coming from userspace (Christian,
  Alex)

V6:
- Add a comment to replace amdgpu_bo_create_kernel() with
  amdgpu_bo_create() during fw_ctx object creation (Christian).
- Move proc_ctx_gpu_addr, gang_ctx_gpu_addr and fw_ctx_gpu_addr out
  of generic queue structure and make it gen11 specific (Alex).

V7:
   - Using helper function to create/destroy userqueue objects.
   - Removed FW object space allocation.

Cc: Alex Deucher 
Cc: Christian Koenig 
Signed-off-by: Shashank Sharma 
Signed-off-by: Arvind Yadav 
---
 drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c| 41 +++
 .../gpu/drm/amd/include/amdgpu_userqueue.h|  1 +
 2 files changed, 42 insertions(+)

diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c 
b/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c
index 30e18cb018fa..4b0c3fc63411 100644
--- a/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c
@@ -61,6 +61,9 @@
 #define regCGTT_WD_CLK_CTRL_BASE_IDX   1
 #define regRLC_RLCS_BOOTLOAD_STATUS_gc_11_0_1  0x4e7e
 #define regRLC_RLCS_BOOTLOAD_STATUS_gc_11_0_1_BASE_IDX 1
+#define AMDGPU_USERQ_PROC_CTX_SZ   PAGE_SIZE
+#define AMDGPU_USERQ_GANG_CTX_SZ   PAGE_SIZE
+#define AMDGPU_USERQ_FW_CTX_SZ PAGE_SIZE
 
 MODULE_FIRMWARE("amdgpu/gc_11_0_0_pfp.bin");
 MODULE_FIRMWARE("amdgpu/gc_11_0_0_me.bin");
@@ -6402,6 +6405,36 @@ const struct amdgpu_ip_block_version gfx_v11_0_ip_block =
.funcs = _v11_0_ip_funcs,
 };
 
+static int gfx_v11_0_userq_create_ctx_space(struct amdgpu_userq_mgr *uq_mgr,
+   struct amdgpu_usermode_queue *queue,
+   struct 
drm_amdgpu_userq_mqd_gfx_v11_0 *mqd_user)
+{
+   struct amdgpu_userq_obj *ctx = >fw_obj;
+   struct v11_gfx_mqd *mqd = queue->mqd.cpu_ptr;
+   int r, size;
+
+   /*
+* The FW expects at least one page space allocated for
+* process ctx and gang ctx each. Create an object
+* for the same.
+*/
+   size = AMDGPU_USERQ_PROC_CTX_SZ + AMDGPU_USERQ_GANG_CTX_SZ;
+   r = amdgpu_userqueue_create_object(uq_mgr, ctx, size);
+   if (r) {
+   DRM_ERROR("Failed to allocate ctx space bo for userqueue, 
err:%d\n", r);
+   return r;
+   }
+
+   /* Shadow and GDS objects come directly from userspace */
+   mqd->shadow_base_lo = mqd_user->shadow_va & 0xFFFC;
+   mqd->shadow_base_hi = upper_32_bits(mqd_user->shadow_va);
+
+   mqd->gds_bkup_base_lo = mqd_user->gds_va & 0xFFFC;
+   mqd->gds_bkup_base_hi = upper_32_bits(mqd_user->gds_va);
+
+   return 0;
+}
+
 static int gfx_v11_0_userq_mqd_create(struct amdgpu_userq_mgr *uq_mgr,
  struct drm_amdgpu_userq_in *args_in,
  struct amdgpu_usermode_queue *queue)
@@ -6450,6 +6483,13 @@ static int gfx_v11_0_userq_mqd_create(struct 
amdgpu_userq_mgr *uq_mgr,
goto free_mqd;
}
 
+   /* Create BO for FW operations */
+   r = gfx_v11_0_userq_create_ctx_space(uq_mgr, queue, mqd_user);
+   if (r) {
+   DRM_ERROR("Failed to allocate BO for userqueue (%d)", r);
+   goto free_mqd;
+   }
+
return 0;
 
 free_mqd:
@@ -6461,6 +6501,7 @@ static int gfx_v11_0_userq_mqd_create(struct 
amdgpu_userq_mgr *uq_mgr,
 static void
 gfx_v11_0_userq_mqd_destroy(struct amdgpu_userq_mgr *uq_mgr, struct 
amdgpu_usermode_queue *queue)
 {
+   amdgpu_userqueue_destroy_object(uq_mgr, >fw_obj);
amdgpu_userqueue_destroy_object(uq_mgr, >mqd);
 }
 
diff --git a/drivers/gpu/drm/amd/include/amdgpu_userqueue.h 
b/drivers/gpu/drm/amd/include/amdgpu_userqueue.h
index bbd29f68b8d4..643f31474bd8 100644
--- a/drivers/gpu/drm/amd/include/amdgpu_userqueue.h
+++ b/drivers/gpu/drm/amd/include/amdgpu_userqueue.h
@@ -44,6 +44,7 @@ struct amdgpu_usermode_queue {
struct amdgpu_userq_mgr *userq_mgr;
struct amdgpu_vm*vm;
struct amdgpu_userq_obj mqd;
+   struct amdgpu_userq_obj fw_obj;
 };
 
 struct amdgpu_userq_funcs {
-- 
2.42.0



[PATCH v7 05/12] drm/amdgpu: create GFX-gen11 usermode queue

2023-10-10 Thread Shashank Sharma
A Memory queue descriptor (MQD) of a userqueue defines it in
the hw's context. As MQD format can vary between different
graphics IPs, we need gfx GEN specific handlers to create MQDs.

This patch:
- Introduces MQD handler functions for the usermode queues.
- Adds new functions to create and destroy userqueue MQD for
  GFX-GEN-11 IP

V1: Worked on review comments from Alex:
- Make MQD functions GEN and IP specific

V2: Worked on review comments from Alex:
- Reuse the existing adev->mqd[ip] for MQD creation
- Formatting and arrangement of code

V3:
- Integration with doorbell manager

V4: Review comments addressed:
- Do not create a new file for userq, reuse gfx_v11_0.c (Alex)
- Align name of structure members (Luben)
- Don't break up the Cc tag list and the Sob tag list in commit
  message (Luben)
V5:
   - No need to reserve the bo for MQD (Christian).
   - Some more changes to support IP specific MQD creation.

V6:
   - Add a comment reminding us to replace the amdgpu_bo_create_kernel()
 calls while creating MQD object to amdgpu_bo_create() once eviction
 fences are ready (Christian).

V7:
   - Re-arrange userqueue functions in adev instead of uq_mgr (Alex)
   - Use memdup_user instead of copy_from_user (Christian)

Cc: Alex Deucher 
Cc: Christian Koenig 
Signed-off-by: Shashank Sharma 
Signed-off-by: Arvind Yadav 
---
 drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c | 72 ++
 1 file changed, 72 insertions(+)

diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c 
b/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c
index 5c3db694afa8..30e18cb018fa 100644
--- a/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c
@@ -49,6 +49,7 @@
 #include "gfx_v11_0_3.h"
 #include "nbio_v4_3.h"
 #include "mes_v11_0.h"
+#include "amdgpu_userqueue.h"
 
 #define GFX11_NUM_GFX_RINGS1
 #define GFX11_MEC_HPD_SIZE 2048
@@ -1295,6 +1296,8 @@ static int gfx_v11_0_rlc_backdoor_autoload_enable(struct 
amdgpu_device *adev)
return 0;
 }
 
+const struct amdgpu_userq_funcs userq_gfx_v11_funcs;
+
 static int gfx_v11_0_sw_init(void *handle)
 {
int i, j, k, r, ring_id = 0;
@@ -1313,6 +1316,7 @@ static int gfx_v11_0_sw_init(void *handle)
adev->gfx.mec.num_mec = 2;
adev->gfx.mec.num_pipe_per_mec = 4;
adev->gfx.mec.num_queue_per_pipe = 4;
+   adev->userq_funcs[AMDGPU_HW_IP_GFX] = _gfx_v11_funcs;
break;
case IP_VERSION(11, 0, 1):
case IP_VERSION(11, 0, 4):
@@ -1322,6 +1326,7 @@ static int gfx_v11_0_sw_init(void *handle)
adev->gfx.mec.num_mec = 1;
adev->gfx.mec.num_pipe_per_mec = 4;
adev->gfx.mec.num_queue_per_pipe = 4;
+   adev->userq_funcs[AMDGPU_HW_IP_GFX] = _gfx_v11_funcs;
break;
default:
adev->gfx.me.num_me = 1;
@@ -6396,3 +6401,70 @@ const struct amdgpu_ip_block_version gfx_v11_0_ip_block =
.rev = 0,
.funcs = _v11_0_ip_funcs,
 };
+
+static int gfx_v11_0_userq_mqd_create(struct amdgpu_userq_mgr *uq_mgr,
+ struct drm_amdgpu_userq_in *args_in,
+ struct amdgpu_usermode_queue *queue)
+{
+   struct amdgpu_device *adev = uq_mgr->adev;
+   struct amdgpu_mqd *mqd_gfx_generic = >mqds[AMDGPU_HW_IP_GFX];
+   struct drm_amdgpu_userq_mqd_gfx_v11_0 *mqd_user;
+   struct amdgpu_mqd_prop userq_props;
+   int r;
+
+   /* Incoming MQD parameters from userspace to be saved here */
+   memset(_user, 0, sizeof(mqd_user));
+
+   /* Structure to initialize MQD for userqueue using generic MQD init 
function */
+   memset(_props, 0, sizeof(userq_props));
+
+   if (args_in->mqd_size != sizeof(struct drm_amdgpu_userq_mqd_gfx_v11_0)) 
{
+   DRM_ERROR("MQD size mismatch\n");
+   return -EINVAL;
+   }
+
+   mqd_user = memdup_user(u64_to_user_ptr(args_in->mqd), 
args_in->mqd_size);
+   if (IS_ERR(mqd_user)) {
+   DRM_ERROR("Failed to read user MQD\n");
+   return -EFAULT;
+   }
+
+   r = amdgpu_userqueue_create_object(uq_mgr, >mqd, 
mqd_gfx_generic->mqd_size);
+   if (r) {
+   DRM_ERROR("Failed to create MQD object for userqueue\n");
+   kfree(mqd_user);
+   return r;
+   }
+
+   /* Initialize the MQD BO with user given values */
+   userq_props.wptr_gpu_addr = mqd_user->wptr_va;
+   userq_props.rptr_gpu_addr = mqd_user->rptr_va;
+   userq_props.queue_size = mqd_user->queue_size;
+   userq_props.hqd_base_gpu_addr = mqd_user->queue_va;
+   userq_props.mqd_gpu_addr = queue->mqd.gpu_addr;
+   userq_props.use_doorbell = true;
+
+   r = mqd_gfx_generic->init_mqd(adev, (void *)queue->mqd.cpu_ptr, 
_props);
+   if (r) {
+   DRM_ERROR("Failed to initialize MQD for userqueue\n");
+   goto 

[PATCH v7 04/12] drm/amdgpu: add helpers to create userqueue object

2023-10-10 Thread Shashank Sharma
This patch introduces amdgpu_userqueue_object and its helper
functions to creates and destroy this object. The helper
functions creates/destroys a base amdgpu_bo, kmap/unmap it and
save the respective GPU and CPU addresses in the encapsulating
userqueue object.

These helpers will be used to create/destroy userqueue MQD, WPTR
and FW areas.

V7:
- Forked out this new patch from V11-gfx-userqueue patch to prevent
  that patch from growing very big.
- Using amdgpu_bo_create instead of amdgpu_bo_create_kernel in prep
  for eviction fences (Christian)

Cc: Alex Deucher 
Cc: Christian Koenig 
Signed-off-by: Shashank Sharma 
---
 drivers/gpu/drm/amd/amdgpu/amdgpu_userqueue.c | 62 +++
 .../gpu/drm/amd/include/amdgpu_userqueue.h| 13 
 2 files changed, 75 insertions(+)

diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_userqueue.c 
b/drivers/gpu/drm/amd/amdgpu/amdgpu_userqueue.c
index 88f0a85e6e17..141808e9296b 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_userqueue.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_userqueue.c
@@ -32,6 +32,68 @@ amdgpu_userqueue_find(struct amdgpu_userq_mgr *uq_mgr, int 
qid)
return idr_find(_mgr->userq_idr, qid);
 }
 
+int amdgpu_userqueue_create_object(struct amdgpu_userq_mgr *uq_mgr,
+  struct amdgpu_userq_obj *userq_obj,
+  int size)
+{
+   struct amdgpu_device *adev = uq_mgr->adev;
+   struct amdgpu_bo_param bp;
+   int r;
+
+   memset(, 0, sizeof(bp));
+   bp.byte_align = PAGE_SIZE;
+   bp.domain = AMDGPU_GEM_DOMAIN_GTT;
+   bp.flags = AMDGPU_GEM_CREATE_VRAM_CONTIGUOUS |
+  AMDGPU_GEM_CREATE_CPU_ACCESS_REQUIRED;
+   bp.type = ttm_bo_type_kernel;
+   bp.size = size;
+   bp.resv = NULL;
+   bp.bo_ptr_size = sizeof(struct amdgpu_bo);
+
+   r = amdgpu_bo_create(adev, , _obj->obj);
+   if (r) {
+   DRM_ERROR("Failed to allocate BO for userqueue (%d)", r);
+   return r;
+   }
+
+   r = amdgpu_bo_reserve(userq_obj->obj, true);
+   if (r) {
+   DRM_ERROR("Failed to reserve BO to map (%d)", r);
+   goto free_obj;
+   }
+
+   r = amdgpu_ttm_alloc_gart(&(userq_obj->obj)->tbo);
+   if (r) {
+   DRM_ERROR("Failed to alloc GART for userqueue object (%d)", r);
+   goto unresv;
+   }
+
+   r = amdgpu_bo_kmap(userq_obj->obj, _obj->cpu_ptr);
+   if (r) {
+   DRM_ERROR("Failed to map BO for userqueue (%d)", r);
+   goto unresv;
+   }
+
+   userq_obj->gpu_addr = amdgpu_bo_gpu_offset(userq_obj->obj);
+   amdgpu_bo_unreserve(userq_obj->obj);
+   memset(userq_obj->cpu_ptr, 0, size);
+   return 0;
+
+unresv:
+   amdgpu_bo_unreserve(userq_obj->obj);
+
+free_obj:
+   amdgpu_bo_unref(_obj->obj);
+   return r;
+}
+
+void amdgpu_userqueue_destroy_object(struct amdgpu_userq_mgr *uq_mgr,
+  struct amdgpu_userq_obj *userq_obj)
+{
+   amdgpu_bo_kunmap(userq_obj->obj);
+   amdgpu_bo_unref(_obj->obj);
+}
+
 static int
 amdgpu_userqueue_destroy(struct drm_file *filp, int queue_id)
 {
diff --git a/drivers/gpu/drm/amd/include/amdgpu_userqueue.h 
b/drivers/gpu/drm/amd/include/amdgpu_userqueue.h
index b739274c72e1..bbd29f68b8d4 100644
--- a/drivers/gpu/drm/amd/include/amdgpu_userqueue.h
+++ b/drivers/gpu/drm/amd/include/amdgpu_userqueue.h
@@ -29,6 +29,12 @@
 
 struct amdgpu_mqd_prop;
 
+struct amdgpu_userq_obj {
+   void *cpu_ptr;
+   uint64_t gpu_addr;
+   struct amdgpu_bo *obj;
+};
+
 struct amdgpu_usermode_queue {
int queue_type;
uint64_tdoorbell_handle;
@@ -37,6 +43,7 @@ struct amdgpu_usermode_queue {
struct amdgpu_mqd_prop  *userq_prop;
struct amdgpu_userq_mgr *userq_mgr;
struct amdgpu_vm*vm;
+   struct amdgpu_userq_obj mqd;
 };
 
 struct amdgpu_userq_funcs {
@@ -60,4 +67,10 @@ int amdgpu_userq_mgr_init(struct amdgpu_userq_mgr 
*userq_mgr, struct amdgpu_devi
 
 void amdgpu_userq_mgr_fini(struct amdgpu_userq_mgr *userq_mgr);
 
+int amdgpu_userqueue_create_object(struct amdgpu_userq_mgr *uq_mgr,
+  struct amdgpu_userq_obj *userq_obj,
+  int size);
+
+void amdgpu_userqueue_destroy_object(struct amdgpu_userq_mgr *uq_mgr,
+struct amdgpu_userq_obj *userq_obj);
 #endif
-- 
2.42.0



[PATCH v7 03/12] drm/amdgpu: add new IOCTL for usermode queue

2023-10-10 Thread Shashank Sharma
This patch adds:
- A new IOCTL function to create and destroy
- A new structure to keep all the user queue data in one place.
- A function to generate unique index for the queue.

V1: Worked on review comments from RFC patch series:
  - Alex: Keep a list of queues, instead of single queue per process.
  - Christian: Use the queue manager instead of global ptrs,
   Don't keep the queue structure in amdgpu_ctx

V2: Worked on review comments:
 - Christian:
   - Formatting of text
   - There is no need for queuing of userqueues, with idr in place
 - Alex:
   - Remove use_doorbell, its unnecessary
   - Reuse amdgpu_mqd_props for saving mqd fields

 - Code formatting and re-arrangement

V3:
 - Integration with doorbell manager

V4:
 - Accommodate MQD union related changes in UAPI (Alex)
 - Do not set the queue size twice (Bas)

V5:
- Remove wrapper functions for queue indexing (Christian)
- Do not save the queue id/idr in queue itself (Christian)
- Move the idr allocation in the IP independent generic space
  (Christian)

V6:
- Check the validity of input IP type (Christian)

V7:
- Move uq_func from uq_mgr to adev (Alex)
- Add missing free(queue) for error cases (Yifan)

Cc: Alex Deucher 
Cc: Christian Koenig 
Signed-off-by: Shashank Sharma 
---
 drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c   |   1 +
 drivers/gpu/drm/amd/amdgpu/amdgpu_userqueue.c | 121 ++
 .../gpu/drm/amd/include/amdgpu_userqueue.h|   2 +
 3 files changed, 124 insertions(+)

diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c 
b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c
index e809859de388..7c540842b2c7 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c
@@ -2789,6 +2789,7 @@ const struct drm_ioctl_desc amdgpu_ioctls_kms[] = {
DRM_IOCTL_DEF_DRV(AMDGPU_GEM_VA, amdgpu_gem_va_ioctl, 
DRM_AUTH|DRM_RENDER_ALLOW),
DRM_IOCTL_DEF_DRV(AMDGPU_GEM_OP, amdgpu_gem_op_ioctl, 
DRM_AUTH|DRM_RENDER_ALLOW),
DRM_IOCTL_DEF_DRV(AMDGPU_GEM_USERPTR, amdgpu_gem_userptr_ioctl, 
DRM_AUTH|DRM_RENDER_ALLOW),
+   DRM_IOCTL_DEF_DRV(AMDGPU_USERQ, amdgpu_userq_ioctl, 
DRM_AUTH|DRM_RENDER_ALLOW),
 };
 
 static const struct drm_driver amdgpu_kms_driver = {
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_userqueue.c 
b/drivers/gpu/drm/amd/amdgpu/amdgpu_userqueue.c
index effc0c7c02cf..88f0a85e6e17 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_userqueue.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_userqueue.c
@@ -23,6 +23,127 @@
  */
 
 #include "amdgpu.h"
+#include "amdgpu_vm.h"
+#include "amdgpu_userqueue.h"
+
+static struct amdgpu_usermode_queue *
+amdgpu_userqueue_find(struct amdgpu_userq_mgr *uq_mgr, int qid)
+{
+   return idr_find(_mgr->userq_idr, qid);
+}
+
+static int
+amdgpu_userqueue_destroy(struct drm_file *filp, int queue_id)
+{
+   struct amdgpu_fpriv *fpriv = filp->driver_priv;
+   struct amdgpu_userq_mgr *uq_mgr = >userq_mgr;
+   struct amdgpu_device *adev = uq_mgr->adev;
+   const struct amdgpu_userq_funcs *uq_funcs;
+   struct amdgpu_usermode_queue *queue;
+
+   mutex_lock(_mgr->userq_mutex);
+
+   queue = amdgpu_userqueue_find(uq_mgr, queue_id);
+   if (!queue) {
+   DRM_DEBUG_DRIVER("Invalid queue id to destroy\n");
+   mutex_unlock(_mgr->userq_mutex);
+   return -EINVAL;
+   }
+
+   uq_funcs = adev->userq_funcs[queue->queue_type];
+   uq_funcs->mqd_destroy(uq_mgr, queue);
+   idr_remove(_mgr->userq_idr, queue_id);
+   kfree(queue);
+
+   mutex_unlock(_mgr->userq_mutex);
+   return 0;
+}
+
+static int
+amdgpu_userqueue_create(struct drm_file *filp, union drm_amdgpu_userq *args)
+{
+   struct amdgpu_fpriv *fpriv = filp->driver_priv;
+   struct amdgpu_userq_mgr *uq_mgr = >userq_mgr;
+   struct amdgpu_device *adev = uq_mgr->adev;
+   const struct amdgpu_userq_funcs *uq_funcs;
+   struct amdgpu_usermode_queue *queue;
+   int qid, r = 0;
+
+   /* Usermode queues are only supported for GFX/SDMA engines as of now */
+   if (args->in.ip_type != AMDGPU_HW_IP_GFX && args->in.ip_type != 
AMDGPU_HW_IP_DMA) {
+   DRM_ERROR("Usermode queue doesn't support IP type %u\n", 
args->in.ip_type);
+   return -EINVAL;
+   }
+
+   mutex_lock(_mgr->userq_mutex);
+
+   uq_funcs = adev->userq_funcs[args->in.ip_type];
+   if (!uq_funcs) {
+   DRM_ERROR("Usermode queue is not supported for this IP (%u)\n", 
args->in.ip_type);
+   r = -EINVAL;
+   goto unlock;
+   }
+
+   queue = kzalloc(sizeof(struct amdgpu_usermode_queue), GFP_KERNEL);
+   if (!queue) {
+   DRM_ERROR("Failed to allocate memory for queue\n");
+   r = -ENOMEM;
+   goto unlock;
+   }
+   queue->doorbell_handle = args->in.doorbell_handle;
+   queue->doorbell_index = args->in.doorbell_offset;
+   queue->queue_type = args->in.ip_type;
+   queue->flags = 

[PATCH v7 02/12] drm/amdgpu: add usermode queue base code

2023-10-10 Thread Shashank Sharma
This patch adds skeleton code for amdgpu usermode queue.
It contains:
- A new files with init functions of usermode queues.
- A queue context manager in driver private data.

V1: Worked on design review comments from RFC patch series:
(https://patchwork.freedesktop.org/series/112214/)
- Alex: Keep a list of queues, instead of single queue per process.
- Christian: Use the queue manager instead of global ptrs,
   Don't keep the queue structure in amdgpu_ctx

V2:
 - Reformatted code, split the big patch into two

V3:
- Integration with doorbell manager

V4:
- Align the structure member names to the largest member's column
  (Luben)
- Added SPDX license (Luben)

V5:
- Do not add amdgpu.h in amdgpu_userqueue.h (Christian).
- Move struct amdgpu_userq_mgr into amdgpu_userqueue.h (Christian).

V6: Rebase

Cc: Alex Deucher 
Cc: Christian Koenig 
Reviewed-by: Christian König 
Signed-off-by: Shashank Sharma 
---
 drivers/gpu/drm/amd/amdgpu/Makefile   |  2 +
 drivers/gpu/drm/amd/amdgpu/amdgpu.h   |  3 +
 drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c   |  1 +
 drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c   |  6 ++
 drivers/gpu/drm/amd/amdgpu/amdgpu_userqueue.c | 40 
 .../gpu/drm/amd/include/amdgpu_userqueue.h| 61 +++
 6 files changed, 113 insertions(+)
 create mode 100644 drivers/gpu/drm/amd/amdgpu/amdgpu_userqueue.c
 create mode 100644 drivers/gpu/drm/amd/include/amdgpu_userqueue.h

diff --git a/drivers/gpu/drm/amd/amdgpu/Makefile 
b/drivers/gpu/drm/amd/amdgpu/Makefile
index 384b798a9bad..a17bbaedfe82 100644
--- a/drivers/gpu/drm/amd/amdgpu/Makefile
+++ b/drivers/gpu/drm/amd/amdgpu/Makefile
@@ -240,6 +240,8 @@ amdgpu-y += \
 # add amdkfd interfaces
 amdgpu-y += amdgpu_amdkfd.o
 
+# add usermode queue
+amdgpu-y += amdgpu_userqueue.o
 
 ifneq ($(CONFIG_HSA_AMD),)
 AMDKFD_PATH := ../amdkfd
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu.h 
b/drivers/gpu/drm/amd/amdgpu/amdgpu.h
index dc2d53081e80..8c12403e51b4 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu.h
@@ -107,6 +107,7 @@
 #include "amdgpu_mca.h"
 #include "amdgpu_ras.h"
 #include "amdgpu_xcp.h"
+#include "amdgpu_userqueue.h"
 
 #define MAX_GPU_INSTANCE   64
 
@@ -469,6 +470,7 @@ struct amdgpu_fpriv {
struct mutexbo_list_lock;
struct idr  bo_list_handles;
struct amdgpu_ctx_mgr   ctx_mgr;
+   struct amdgpu_userq_mgr userq_mgr;
/** GPU partition selection */
uint32_txcp_id;
 };
@@ -969,6 +971,7 @@ struct amdgpu_device {
boolenable_mes_kiq;
struct amdgpu_mes   mes;
struct amdgpu_mqd   mqds[AMDGPU_HW_IP_NUM];
+   const struct amdgpu_userq_funcs *userq_funcs[AMDGPU_HW_IP_NUM];
 
/* df */
struct amdgpu_dfdf;
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c 
b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c
index 81edf66dbea8..e809859de388 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c
@@ -50,6 +50,7 @@
 #include "amdgpu_reset.h"
 #include "amdgpu_sched.h"
 #include "amdgpu_xgmi.h"
+#include "amdgpu_userqueue.h"
 #include "../amdxcp/amdgpu_xcp_drv.h"
 
 /*
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c 
b/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c
index 99f4df133ed3..809883de7664 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c
@@ -44,6 +44,7 @@
 #include "amdgpu_display.h"
 #include "amdgpu_ras.h"
 #include "amd_pcie.h"
+#include "amdgpu_userqueue.h"
 
 void amdgpu_unregister_gpu_instance(struct amdgpu_device *adev)
 {
@@ -1266,6 +1267,10 @@ int amdgpu_driver_open_kms(struct drm_device *dev, 
struct drm_file *file_priv)
 
amdgpu_ctx_mgr_init(>ctx_mgr, adev);
 
+   r = amdgpu_userq_mgr_init(>userq_mgr, adev);
+   if (r)
+   DRM_WARN("Can't setup usermode queues, use legacy workload 
submission only\n");
+
file_priv->driver_priv = fpriv;
goto out_suspend;
 
@@ -1333,6 +1338,7 @@ void amdgpu_driver_postclose_kms(struct drm_device *dev,
 
amdgpu_ctx_mgr_fini(>ctx_mgr);
amdgpu_vm_fini(adev, >vm);
+   amdgpu_userq_mgr_fini(>userq_mgr);
 
if (pasid)
amdgpu_pasid_free_delayed(pd->tbo.base.resv, pasid);
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_userqueue.c 
b/drivers/gpu/drm/amd/amdgpu/amdgpu_userqueue.c
new file mode 100644
index ..effc0c7c02cf
--- /dev/null
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_userqueue.c
@@ -0,0 +1,40 @@
+// SPDX-License-Identifier: MIT
+/*
+ * 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, 

[PATCH v7 01/12] drm/amdgpu: UAPI for user queue management

2023-10-10 Thread Shashank Sharma
From: Alex Deucher 

This patch intorduces new UAPI/IOCTL for usermode graphics
queue. The userspace app will fill this structure and request
the graphics driver to add a graphics work queue for it. The
output of this UAPI is a queue id.

This UAPI maps the queue into GPU, so the graphics app can start
submitting work to the queue as soon as the call returns.

V2: Addressed review comments from Alex and Christian
- Make the doorbell offset's comment clearer
- Change the output parameter name to queue_id

V3: Integration with doorbell manager

V4:
- Updated the UAPI doc (Pierre-Eric)
- Created a Union for engine specific MQDs (Alex)
- Added Christian's R-B
V5:
- Add variables for GDS and CSA in MQD structure (Alex)
- Make MQD data a ptr-size pair instead of union (Alex)

Cc: Alex Deucher 
Cc: Christian Koenig 
Reviewed-by: Christian König 
Signed-off-by: Alex Deucher 
Signed-off-by: Shashank Sharma 
---
 include/uapi/drm/amdgpu_drm.h | 110 ++
 1 file changed, 110 insertions(+)

diff --git a/include/uapi/drm/amdgpu_drm.h b/include/uapi/drm/amdgpu_drm.h
index f477eda6a2b8..a508329ce70f 100644
--- a/include/uapi/drm/amdgpu_drm.h
+++ b/include/uapi/drm/amdgpu_drm.h
@@ -54,6 +54,7 @@ extern "C" {
 #define DRM_AMDGPU_VM  0x13
 #define DRM_AMDGPU_FENCE_TO_HANDLE 0x14
 #define DRM_AMDGPU_SCHED   0x15
+#define DRM_AMDGPU_USERQ   0x16
 
 #define DRM_IOCTL_AMDGPU_GEM_CREATEDRM_IOWR(DRM_COMMAND_BASE + 
DRM_AMDGPU_GEM_CREATE, union drm_amdgpu_gem_create)
 #define DRM_IOCTL_AMDGPU_GEM_MMAP  DRM_IOWR(DRM_COMMAND_BASE + 
DRM_AMDGPU_GEM_MMAP, union drm_amdgpu_gem_mmap)
@@ -71,6 +72,7 @@ extern "C" {
 #define DRM_IOCTL_AMDGPU_VMDRM_IOWR(DRM_COMMAND_BASE + 
DRM_AMDGPU_VM, union drm_amdgpu_vm)
 #define DRM_IOCTL_AMDGPU_FENCE_TO_HANDLE DRM_IOWR(DRM_COMMAND_BASE + 
DRM_AMDGPU_FENCE_TO_HANDLE, union drm_amdgpu_fence_to_handle)
 #define DRM_IOCTL_AMDGPU_SCHED DRM_IOW(DRM_COMMAND_BASE + 
DRM_AMDGPU_SCHED, union drm_amdgpu_sched)
+#define DRM_IOCTL_AMDGPU_USERQ DRM_IOW(DRM_COMMAND_BASE + 
DRM_AMDGPU_USERQ, union drm_amdgpu_userq)
 
 /**
  * DOC: memory domains
@@ -309,6 +311,114 @@ union drm_amdgpu_ctx {
union drm_amdgpu_ctx_out out;
 };
 
+/* user queue IOCTL */
+#define AMDGPU_USERQ_OP_CREATE 1
+#define AMDGPU_USERQ_OP_FREE   2
+
+/* Flag to indicate secure buffer related workload, unused for now */
+#define AMDGPU_USERQ_MQD_FLAGS_SECURE  (1 << 0)
+/* Flag to indicate AQL workload, unused for now */
+#define AMDGPU_USERQ_MQD_FLAGS_AQL (1 << 1)
+
+/*
+ * MQD (memory queue descriptor) is a set of parameters which allow
+ * the GPU to uniquely define and identify a usermode queue. This
+ * structure defines the MQD for GFX-V11 IP ver 0.
+ */
+struct drm_amdgpu_userq_mqd_gfx_v11_0 {
+   /**
+* @queue_va: Virtual address of the GPU memory which holds the queue
+* object. The queue holds the workload packets.
+*/
+   __u64   queue_va;
+   /**
+* @queue_size: Size of the queue in bytes, this needs to be 256-byte
+* aligned.
+*/
+   __u64   queue_size;
+   /**
+* @rptr_va : Virtual address of the GPU memory which holds the ring 
RPTR.
+* This object must be at least 8 byte in size and aligned to 8-byte 
offset.
+*/
+   __u64   rptr_va;
+   /**
+* @wptr_va : Virtual address of the GPU memory which holds the ring 
WPTR.
+* This object must be at least 8 byte in size and aligned to 8-byte 
offset.
+*
+* Queue, RPTR and WPTR can come from the same object, as long as the 
size
+* and alignment related requirements are met.
+*/
+   __u64   wptr_va;
+   /**
+* @shadow_va: Virtual address of the GPU memory to hold the shadow 
buffer.
+* This must be a from a separate GPU object, and must be at least 
4-page
+* sized.
+*/
+   __u64   shadow_va;
+   /**
+* @gds_va: Virtual address of the GPU memory to hold the GDS buffer.
+* This must be a from a separate GPU object, and must be at least 
1-page
+* sized.
+*/
+   __u64   gds_va;
+   /**
+* @csa_va: Virtual address of the GPU memory to hold the CSA buffer.
+* This must be a from a separate GPU object, and must be at least 
1-page
+* sized.
+*/
+   __u64   csa_va;
+};
+
+struct drm_amdgpu_userq_in {
+   /** AMDGPU_USERQ_OP_* */
+   __u32   op;
+   /** Queue handle for USERQ_OP_FREE */
+   __u32   queue_id;
+   /** the target GPU engine to execute workload (AMDGPU_HW_IP_*) */
+   __u32   ip_type;
+   /**
+* @flags: flags to indicate special function for queue like secure
+* buffer (TMZ). Unused for now.
+*/
+   __u32   flags;
+   /**
+* @doorbell_handle: the handle of doorbell GEM object
+* associated to this 

[PATCH v7 00/12] AMDGPU usermode queues

2023-10-10 Thread Shashank Sharma
This patch series introduces AMDGPU usermode queues for gfx workloads.
Usermode queues is a method of GPU workload submission into the graphics
hardware without any interaction with kernel/DRM schedulers. In this
method, a userspace graphics application can create its own workqueue
and submit it directly in the GPU HW.

The general idea of how this is supposed to work:
- The application creates the following GPU objetcs:
  - A queue object to hold the workload packets.
  - A read pointer object.
  - A write pointer object.
  - A doorbell page.
  - Shadow bufffer pages.
  - GDS buffer pages (as required).
- The application picks a 32-bit offset in the doorbell page for this
  queue.
- The application uses the usermode_queue_create IOCTL introduced in
  this patch, by passing the GPU addresses of these objects (read ptr,
  write ptr, queue base address, shadow, gds) with doorbell object and
  32-bit doorbell offset in the doorbell page.
- The kernel creates the queue and maps it in the HW.
- The application can start submitting the data in the queue as soon as
  the kernel IOCTL returns.
- After filling the workload data in the queue, the app must write the
  number of dwords added in the queue into the doorbell offset, and the
  GPU will start fetching the data.

libDRM changes for this series and a sample DRM test program can be found
in the MESA merge request here:
https://gitlab.freedesktop.org/mesa/drm/-/merge_requests/287

Alex Deucher (1):
  drm/amdgpu: UAPI for user queue management

Shashank Sharma (11):
  drm/amdgpu: add usermode queue base code
  drm/amdgpu: add new IOCTL for usermode queue
  drm/amdgpu: add helpers to create userqueue object
  drm/amdgpu: create GFX-gen11 usermode queue
  drm/amdgpu: create context space for usermode queue
  drm/amdgpu: map usermode queue into MES
  drm/amdgpu: map wptr BO into GART
  drm/amdgpu: generate doorbell index for userqueue
  drm/amdgpu: cleanup leftover queues
  drm/amdgpu: introduce userqueue eviction fence
  drm/amdgpu: [REVERTME] block usermode queue IOCTL

 drivers/gpu/drm/amd/amdgpu/Makefile   |   2 +
 drivers/gpu/drm/amd/amdgpu/amdgpu.h   |   3 +
 drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c   |   2 +
 drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c   |   6 +
 drivers/gpu/drm/amd/amdgpu/amdgpu_userqueue.c | 377 ++
 drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c| 269 +
 .../gpu/drm/amd/include/amdgpu_userqueue.h|  94 +
 include/uapi/drm/amdgpu_drm.h | 110 +
 8 files changed, 863 insertions(+)
 create mode 100644 drivers/gpu/drm/amd/amdgpu/amdgpu_userqueue.c
 create mode 100644 drivers/gpu/drm/amd/include/amdgpu_userqueue.h

-- 
2.42.0



RE: [PATCH] drm/amdgpu:Check gfx poweron when skip flush_gpu_tlb

2023-10-10 Thread Xu, Feifei
[AMD Official Use Only - General]

If the behavior is correct, this patch looks like workaround HW reset not 
flushed the TLB or something can be workaround by adding a gpu TLB flush.

Thanks,
Feifei

-Original Message-
From: Koenig, Christian 
Sent: Tuesday, October 10, 2023 5:07 PM
To: Xu, Feifei ; Zhang, Hawking ; 
Wang, Yang(Kevin) ; amd-gfx@lists.freedesktop.org
Subject: Re: [PATCH] drm/amdgpu:Check gfx poweron when skip flush_gpu_tlb

Hi Feifei,

yeah, that is correct behavior. The GMC callback should *not* get called during 
resume in a reset, because the reset needs to take care of invalidating the TLB 
anyway.

If the later doesn't work any more we need to re-iterate the reset procedure 
and not mess with this here.

Regards,
Christian.

Am 10.10.23 um 04:27 schrieb Xu, Feifei:
> [AMD Official Use Only - General]
>
> Yes, adev->gfx.is_poweron check will be applied in gmc_v11 callback, which 
> will be called after the generic gmc part: amdgpu_gmc_flush_gpu_tlb() 
> function.
> But in commit: d0c860f33553 ("drm/amdgpu: rework lock handling for flush_tlb 
> v2"), the flush is moved at a higher level amdgpu_gmc_flush_gpu_tlb() 
> function.
>
> Thus the gmc_v11 callback will never be called in the resume because 
> adev->reset_domain->sem not released and returned ahead. Adding a check of 
> adev->gfx.is_poweron will let GFX11 not breaking ahead, like following:
>
> if (!down_read_trylock(>reset_domain->sem) && //--> true in
> gfx11
> +!adev->gfx.is_poweron) //-->false in gfx11, and the whole if 
> statement will be false, not return ahead. The following gmc v11 callback 
> will be executed later.
>
> Thanks,
> Feifei
>
> -Original Message-
> From: Zhang, Hawking 
> Sent: Monday, October 9, 2023 4:58 PM
> To: Xu, Feifei ; Wang, Yang(Kevin)
> ; amd-gfx@lists.freedesktop.org
> Cc: Koenig, Christian 
> Subject: RE: [PATCH] drm/amdgpu:Check gfx poweron when skip
> flush_gpu_tlb
>
> [AMD Official Use Only - General]
>
> adev->gfx.is_poweron check should already be applied in IP specific (gmc v11) 
> callback. If gfx is not power on, it does nothing but just returns. I didn't 
> see how it helps resolve the issue if we just move the check from one 
> function to another.
>
> Regards,
> Hawking
>
> -Original Message-
> From: Xu, Feifei 
> Sent: Monday, October 9, 2023 09:51
> To: Wang, Yang(Kevin) ;
> amd-gfx@lists.freedesktop.org
> Cc: Koenig, Christian ; Zhang, Hawking
> 
> Subject: RE: [PATCH] drm/amdgpu:Check gfx poweron when skip
> flush_gpu_tlb
>
> [AMD Official Use Only - General]
>
> Hi,
>
>>> Based on your description, the above code should use "||" instead of
>>> "&&",
> && is to add more restriction here.  To avoid skipping necessary TLB flush by 
> return.
> For Asics < GFX11, !adev->gfx.is_poweron is always true (this paremeter is 
> intrudoced from GFX11), only depends on reset_domain->sem; For Asics = GFX11, 
> !adev->gfx.is_poweron might be false (which gfx might already poweron in the 
> reset), this will make the if () not ture, return will not be executed, thus 
> flush TLB.
>
>>> And after merging code into one line may result in the lock not being 
>>> released if the lock can be acquired success.
> If !adev->gfx.is_poweron is true, the reset_domin->sem will not be 
> down_read_trylock, thus could avoid this deadlock.
>
> Thanks,
> Feifei
>
> -Original Message-
> From: Wang, Yang(Kevin) 
> Sent: Sunday, October 8, 2023 9:36 PM
> To: Xu, Feifei ; amd-gfx@lists.freedesktop.org
> Cc: Xu, Feifei ; Xu, Feifei ;
> Koenig, Christian ; Zhang, Hawking
> 
> Subject: RE: [PATCH] drm/amdgpu:Check gfx poweron when skip
> flush_gpu_tlb
>
>
> -Original Message-
> From: amd-gfx  On Behalf Of
> Feifei Xu
> Sent: Sunday, October 8, 2023 6:07 PM
> To: amd-gfx@lists.freedesktop.org
> Cc: Xu, Feifei ; Xu, Feifei ;
> Koenig, Christian ; Zhang, Hawking
> 
> Subject: [PATCH] drm/amdgpu:Check gfx poweron when skip flush_gpu_tlb
>
> To fix the gpu recovery failed on GFX11 with gfxhub pagefault, flush gpu tlb 
> after reset on GFX11.
> Gfxhub tlb flush need check if adev->gfx.is_poweron set.
>
> Fixes: d0c860f33553 ("drm/amdgpu: rework lock handling for flush_tlb
> v2")
>
> Signed-off-by: Feifei Xu 
> ---
>   drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.c | 3 ++-
>   1 file changed, 2 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.c
> b/drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.c
> index 2f9bb86edd71..048d32edee88 100644
> --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.c
> +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.c
> @@ -611,8 +611,9 @@ void amdgpu_gmc_flush_gpu_tlb(struct amdgpu_device *adev, 
> uint32_t vmid,
>  /*
>   * A GPU reset should flush all TLBs anyway, so no need to do
>   * this while one is ongoing.
> +* For GFX11, gfxhub flush check if adev->gfx.is_poweron is 
> set.
>   */
> -   if (!down_read_trylock(>reset_domain->sem))
> +  

RE: [PATCH] drm/amdgpu:Check gfx poweron when skip flush_gpu_tlb

2023-10-10 Thread Xu, Feifei
[AMD Official Use Only - General]

For the unlocking, I have tested on both nv21 and nv31, the unlock/lock paring 
looks not break.

On asic gfx.is_poweron) always true, this parameter is 
introduced from GFX11.
On gfx11, in the reset (suspend then resume) process,  after suspend, gfx 
poweron right after smu resumed successfully.
The (!adev->gfx.is_poweron) is always false  when trylock the reset_domin->sem. 
Not return ahead in gfx11 and continue gpu tlb flush in IP specific (gmc v11) 
callback.

Then unlock after gpu tlb flush:

void amdgpu_gmc_flush_gpu_tlb(struct amdgpu_device *adev, uint32_t vmid,
  uint32_t vmhub, uint32_t flush_type)
{
if (!down_read_trylock(>reset_domain->sem) && 
!adev->gfx.is_poweron)  //lock
return;
...

adev->gmc.gmc_funcs->flush_gpu_tlb(adev, vmid, vmhub,
   flush_type);
up_read(>reset_domain->sem);   //unlock
return;
}

Thanks,
Feifei

-Original Message-
From: Xu, Feifei
Sent: Tuesday, October 10, 2023 5:44 PM
To: Christian König ; Wang, Yang(Kevin) 
; amd-gfx@lists.freedesktop.org
Cc: Koenig, Christian ; Zhang, Hawking 

Subject: RE: [PATCH] drm/amdgpu:Check gfx poweron when skip flush_gpu_tlb

>> Then a TLB flush shouldn't be necessary on reset. A reset implies that the 
>> TLB is cleared as well.
Hmm, in current implementation, when we say a reset implied that the TLB is 
cleared, assume that the TLB clear is purely hardware action. There's no gpu 
tlb flush initiated by software/driver after suspend.

While in some asics of gfx11 (like nv31), gpu tlb need to be flushed by 
software/driver after smu resume successfully intentionally.
Without the gpu tlb flush on nv31, S3 or reset will be break with gfx page 
fault.

>> First of all the patch is broken because you only handle the locking, but 
>> not the unlocking part.
For the unlocking part, realized that you and Kevin are correct. Lock/unlock 
not paried.

Thanks,
Feifei

-Original Message-
From: Christian König 
Sent: Monday, October 9, 2023 4:52 PM
To: Xu, Feifei ; Wang, Yang(Kevin) ; 
amd-gfx@lists.freedesktop.org
Cc: Koenig, Christian ; Zhang, Hawking 

Subject: Re: [PATCH] drm/amdgpu:Check gfx poweron when skip flush_gpu_tlb

Am 09.10.23 um 03:50 schrieb Xu, Feifei:
> [AMD Official Use Only - General]
>
> Hi,
>
>>> Based on your description, the above code should use "||" instead of
>>> "&&",
> && is to add more restriction here.  To avoid skipping necessary TLB flush by 
> return.
> For Asics < GFX11, !adev->gfx.is_poweron is always true (this
> paremeter is intrudoced from GFX11), only depends on reset_domain->sem; For 
> Asics = GFX11, !adev->gfx.is_poweron might be false (which gfx might already 
> poweron in the reset), this will make the if () not ture, return will not be 
> executed, thus flush TLB.

First of all the patch is broken because you only handle the locking, but not 
the unlocking part.

Then a TLB flush shouldn't be necessary on reset. A reset implies that the TLB 
is cleared as well.

We discussed the possibility to avoid that, but this is not supposed to be 
happening at the moment.

Regards,
Christian.

>
>>> And after merging code into one line may result in the lock not being 
>>> released if the lock can be acquired success.
> If !adev->gfx.is_poweron is true, the reset_domin->sem will not be 
> down_read_trylock, thus could avoid this deadlock.

>
> Thanks,
> Feifei
>
> -Original Message-
> From: Wang, Yang(Kevin) 
> Sent: Sunday, October 8, 2023 9:36 PM
> To: Xu, Feifei ; amd-gfx@lists.freedesktop.org
> Cc: Xu, Feifei ; Xu, Feifei ;
> Koenig, Christian ; Zhang, Hawking
> 
> Subject: RE: [PATCH] drm/amdgpu:Check gfx poweron when skip
> flush_gpu_tlb
>
>
> -Original Message-
> From: amd-gfx  On Behalf Of
> Feifei Xu
> Sent: Sunday, October 8, 2023 6:07 PM
> To: amd-gfx@lists.freedesktop.org
> Cc: Xu, Feifei ; Xu, Feifei ;
> Koenig, Christian ; Zhang, Hawking
> 
> Subject: [PATCH] drm/amdgpu:Check gfx poweron when skip flush_gpu_tlb
>
> To fix the gpu recovery failed on GFX11 with gfxhub pagefault, flush gpu tlb 
> after reset on GFX11.
> Gfxhub tlb flush need check if adev->gfx.is_poweron set.
>
> Fixes: d0c860f33553 ("drm/amdgpu: rework lock handling for flush_tlb
> v2")
>
> Signed-off-by: Feifei Xu 
> ---
>   drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.c | 3 ++-
>   1 file changed, 2 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.c
> b/drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.c
> index 2f9bb86edd71..048d32edee88 100644
> --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.c
> +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.c
> @@ -611,8 +611,9 @@ void amdgpu_gmc_flush_gpu_tlb(struct amdgpu_device *adev, 
> uint32_t vmid,
>  /*
>   * A GPU reset should flush all TLBs anyway, so no need to do
>   * this while one is ongoing.
> +* 

[PATCH 2/2] drm/amd/pm: Add reset option for fan_ctrl on smu 13.0.7

2023-10-10 Thread Ma Jun
Add reset option for fan_ctrl interfaces on the smu v13.0.7
User can use command "echo r > interface_name" to reset the
interface to boot value

Signed-off-by: Ma Jun 
---
 .../drm/amd/pm/swsmu/smu13/smu_v13_0_7_ppt.c  | 69 +--
 1 file changed, 64 insertions(+), 5 deletions(-)

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 b8a7a1d853df..3c5526babb14 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
@@ -1497,6 +1497,59 @@ static int smu_v13_0_7_print_clk_levels(struct 
smu_context *smu,
return size;
 }
 
+static int smu_v13_0_7_od_restore_table_single(struct smu_context *smu, long 
input)
+{
+   struct smu_table_context *table_context = >smu_table;
+   OverDriveTableExternal_t *boot_overdrive_table =
+   (OverDriveTableExternal_t *)table_context->boot_overdrive_table;
+   OverDriveTableExternal_t *od_table =
+   (OverDriveTableExternal_t *)table_context->overdrive_table;
+   struct amdgpu_device *adev = smu->adev;
+   int i;
+
+   switch (input) {
+   case PP_OD_EDIT_FAN_CURVE:
+   for (i = 0; i < NUM_OD_FAN_MAX_POINTS; i++) {
+   od_table->OverDriveTable.FanLinearTempPoints[i] =
+   
boot_overdrive_table->OverDriveTable.FanLinearTempPoints[i];
+   od_table->OverDriveTable.FanLinearPwmPoints[i] =
+   
boot_overdrive_table->OverDriveTable.FanLinearPwmPoints[i];
+   }
+   od_table->OverDriveTable.FanMode = FAN_MODE_AUTO;
+   od_table->OverDriveTable.FeatureCtrlMask |= 
BIT(PP_OD_FEATURE_FAN_CURVE_BIT);
+   break;
+   case PP_OD_EDIT_ACOUSTIC_LIMIT:
+   od_table->OverDriveTable.AcousticLimitRpmThreshold =
+   
boot_overdrive_table->OverDriveTable.AcousticLimitRpmThreshold;
+   od_table->OverDriveTable.FanMode = FAN_MODE_AUTO;
+   od_table->OverDriveTable.FeatureCtrlMask |= 
BIT(PP_OD_FEATURE_FAN_CURVE_BIT);
+   break;
+   case PP_OD_EDIT_ACOUSTIC_TARGET:
+   od_table->OverDriveTable.AcousticTargetRpmThreshold =
+   
boot_overdrive_table->OverDriveTable.AcousticTargetRpmThreshold;
+   od_table->OverDriveTable.FanMode = FAN_MODE_AUTO;
+   od_table->OverDriveTable.FeatureCtrlMask |= 
BIT(PP_OD_FEATURE_FAN_CURVE_BIT);
+   break;
+   case PP_OD_EDIT_FAN_TARGET_TEMPERATURE:
+   od_table->OverDriveTable.FanTargetTemperature =
+   
boot_overdrive_table->OverDriveTable.FanTargetTemperature;
+   od_table->OverDriveTable.FanMode = FAN_MODE_AUTO;
+   od_table->OverDriveTable.FeatureCtrlMask |= 
BIT(PP_OD_FEATURE_FAN_CURVE_BIT);
+   break;
+   case PP_OD_EDIT_FAN_MINIMUM_PWM:
+   od_table->OverDriveTable.FanMinimumPwm =
+   
boot_overdrive_table->OverDriveTable.FanMinimumPwm;
+   od_table->OverDriveTable.FanMode = FAN_MODE_AUTO;
+   od_table->OverDriveTable.FeatureCtrlMask |= 
BIT(PP_OD_FEATURE_FAN_CURVE_BIT);
+   break;
+   default:
+   dev_info(adev->dev, "Invalid table index: %ld\n", input);
+   return -EINVAL;
+   }
+
+   return 0;
+}
+
 static int smu_v13_0_7_od_edit_dpm_table(struct smu_context *smu,
 enum PP_OD_DPM_TABLE_COMMAND type,
 long input[],
@@ -1783,11 +1836,17 @@ static int smu_v13_0_7_od_edit_dpm_table(struct 
smu_context *smu,
break;
 
case PP_OD_RESTORE_DEFAULT_TABLE:
-   feature_ctrlmask = od_table->OverDriveTable.FeatureCtrlMask;
-   memcpy(od_table,
-  table_context->boot_overdrive_table,
-  sizeof(OverDriveTableExternal_t));
-   od_table->OverDriveTable.FeatureCtrlMask = feature_ctrlmask;
+   if (size == 1) {
+   ret = smu_v13_0_7_od_restore_table_single(smu, 
input[0]);
+   if (ret)
+   return ret;
+   } else {
+   feature_ctrlmask = 
od_table->OverDriveTable.FeatureCtrlMask;
+   memcpy(od_table,
+   table_context->boot_overdrive_table,
+   sizeof(OverDriveTableExternal_t));
+   od_table->OverDriveTable.FeatureCtrlMask = 
feature_ctrlmask;
+   }
fallthrough;
 
case PP_OD_COMMIT_DPM_TABLE:
-- 
2.34.1



[PATCH 1/2] drm/amd/pm: Add reset option for fan_ctrl interfaces

2023-10-10 Thread Ma Jun
Add reset option for fan_ctrl interfaces.

For example:
User can use the "echo r > acoustic_limit_rpm_threshold" command
to reset acoustic_limit_rpm_threshold to boot value

Signed-off-by: Ma Jun 
---
 drivers/gpu/drm/amd/pm/amdgpu_pm.c| 12 ++
 .../drm/amd/pm/swsmu/smu13/smu_v13_0_0_ppt.c  | 24 +++
 2 files changed, 36 insertions(+)

diff --git a/drivers/gpu/drm/amd/pm/amdgpu_pm.c 
b/drivers/gpu/drm/amd/pm/amdgpu_pm.c
index 4c65a2fac028..c7c29aa24c36 100644
--- a/drivers/gpu/drm/amd/pm/amdgpu_pm.c
+++ b/drivers/gpu/drm/amd/pm/amdgpu_pm.c
@@ -3680,6 +3680,9 @@ static umode_t fan_curve_visible(struct amdgpu_device 
*adev)
  * When you have finished the editing, write "c" (commit) to the file to commit
  * your changes.
  *
+ * If you want to reset to the default value, write "r" (reset) to the file to
+ * reset them
+ *
  * This setting works under auto fan control mode only. It adjusts the PMFW's
  * behavior about the maximum speed in RPM the fan can spin. Setting via this
  * interface will switch the fan control to auto mode implicitly.
@@ -3735,6 +3738,9 @@ static umode_t acoustic_limit_threshold_visible(struct 
amdgpu_device *adev)
  * When you have finished the editing, write "c" (commit) to the file to commit
  * your changes.
  *
+ * If you want to reset to the default value, write "r" (reset) to the file to
+ * reset them
+ *
  * This setting works under auto fan control mode only. It can co-exist with
  * other settings which can work also under auto mode. It adjusts the PMFW's
  * behavior about the maximum speed in RPM the fan can spin when ASIC
@@ -3792,6 +3798,9 @@ static umode_t acoustic_target_threshold_visible(struct 
amdgpu_device *adev)
  * When you have finished the editing, write "c" (commit) to the file to commit
  * your changes.
  *
+ * If you want to reset to the default value, write "r" (reset) to the file to
+ * reset them
+ *
  * This setting works under auto fan control mode only. It can co-exist with
  * other settings which can work also under auto mode. Paring with the
  * acoustic_target_rpm_threshold setting, they define the maximum speed in
@@ -3850,6 +3859,9 @@ static umode_t fan_target_temperature_visible(struct 
amdgpu_device *adev)
  * When you have finished the editing, write "c" (commit) to the file to commit
  * your changes.
  *
+ * If you want to reset to the default value, write "r" (reset) to the file to
+ * reset them
+ *
  * This setting works under auto fan control mode only. It can co-exist with
  * other settings which can work also under auto mode. It adjusts the PMFW's
  * behavior about the minimum fan speed in PWM the fan should spin. Setting
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 47d008cbc186..4ddaa372604a 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
@@ -1533,6 +1533,30 @@ static int smu_v13_0_0_od_restore_table_single(struct 
smu_context *smu, long inp
od_table->OverDriveTable.FanMode = FAN_MODE_AUTO;
od_table->OverDriveTable.FeatureCtrlMask |= 
BIT(PP_OD_FEATURE_FAN_CURVE_BIT);
break;
+   case PP_OD_EDIT_ACOUSTIC_LIMIT:
+   od_table->OverDriveTable.AcousticLimitRpmThreshold =
+   
boot_overdrive_table->OverDriveTable.AcousticLimitRpmThreshold;
+   od_table->OverDriveTable.FanMode = FAN_MODE_AUTO;
+   od_table->OverDriveTable.FeatureCtrlMask |= 
BIT(PP_OD_FEATURE_FAN_CURVE_BIT);
+   break;
+   case PP_OD_EDIT_ACOUSTIC_TARGET:
+   od_table->OverDriveTable.AcousticTargetRpmThreshold =
+   
boot_overdrive_table->OverDriveTable.AcousticTargetRpmThreshold;
+   od_table->OverDriveTable.FanMode = FAN_MODE_AUTO;
+   od_table->OverDriveTable.FeatureCtrlMask |= 
BIT(PP_OD_FEATURE_FAN_CURVE_BIT);
+   break;
+   case PP_OD_EDIT_FAN_TARGET_TEMPERATURE:
+   od_table->OverDriveTable.FanTargetTemperature =
+   
boot_overdrive_table->OverDriveTable.FanTargetTemperature;
+   od_table->OverDriveTable.FanMode = FAN_MODE_AUTO;
+   od_table->OverDriveTable.FeatureCtrlMask |= 
BIT(PP_OD_FEATURE_FAN_CURVE_BIT);
+   break;
+   case PP_OD_EDIT_FAN_MINIMUM_PWM:
+   od_table->OverDriveTable.FanMinimumPwm =
+   
boot_overdrive_table->OverDriveTable.FanMinimumPwm;
+   od_table->OverDriveTable.FanMode = FAN_MODE_AUTO;
+   od_table->OverDriveTable.FeatureCtrlMask |= 
BIT(PP_OD_FEATURE_FAN_CURVE_BIT);
+   break;
default:
dev_info(adev->dev, "Invalid table index: %ld\n", input);
return -EINVAL;
-- 
2.34.1



RE: [PATCH] drm/amdgpu:Check gfx poweron when skip flush_gpu_tlb

2023-10-10 Thread Xu, Feifei
[AMD Official Use Only - General]

>> Then a TLB flush shouldn't be necessary on reset. A reset implies that the 
>> TLB is cleared as well.
Hmm, in current implementation, when we say a reset implied that the TLB is 
cleared, assume that the TLB clear is purely hardware action. There's no gpu 
tlb flush initiated by software/driver after suspend.

While in some asics of gfx11 (like nv31), gpu tlb need to be flushed by 
software/driver after smu resume successfully intentionally.
Without the gpu tlb flush on nv31, S3 or reset will be break with gfx page 
fault.

>> First of all the patch is broken because you only handle the locking, but 
>> not the unlocking part.
For the unlocking part, realized that you and Kevin are correct. Lock/unlock 
not paried.

Thanks,
Feifei

-Original Message-
From: Christian König 
Sent: Monday, October 9, 2023 4:52 PM
To: Xu, Feifei ; Wang, Yang(Kevin) ; 
amd-gfx@lists.freedesktop.org
Cc: Koenig, Christian ; Zhang, Hawking 

Subject: Re: [PATCH] drm/amdgpu:Check gfx poweron when skip flush_gpu_tlb

Am 09.10.23 um 03:50 schrieb Xu, Feifei:
> [AMD Official Use Only - General]
>
> Hi,
>
>>> Based on your description, the above code should use "||" instead of
>>> "&&",
> && is to add more restriction here.  To avoid skipping necessary TLB flush by 
> return.
> For Asics < GFX11, !adev->gfx.is_poweron is always true (this
> paremeter is intrudoced from GFX11), only depends on reset_domain->sem; For 
> Asics = GFX11, !adev->gfx.is_poweron might be false (which gfx might already 
> poweron in the reset), this will make the if () not ture, return will not be 
> executed, thus flush TLB.

First of all the patch is broken because you only handle the locking, but not 
the unlocking part.

Then a TLB flush shouldn't be necessary on reset. A reset implies that the TLB 
is cleared as well.

We discussed the possibility to avoid that, but this is not supposed to be 
happening at the moment.

Regards,
Christian.

>
>>> And after merging code into one line may result in the lock not being 
>>> released if the lock can be acquired success.
> If !adev->gfx.is_poweron is true, the reset_domin->sem will not be 
> down_read_trylock, thus could avoid this deadlock.

>
> Thanks,
> Feifei
>
> -Original Message-
> From: Wang, Yang(Kevin) 
> Sent: Sunday, October 8, 2023 9:36 PM
> To: Xu, Feifei ; amd-gfx@lists.freedesktop.org
> Cc: Xu, Feifei ; Xu, Feifei ;
> Koenig, Christian ; Zhang, Hawking
> 
> Subject: RE: [PATCH] drm/amdgpu:Check gfx poweron when skip
> flush_gpu_tlb
>
>
> -Original Message-
> From: amd-gfx  On Behalf Of
> Feifei Xu
> Sent: Sunday, October 8, 2023 6:07 PM
> To: amd-gfx@lists.freedesktop.org
> Cc: Xu, Feifei ; Xu, Feifei ;
> Koenig, Christian ; Zhang, Hawking
> 
> Subject: [PATCH] drm/amdgpu:Check gfx poweron when skip flush_gpu_tlb
>
> To fix the gpu recovery failed on GFX11 with gfxhub pagefault, flush gpu tlb 
> after reset on GFX11.
> Gfxhub tlb flush need check if adev->gfx.is_poweron set.
>
> Fixes: d0c860f33553 ("drm/amdgpu: rework lock handling for flush_tlb
> v2")
>
> Signed-off-by: Feifei Xu 
> ---
>   drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.c | 3 ++-
>   1 file changed, 2 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.c
> b/drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.c
> index 2f9bb86edd71..048d32edee88 100644
> --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.c
> +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.c
> @@ -611,8 +611,9 @@ void amdgpu_gmc_flush_gpu_tlb(struct amdgpu_device *adev, 
> uint32_t vmid,
>  /*
>   * A GPU reset should flush all TLBs anyway, so no need to do
>   * this while one is ongoing.
> +* For GFX11, gfxhub flush check if adev->gfx.is_poweron is 
> set.
>   */
> -   if (!down_read_trylock(>reset_domain->sem))
> +   if (!down_read_trylock(>reset_domain->sem) &&
> +!adev->gfx.is_poweron)
>  return;
>
> [Kevin]:
> Based on your description, the above code should use "||" instead of
> "&&", And after merging code into one line may result in the lock not being 
> released if the lock can be acquired success.
>
> Best Regards,
> Kevin
>
>  if (adev->gmc.flush_tlb_needs_extra_type_2)
> --
> 2.34.1
>



Recall: [PATCH] drm/amdgpu:Check gfx poweron when skip flush_gpu_tlb

2023-10-10 Thread Xu, Feifei
Xu, Feifei would like to recall the message, "[PATCH] drm/amdgpu:Check gfx 
poweron when skip flush_gpu_tlb".

RE: [PATCH] drm/amdgpu:Check gfx poweron when skip flush_gpu_tlb

2023-10-10 Thread Xu, Feifei
[AMD Official Use Only - General]

>> Then a TLB flush shouldn't be necessary on reset. A reset implies that the 
>> TLB is cleared as well.
Hmm, in current implementation, when we say a reset implied that the TLB is 
cleared, assume that the TLB clear is purely hardware action. There's no gpu 
tlb flush initiated by software/driver after suspend.

While in some asics of gfx11 (like nv31), gpu tlb need to be flushed by 
software/driver after smu resume successfully intentionally.
Without the gpu tlb flush on nv31, S3 or reset will be break with gfx page 
fault.

>> First of all the patch is broken because you only handle the locking, but 
>> not the unlocking part.
For the unlocking part, realized that you and Kevin are correct. I should put 
the trylock checking on the right of && to make sure it will be checked 
firstly. Otherwise lock/unlock not paried.

Thanks,
Feifei

-Original Message-
From: Christian König 
Sent: Monday, October 9, 2023 4:52 PM
To: Xu, Feifei ; Wang, Yang(Kevin) ; 
amd-gfx@lists.freedesktop.org
Cc: Koenig, Christian ; Zhang, Hawking 

Subject: Re: [PATCH] drm/amdgpu:Check gfx poweron when skip flush_gpu_tlb

Am 09.10.23 um 03:50 schrieb Xu, Feifei:
> [AMD Official Use Only - General]
>
> Hi,
>
>>> Based on your description, the above code should use "||" instead of
>>> "&&",
> && is to add more restriction here.  To avoid skipping necessary TLB flush by 
> return.
> For Asics < GFX11, !adev->gfx.is_poweron is always true (this
> paremeter is intrudoced from GFX11), only depends on reset_domain->sem; For 
> Asics = GFX11, !adev->gfx.is_poweron might be false (which gfx might already 
> poweron in the reset), this will make the if () not ture, return will not be 
> executed, thus flush TLB.

First of all the patch is broken because you only handle the locking, but not 
the unlocking part.

Then a TLB flush shouldn't be necessary on reset. A reset implies that the TLB 
is cleared as well.

We discussed the possibility to avoid that, but this is not supposed to be 
happening at the moment.

Regards,
Christian.

>
>>> And after merging code into one line may result in the lock not being 
>>> released if the lock can be acquired success.
> If !adev->gfx.is_poweron is true, the reset_domin->sem will not be 
> down_read_trylock, thus could avoid this deadlock.

>
> Thanks,
> Feifei
>
> -Original Message-
> From: Wang, Yang(Kevin) 
> Sent: Sunday, October 8, 2023 9:36 PM
> To: Xu, Feifei ; amd-gfx@lists.freedesktop.org
> Cc: Xu, Feifei ; Xu, Feifei ;
> Koenig, Christian ; Zhang, Hawking
> 
> Subject: RE: [PATCH] drm/amdgpu:Check gfx poweron when skip
> flush_gpu_tlb
>
>
> -Original Message-
> From: amd-gfx  On Behalf Of
> Feifei Xu
> Sent: Sunday, October 8, 2023 6:07 PM
> To: amd-gfx@lists.freedesktop.org
> Cc: Xu, Feifei ; Xu, Feifei ;
> Koenig, Christian ; Zhang, Hawking
> 
> Subject: [PATCH] drm/amdgpu:Check gfx poweron when skip flush_gpu_tlb
>
> To fix the gpu recovery failed on GFX11 with gfxhub pagefault, flush gpu tlb 
> after reset on GFX11.
> Gfxhub tlb flush need check if adev->gfx.is_poweron set.
>
> Fixes: d0c860f33553 ("drm/amdgpu: rework lock handling for flush_tlb
> v2")
>
> Signed-off-by: Feifei Xu 
> ---
>   drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.c | 3 ++-
>   1 file changed, 2 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.c
> b/drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.c
> index 2f9bb86edd71..048d32edee88 100644
> --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.c
> +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.c
> @@ -611,8 +611,9 @@ void amdgpu_gmc_flush_gpu_tlb(struct amdgpu_device *adev, 
> uint32_t vmid,
>  /*
>   * A GPU reset should flush all TLBs anyway, so no need to do
>   * this while one is ongoing.
> +* For GFX11, gfxhub flush check if adev->gfx.is_poweron is 
> set.
>   */
> -   if (!down_read_trylock(>reset_domain->sem))
> +   if (!down_read_trylock(>reset_domain->sem) &&
> +!adev->gfx.is_poweron)
>  return;
>
> [Kevin]:
> Based on your description, the above code should use "||" instead of
> "&&", And after merging code into one line may result in the lock not being 
> released if the lock can be acquired success.
>
> Best Regards,
> Kevin
>
>  if (adev->gmc.flush_tlb_needs_extra_type_2)
> --
> 2.34.1
>



RE: [PATCH] drm/amdgpu:Check gfx poweron when skip flush_gpu_tlb

2023-10-10 Thread Xu, Feifei
[AMD Official Use Only - General]

If gfx is not power on, both check will return ahead. The logic will not change.
If gfx is power on early in resume, tlb flush in the IP specific (gmc v11) 
callback will never be called because it returned ahead in the higher level 
check in amdgpu_gmc_flush_gpu_tlb() :

if (!down_read_trylock(>reset_domain->sem) && //--> true in gfx11
+!adev->gfx.is_poweron) //--> (!adev->gfx.is_poweron) = false in gfx11, 
and the whole if statement will be false, not return ahead.

Thanks,
Feifei

-Original Message-
From: Xu, Feifei
Sent: Tuesday, October 10, 2023 10:28 AM
To: Zhang, Hawking ; Wang, Yang(Kevin) 
; amd-gfx@lists.freedesktop.org
Cc: Koenig, Christian 
Subject: RE: [PATCH] drm/amdgpu:Check gfx poweron when skip flush_gpu_tlb

Yes, adev->gfx.is_poweron check will be applied in gmc_v11 callback, which will 
be called after the generic gmc part: amdgpu_gmc_flush_gpu_tlb() function.
But in commit: d0c860f33553 ("drm/amdgpu: rework lock handling for flush_tlb 
v2"), the flush is moved at a higher level amdgpu_gmc_flush_gpu_tlb() function.

Thus the gmc_v11 callback will never be called in the resume because 
adev->reset_domain->sem not released and returned ahead. Adding a check of 
adev->gfx.is_poweron will let GFX11 not breaking ahead, like following:

if (!down_read_trylock(>reset_domain->sem) && //--> true in gfx11
+!adev->gfx.is_poweron) //-->false in gfx11, and the whole if statement 
will be false, not return ahead. The following gmc v11 callback will be 
executed later.

Thanks,
Feifei

-Original Message-
From: Zhang, Hawking 
Sent: Monday, October 9, 2023 4:58 PM
To: Xu, Feifei ; Wang, Yang(Kevin) ; 
amd-gfx@lists.freedesktop.org
Cc: Koenig, Christian 
Subject: RE: [PATCH] drm/amdgpu:Check gfx poweron when skip flush_gpu_tlb

[AMD Official Use Only - General]

adev->gfx.is_poweron check should already be applied in IP specific (gmc v11) 
callback. If gfx is not power on, it does nothing but just returns. I didn't 
see how it helps resolve the issue if we just move the check from one function 
to another.

Regards,
Hawking

-Original Message-
From: Xu, Feifei 
Sent: Monday, October 9, 2023 09:51
To: Wang, Yang(Kevin) ; amd-gfx@lists.freedesktop.org
Cc: Koenig, Christian ; Zhang, Hawking 

Subject: RE: [PATCH] drm/amdgpu:Check gfx poweron when skip flush_gpu_tlb

[AMD Official Use Only - General]

Hi,

>> Based on your description, the above code should use "||" instead of
>> "&&",
&& is to add more restriction here.  To avoid skipping necessary TLB flush by 
return.
For Asics < GFX11, !adev->gfx.is_poweron is always true (this paremeter is 
intrudoced from GFX11), only depends on reset_domain->sem; For Asics = GFX11, 
!adev->gfx.is_poweron might be false (which gfx might already poweron in the 
reset), this will make the if () not ture, return will not be executed, thus 
flush TLB.

>> And after merging code into one line may result in the lock not being 
>> released if the lock can be acquired success.
If !adev->gfx.is_poweron is true, the reset_domin->sem will not be 
down_read_trylock, thus could avoid this deadlock.

Thanks,
Feifei

-Original Message-
From: Wang, Yang(Kevin) 
Sent: Sunday, October 8, 2023 9:36 PM
To: Xu, Feifei ; amd-gfx@lists.freedesktop.org
Cc: Xu, Feifei ; Xu, Feifei ; Koenig, 
Christian ; Zhang, Hawking 
Subject: RE: [PATCH] drm/amdgpu:Check gfx poweron when skip flush_gpu_tlb


-Original Message-
From: amd-gfx  On Behalf Of Feifei Xu
Sent: Sunday, October 8, 2023 6:07 PM
To: amd-gfx@lists.freedesktop.org
Cc: Xu, Feifei ; Xu, Feifei ; Koenig, 
Christian ; Zhang, Hawking 
Subject: [PATCH] drm/amdgpu:Check gfx poweron when skip flush_gpu_tlb

To fix the gpu recovery failed on GFX11 with gfxhub pagefault, flush gpu tlb 
after reset on GFX11.
Gfxhub tlb flush need check if adev->gfx.is_poweron set.

Fixes: d0c860f33553 ("drm/amdgpu: rework lock handling for flush_tlb v2")

Signed-off-by: Feifei Xu 
---
 drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.c 
b/drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.c
index 2f9bb86edd71..048d32edee88 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.c
@@ -611,8 +611,9 @@ void amdgpu_gmc_flush_gpu_tlb(struct amdgpu_device *adev, 
uint32_t vmid,
/*
 * A GPU reset should flush all TLBs anyway, so no need to do
 * this while one is ongoing.
+* For GFX11, gfxhub flush check if adev->gfx.is_poweron is set.
 */
-   if (!down_read_trylock(>reset_domain->sem))
+   if (!down_read_trylock(>reset_domain->sem) &&
+!adev->gfx.is_poweron)
return;

[Kevin]:
Based on your description, the above code should use "||" instead of "&&", And 
after merging code into one line may result in the lock not being released if 

Re: [PATCH] drm/amdgpu:Check gfx poweron when skip flush_gpu_tlb

2023-10-10 Thread Christian König

Hi Feifei,

yeah, that is correct behavior. The GMC callback should *not* get called 
during resume in a reset, because the reset needs to take care of 
invalidating the TLB anyway.


If the later doesn't work any more we need to re-iterate the reset 
procedure and not mess with this here.


Regards,
Christian.

Am 10.10.23 um 04:27 schrieb Xu, Feifei:

[AMD Official Use Only - General]

Yes, adev->gfx.is_poweron check will be applied in gmc_v11 callback, which will 
be called after the generic gmc part: amdgpu_gmc_flush_gpu_tlb() function.
But in commit: d0c860f33553 ("drm/amdgpu: rework lock handling for flush_tlb 
v2"), the flush is moved at a higher level amdgpu_gmc_flush_gpu_tlb() function.

Thus the gmc_v11 callback will never be called in the resume because 
adev->reset_domain->sem not released and returned ahead. Adding a check of 
adev->gfx.is_poweron will let GFX11 not breaking ahead, like following:

if (!down_read_trylock(>reset_domain->sem) && //--> true in gfx11
+!adev->gfx.is_poweron) //-->false in gfx11, and the whole if statement 
will be false, not return ahead. The following gmc v11 callback will be executed 
later.

Thanks,
Feifei

-Original Message-
From: Zhang, Hawking 
Sent: Monday, October 9, 2023 4:58 PM
To: Xu, Feifei ; Wang, Yang(Kevin) ; 
amd-gfx@lists.freedesktop.org
Cc: Koenig, Christian 
Subject: RE: [PATCH] drm/amdgpu:Check gfx poweron when skip flush_gpu_tlb

[AMD Official Use Only - General]

adev->gfx.is_poweron check should already be applied in IP specific (gmc v11) 
callback. If gfx is not power on, it does nothing but just returns. I didn't see 
how it helps resolve the issue if we just move the check from one function to 
another.

Regards,
Hawking

-Original Message-
From: Xu, Feifei 
Sent: Monday, October 9, 2023 09:51
To: Wang, Yang(Kevin) ; amd-gfx@lists.freedesktop.org
Cc: Koenig, Christian ; Zhang, Hawking 

Subject: RE: [PATCH] drm/amdgpu:Check gfx poweron when skip flush_gpu_tlb

[AMD Official Use Only - General]

Hi,


Based on your description, the above code should use "||" instead of
"&&",

&& is to add more restriction here.  To avoid skipping necessary TLB flush by 
return.
For Asics < GFX11, !adev->gfx.is_poweron is always true (this paremeter is intrudoced 
from GFX11), only depends on reset_domain->sem; For Asics = GFX11, 
!adev->gfx.is_poweron might be false (which gfx might already poweron in the reset), 
this will make the if () not ture, return will not be executed, thus flush TLB.


And after merging code into one line may result in the lock not being released 
if the lock can be acquired success.

If !adev->gfx.is_poweron is true, the reset_domin->sem will not be 
down_read_trylock, thus could avoid this deadlock.

Thanks,
Feifei

-Original Message-
From: Wang, Yang(Kevin) 
Sent: Sunday, October 8, 2023 9:36 PM
To: Xu, Feifei ; amd-gfx@lists.freedesktop.org
Cc: Xu, Feifei ; Xu, Feifei ; Koenig, Christian 
; Zhang, Hawking 
Subject: RE: [PATCH] drm/amdgpu:Check gfx poweron when skip flush_gpu_tlb


-Original Message-
From: amd-gfx  On Behalf Of Feifei Xu
Sent: Sunday, October 8, 2023 6:07 PM
To: amd-gfx@lists.freedesktop.org
Cc: Xu, Feifei ; Xu, Feifei ; Koenig, Christian 
; Zhang, Hawking 
Subject: [PATCH] drm/amdgpu:Check gfx poweron when skip flush_gpu_tlb

To fix the gpu recovery failed on GFX11 with gfxhub pagefault, flush gpu tlb 
after reset on GFX11.
Gfxhub tlb flush need check if adev->gfx.is_poweron set.

Fixes: d0c860f33553 ("drm/amdgpu: rework lock handling for flush_tlb v2")

Signed-off-by: Feifei Xu 
---
  drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.c | 3 ++-
  1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.c 
b/drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.c
index 2f9bb86edd71..048d32edee88 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.c
@@ -611,8 +611,9 @@ void amdgpu_gmc_flush_gpu_tlb(struct amdgpu_device *adev, 
uint32_t vmid,
 /*
  * A GPU reset should flush all TLBs anyway, so no need to do
  * this while one is ongoing.
+* For GFX11, gfxhub flush check if adev->gfx.is_poweron is set.
  */
-   if (!down_read_trylock(>reset_domain->sem))
+   if (!down_read_trylock(>reset_domain->sem) &&
+!adev->gfx.is_poweron)
 return;

[Kevin]:
Based on your description, the above code should use "||" instead of "&&", And 
after merging code into one line may result in the lock not being released if the lock can be acquired 
success.

Best Regards,
Kevin

 if (adev->gmc.flush_tlb_needs_extra_type_2)
--
2.34.1







[PATCH] drm/amd/pm: Fix a memory leak on an error path

2023-10-10 Thread Kunwu.Chan
Add missing free on an error path.

Signed-off-by: Kunwu.Chan 
---
 drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_6_ppt.c | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_6_ppt.c 
b/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_6_ppt.c
index ce971a93d28b..c26e12ff532c 100644
--- a/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_6_ppt.c
+++ b/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_6_ppt.c
@@ -1981,8 +1981,10 @@ static ssize_t smu_v13_0_6_get_gpu_metrics(struct 
smu_context *smu, void **table
 
metrics = kzalloc(sizeof(MetricsTable_t), GFP_KERNEL);
ret = smu_v13_0_6_get_metrics_table(smu, metrics, true);
-   if (ret)
+   if (ret) {
+   kfree(metrics);
return ret;
+   }
 
smu_cmn_init_soft_gpu_metrics(gpu_metrics, 1, 3);
 
-- 
2.25.1



[PATCH] drm/amd/pm: Fix a memory leak on an error path

2023-10-10 Thread Kunwu.Chan
Add missing free on an error path.

Fixes: 511a95552ec8 ("drm/amd/pm: Add SMU 13.0.6 support")
Signed-off-by: Kunwu.Chan 
---
 drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_6_ppt.c | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_6_ppt.c 
b/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_6_ppt.c
index ce971a93d28b..c26e12ff532c 100644
--- a/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_6_ppt.c
+++ b/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_6_ppt.c
@@ -1981,8 +1981,10 @@ static ssize_t smu_v13_0_6_get_gpu_metrics(struct 
smu_context *smu, void **table
 
metrics = kzalloc(sizeof(MetricsTable_t), GFP_KERNEL);
ret = smu_v13_0_6_get_metrics_table(smu, metrics, true);
-   if (ret)
+   if (ret) {
+   kfree(metrics);
return ret;
+   }
 
smu_cmn_init_soft_gpu_metrics(gpu_metrics, 1, 3);
 
-- 
2.25.1



Re: [PATCH] drm/amdgpu: save VCN instances init info before jpeg init

2023-10-10 Thread Chen, JingWen (Wayne)

Reviewed-by: Jingwen Chen 

Best Regards,
JingWen Chen

On 2023/10/10 14:27, Lin.Cao wrote:

JPEG init header will overwirte vcn init header info which will
loss some debug information

Signed-off-by: Lin.Cao 
---
  drivers/gpu/drm/amd/amdgpu/jpeg_v4_0.c | 4 
  1 file changed, 4 insertions(+)

diff --git a/drivers/gpu/drm/amd/amdgpu/jpeg_v4_0.c 
b/drivers/gpu/drm/amd/amdgpu/jpeg_v4_0.c
index a3768aefb6b6..bc38b90f8cf8 100644
--- a/drivers/gpu/drm/amd/amdgpu/jpeg_v4_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/jpeg_v4_0.c
@@ -431,6 +431,10 @@ static int jpeg_v4_0_start_sriov(struct amdgpu_device 
*adev)
end.cmd_header.command_type =
MMSCH_COMMAND__END;
  
+	size = sizeof(struct mmsch_v4_0_init_header);

+   table_loc = (uint32_t *)table->cpu_addr;
+   memcpy(, (void *)table_loc, size);
+
header.version = MMSCH_VERSION;
header.total_size = RREG32_SOC15(VCN, 0, regMMSCH_VF_CTX_SIZE);
  


RE: [PATCH] drm/amd/pm: wait for completion of the EnableGfxImu command

2023-10-10 Thread Zhang, Yifan
[Public]

Thanks for clarification.  This patch is

Reviewed-by: Yifan Zhang 

-Original Message-
From: Huang, Tim 
Sent: Tuesday, October 10, 2023 2:38 PM
To: Zhang, Yifan ; amd-gfx@lists.freedesktop.org
Cc: Deucher, Alexander 
Subject: RE: [PATCH] drm/amd/pm: wait for completion of the EnableGfxImu command

[AMD Official Use Only - General]

Hi Yifan,


-Original Message-
From: Zhang, Yifan 
Sent: Tuesday, October 10, 2023 1:31 PM
To: Huang, Tim ; amd-gfx@lists.freedesktop.org
Cc: Deucher, Alexander 
Subject: RE: [PATCH] drm/amd/pm: wait for completion of the EnableGfxImu command

[AMD Official Use Only - General]

> I'm wondering why it is "without waiting" in the first place ? It doesn't 
> make sense to continue driver loading if power up GFX fails. Can we apply the 
> change regardless of load types ?

The "without waiting" is only for ASIC bringing up. Because of some reason, the 
SMU can't response to driver in the GFX powerup stage if use FW backdoor 
loading, It may hang the system if driver try to read the status of the SMU. 
So, drive will wait a regular time to let SMU powerup the GFX but not by 
polling the response of the command.

Keep this "without waiting" for FW backdoor loading, maybe new ASICs bringing 
up need it as well. It will never be used for the normal case 
(AMDGPU_FW_LOAD_PSP).


Best Regards,
Tim Huang



-Original Message-
From: Huang, Tim 
Sent: Tuesday, October 10, 2023 12:47 PM
To: amd-gfx@lists.freedesktop.org
Cc: Deucher, Alexander ; Zhang, Yifan 
; Huang, Tim 
Subject: [PATCH] drm/amd/pm: wait for completion of the EnableGfxImu command

Wait for completion of sending the EnableGfxImu message when using the PSP FW 
loading.

Signed-off-by: Tim Huang 
---
 drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0.c | 12 ++--
 1 file changed, 10 insertions(+), 2 deletions(-)

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 8dc683c02a7d..bcb7ab9d2221 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
@@ -82,6 +82,8 @@ MODULE_FIRMWARE("amdgpu/smu_13_0_10.bin");
 #define PCIE_LC_SPEED_CNTL__LC_CURRENT_DATA_RATE_MASK 0xC000  #define 
PCIE_LC_SPEED_CNTL__LC_CURRENT_DATA_RATE__SHIFT 0xE

+#define ENABLE_IMU_ARG_GFXOFF_ENABLE   1
+
 static const int link_width[] = {0, 1, 2, 4, 8, 12, 16};

 const int pmfw_decoded_link_speed[5] = {1, 2, 3, 4, 5}; @@ -2301,11 +2303,17 
@@ int smu_v13_0_baco_exit(struct smu_context *smu)  int 
smu_v13_0_set_gfx_power_up_by_imu(struct smu_context *smu)  {
uint16_t index;
+   struct amdgpu_device *adev = smu->adev;
+
+   if (adev->firmware.load_type == AMDGPU_FW_LOAD_PSP) {
+   return smu_cmn_send_smc_msg_with_param(smu, 
SMU_MSG_EnableGfxImu,
+  
ENABLE_IMU_ARG_GFXOFF_ENABLE, NULL);
+   }

index = smu_cmn_to_asic_specific_index(smu, CMN2ASIC_MAPPING_MSG,
   SMU_MSG_EnableGfxImu);
-   /* Param 1 to tell PMFW to enable GFXOFF feature */
-   return smu_cmn_send_msg_without_waiting(smu, index, 1);
+   return smu_cmn_send_msg_without_waiting(smu, index,
+
+ ENABLE_IMU_ARG_GFXOFF_ENABLE);
 }

 int smu_v13_0_od_edit_dpm_table(struct smu_context *smu,
--
2.39.2





RE: [PATCH] drm/amd/pm: wait for completion of the EnableGfxImu command

2023-10-10 Thread Huang, Tim
[AMD Official Use Only - General]

Hi Yifan,


-Original Message-
From: Zhang, Yifan 
Sent: Tuesday, October 10, 2023 1:31 PM
To: Huang, Tim ; amd-gfx@lists.freedesktop.org
Cc: Deucher, Alexander 
Subject: RE: [PATCH] drm/amd/pm: wait for completion of the EnableGfxImu command

[AMD Official Use Only - General]

> I'm wondering why it is "without waiting" in the first place ? It doesn't 
> make sense to continue driver loading if power up GFX fails. Can we apply the 
> change regardless of load types ?

The "without waiting" is only for ASIC bringing up. Because of some reason, the 
SMU can't response to driver in the GFX powerup stage if use FW backdoor 
loading,
It may hang the system if driver try to read the status of the SMU. So, drive 
will wait a regular time to let SMU powerup the GFX but not by polling the 
response of the command.

Keep this "without waiting" for FW backdoor loading, maybe new ASICs bringing 
up need it as well. It will never be used for the normal case 
(AMDGPU_FW_LOAD_PSP).


Best Regards,
Tim Huang



-Original Message-
From: Huang, Tim 
Sent: Tuesday, October 10, 2023 12:47 PM
To: amd-gfx@lists.freedesktop.org
Cc: Deucher, Alexander ; Zhang, Yifan 
; Huang, Tim 
Subject: [PATCH] drm/amd/pm: wait for completion of the EnableGfxImu command

Wait for completion of sending the EnableGfxImu message when using the PSP FW 
loading.

Signed-off-by: Tim Huang 
---
 drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0.c | 12 ++--
 1 file changed, 10 insertions(+), 2 deletions(-)

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 8dc683c02a7d..bcb7ab9d2221 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
@@ -82,6 +82,8 @@ MODULE_FIRMWARE("amdgpu/smu_13_0_10.bin");
 #define PCIE_LC_SPEED_CNTL__LC_CURRENT_DATA_RATE_MASK 0xC000  #define 
PCIE_LC_SPEED_CNTL__LC_CURRENT_DATA_RATE__SHIFT 0xE

+#define ENABLE_IMU_ARG_GFXOFF_ENABLE   1
+
 static const int link_width[] = {0, 1, 2, 4, 8, 12, 16};

 const int pmfw_decoded_link_speed[5] = {1, 2, 3, 4, 5}; @@ -2301,11 +2303,17 
@@ int smu_v13_0_baco_exit(struct smu_context *smu)  int 
smu_v13_0_set_gfx_power_up_by_imu(struct smu_context *smu)  {
uint16_t index;
+   struct amdgpu_device *adev = smu->adev;
+
+   if (adev->firmware.load_type == AMDGPU_FW_LOAD_PSP) {
+   return smu_cmn_send_smc_msg_with_param(smu, 
SMU_MSG_EnableGfxImu,
+  
ENABLE_IMU_ARG_GFXOFF_ENABLE, NULL);
+   }

index = smu_cmn_to_asic_specific_index(smu, CMN2ASIC_MAPPING_MSG,
   SMU_MSG_EnableGfxImu);
-   /* Param 1 to tell PMFW to enable GFXOFF feature */
-   return smu_cmn_send_msg_without_waiting(smu, index, 1);
+   return smu_cmn_send_msg_without_waiting(smu, index,
+   ENABLE_IMU_ARG_GFXOFF_ENABLE);
 }

 int smu_v13_0_od_edit_dpm_table(struct smu_context *smu,
--
2.39.2




[PATCH] drm/amdgpu: save VCN instances init info before jpeg init

2023-10-10 Thread Lin . Cao
JPEG init header will overwirte vcn init header info which will
loss some debug information

Signed-off-by: Lin.Cao 
---
 drivers/gpu/drm/amd/amdgpu/jpeg_v4_0.c | 4 
 1 file changed, 4 insertions(+)

diff --git a/drivers/gpu/drm/amd/amdgpu/jpeg_v4_0.c 
b/drivers/gpu/drm/amd/amdgpu/jpeg_v4_0.c
index a3768aefb6b6..bc38b90f8cf8 100644
--- a/drivers/gpu/drm/amd/amdgpu/jpeg_v4_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/jpeg_v4_0.c
@@ -431,6 +431,10 @@ static int jpeg_v4_0_start_sriov(struct amdgpu_device 
*adev)
end.cmd_header.command_type =
MMSCH_COMMAND__END;
 
+   size = sizeof(struct mmsch_v4_0_init_header);
+   table_loc = (uint32_t *)table->cpu_addr;
+   memcpy(, (void *)table_loc, size);
+
header.version = MMSCH_VERSION;
header.total_size = RREG32_SOC15(VCN, 0, regMMSCH_VF_CTX_SIZE);
 
-- 
2.25.1



RE: [PATCH] drm/amd/pm: Fix a memory leak on an error path

2023-10-10 Thread Wang, Yang(Kevin)
[AMD Official Use Only - General]

Reviewed-by: Yang Wang 

Best Regards,
Kevin

-Original Message-
From: Kunwu.Chan 
Sent: Tuesday, October 10, 2023 2:11 PM
To: Wang, Yang(Kevin) 
Cc: Deucher, Alexander ; Kamal, Asad 
; Koenig, Christian ; Zhang, 
Hawking ; Ma, Le ; Lazar, Lijo 
; Pan, Xinhui ; airl...@gmail.com; 
amd-gfx@lists.freedesktop.org; chen...@kylinos.cn; dan.carpen...@linaro.org; 
dan...@ffwll.ch; dri-de...@lists.freedesktop.org; evan.q...@amd.com; 
kunwu.c...@hotmail.com; linux-ker...@vger.kernel.org
Subject: [PATCH] drm/amd/pm: Fix a memory leak on an error path

Add missing free on an error path.

Fixes: 511a95552ec8 ("drm/amd/pm: Add SMU 13.0.6 support")
Signed-off-by: Kunwu.Chan 
---
 drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_6_ppt.c | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_6_ppt.c 
b/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_6_ppt.c
index ce971a93d28b..c26e12ff532c 100644
--- a/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_6_ppt.c
+++ b/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_6_ppt.c
@@ -1981,8 +1981,10 @@ static ssize_t smu_v13_0_6_get_gpu_metrics(struct 
smu_context *smu, void **table

metrics = kzalloc(sizeof(MetricsTable_t), GFP_KERNEL);
ret = smu_v13_0_6_get_metrics_table(smu, metrics, true);
-   if (ret)
+   if (ret) {
+   kfree(metrics);
return ret;
+   }

smu_cmn_init_soft_gpu_metrics(gpu_metrics, 1, 3);

--
2.25.1