Re: [PATCH v3 04/16] platform/x86/amd/pmf: Add support for PMF Policy Binary
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
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
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
[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
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
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
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
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
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
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
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
[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
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
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
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
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
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
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
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
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
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
[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
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
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
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
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
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
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
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
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
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()
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
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
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
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
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
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
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
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
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
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
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()
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
[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
[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
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
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
[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
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
[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
[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
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
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
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
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
[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
[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
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
[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