Notify node unload on smu_v15_0_8 during driver unload
Signed-off-by: Asad Kamal <[email protected]>
Reviewed-by: Lijo Lazar <[email protected]>
---
.../pm/swsmu/inc/pmfw_if/smu_v15_0_8_ppsmc.h | 3 +-
drivers/gpu/drm/amd/pm/swsmu/inc/smu_types.h | 3 +-
drivers/gpu/drm/amd/pm/swsmu/inc/smu_v15_0.h | 1 +
.../drm/amd/pm/swsmu/smu15/smu_v15_0_8_ppt.c | 60 +++++++++++++++++++
.../drm/amd/pm/swsmu/smu15/smu_v15_0_8_ppt.h | 2 +
drivers/gpu/drm/amd/pm/swsmu/smu_cmn.c | 26 ++++++++
drivers/gpu/drm/amd/pm/swsmu/smu_cmn.h | 2 +
7 files changed, 95 insertions(+), 2 deletions(-)
diff --git a/drivers/gpu/drm/amd/pm/swsmu/inc/pmfw_if/smu_v15_0_8_ppsmc.h
b/drivers/gpu/drm/amd/pm/swsmu/inc/pmfw_if/smu_v15_0_8_ppsmc.h
index bf73d10c0ce7..888261c26409 100644
--- a/drivers/gpu/drm/amd/pm/swsmu/inc/pmfw_if/smu_v15_0_8_ppsmc.h
+++ b/drivers/gpu/drm/amd/pm/swsmu/inc/pmfw_if/smu_v15_0_8_ppsmc.h
@@ -85,7 +85,8 @@
#define PPSMC_MSG_SetSoftMaxFclk 0x34
/* NPM limit setter; NPM reads are served from the SystemMetricsTable. */
#define PPSMC_MSG_SetNpmLimit 0x40
-#define PPSMC_Message_Count 0x41
+#define PPSMC_MSG_PrepareNodeForUnload 0x41
+#define PPSMC_Message_Count 0x42
/* PSMC Reset Types for driver msg argument */
#define PPSMC_RESET_TYPE_DRIVER_MODE_1_RESET 0x1
diff --git a/drivers/gpu/drm/amd/pm/swsmu/inc/smu_types.h
b/drivers/gpu/drm/amd/pm/swsmu/inc/smu_types.h
index f86201764814..31b4ef025351 100644
--- a/drivers/gpu/drm/amd/pm/swsmu/inc/smu_types.h
+++ b/drivers/gpu/drm/amd/pm/swsmu/inc/smu_types.h
@@ -306,7 +306,8 @@
__SMU_DUMMY_MAP(SetSoftMaxGl2clk), \
__SMU_DUMMY_MAP(SetSoftMinGl2clk), \
__SMU_DUMMY_MAP(GetSystemMetricsVersion), \
- __SMU_DUMMY_MAP(SetNpmLimit),
+ __SMU_DUMMY_MAP(SetNpmLimit), \
+ __SMU_DUMMY_MAP(PrepareNodeForUnload),
#undef __SMU_DUMMY_MAP
#define __SMU_DUMMY_MAP(type) SMU_MSG_##type
diff --git a/drivers/gpu/drm/amd/pm/swsmu/inc/smu_v15_0.h
b/drivers/gpu/drm/amd/pm/swsmu/inc/smu_v15_0.h
index 0c97bee2c4bb..f443000ba657 100644
--- a/drivers/gpu/drm/amd/pm/swsmu/inc/smu_v15_0.h
+++ b/drivers/gpu/drm/amd/pm/swsmu/inc/smu_v15_0.h
@@ -89,6 +89,7 @@ struct smu_15_0_dpm_context {
uint32_t workload_policy_mask;
uint32_t dcef_min_ds_clk;
uint64_t caps;
+ bool node_unload;
uint32_t board_volt;
};
diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu15/smu_v15_0_8_ppt.c
b/drivers/gpu/drm/amd/pm/swsmu/smu15/smu_v15_0_8_ppt.c
index e7213f3ebf63..82c2a379ba4b 100644
--- a/drivers/gpu/drm/amd/pm/swsmu/smu15/smu_v15_0_8_ppt.c
+++ b/drivers/gpu/drm/amd/pm/swsmu/smu15/smu_v15_0_8_ppt.c
@@ -25,6 +25,7 @@
#include <linux/firmware.h>
#include "amdgpu.h"
+#include "amdgpu_xgmi.h"
#include "amdgpu_smu.h"
#include "smu_v15_0_8_pmfw.h"
#include "smu15_driver_if_v15_0_8.h"
@@ -138,6 +139,7 @@ static const struct cmn2asic_msg_mapping
smu_v15_0_8_message_map[SMU_MSG_MAX_COU
MSG_MAP(SetSoftMinFclk, PPSMC_MSG_SetSoftMinFclk,
0),
MSG_MAP(SetSoftMaxFclk, PPSMC_MSG_SetSoftMaxFclk,
0),
MSG_MAP(SetNpmLimit, PPSMC_MSG_SetNpmLimit,
0),
+ MSG_MAP(PrepareNodeForUnload,
PPSMC_MSG_PrepareNodeForUnload, 0),
};
/* TODO: Update the clk map once enum PPCLK is updated in
smu15_driver_if_v15_0_8.h */
@@ -635,9 +637,22 @@ static void smu_v15_0_8_init_npm_cap(struct smu_context
*smu)
smu_v15_0_8_cap_set(smu, SMU_15_0_8_CAP_NPM);
}
+static void smu_v15_0_8_init_node_unload_cap(struct smu_context *smu)
+{
+ uint32_t fw_ver = smu->smc_fw_version;
+ uint32_t pgm = (fw_ver >> 24) & 0xFF;
+
+ if (smu_v15_0_8_cap_supported(smu, SMU_15_0_8_CAP_NODE_UNLOAD))
+ return;
+
+ if (pgm == 2 && fw_ver >= SMU_15_0_8_NODE_UNLOAD_MIN_FW_VERSION)
+ smu_v15_0_8_cap_set(smu, SMU_15_0_8_CAP_NODE_UNLOAD);
+}
+
static void smu_v15_0_8_init_caps(struct smu_context *smu)
{
smu_v15_0_8_init_npm_cap(smu);
+ smu_v15_0_8_init_node_unload_cap(smu);
}
static u64 smu_v15_0_8_get_npm_cap(struct smu_context *smu)
@@ -1366,8 +1381,46 @@ static int smu_v15_0_8_register_irq_handler(struct
smu_context *smu)
return ret;
}
+static void smu_v15_0_8_notify_node_unload(struct smu_context *smu)
+{
+ if (!smu_v15_0_8_cap_supported(smu, SMU_15_0_8_CAP_NODE_UNLOAD))
+ return;
+
+ smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_PrepareNodeForUnload, 0,
NULL);
+}
+
+static void smu_v15_0_8_mark_node_unload(struct smu_context *smu)
+{
+ struct amdgpu_device *adev = smu->adev;
+ struct amdgpu_hive_info *hive;
+ struct amdgpu_device *peer;
+ struct smu_context *peer_smu;
+ struct smu_15_0_dpm_context *dpm;
+
+ hive = amdgpu_get_xgmi_hive(adev);
+ if (!hive) {
+ dpm = smu->smu_dpm.dpm_context;
+ if (dpm)
+ dpm->node_unload = true;
+ return;
+ }
+
+ list_for_each_entry(peer, &hive->device_list, gmc.xgmi.head) {
+ peer_smu = peer->powerplay.pp_handle;
+ if (!peer_smu)
+ continue;
+ dpm = peer_smu->smu_dpm.dpm_context;
+ if (dpm)
+ dpm->node_unload = true;
+ }
+
+ amdgpu_put_xgmi_hive(hive);
+}
+
static int smu_v15_0_8_notify_unload(struct smu_context *smu)
{
+ struct smu_context *primary_smu;
+ struct smu_15_0_dpm_context *dpm = smu->smu_dpm.dpm_context;
struct smu_msg_ctl *ctl = &smu->msg_ctl;
struct smu_msg_args args = {
.msg = SMU_MSG_PrepareMp1ForUnload,
@@ -1377,6 +1430,13 @@ static int smu_v15_0_8_notify_unload(struct smu_context
*smu)
if (amdgpu_in_reset(smu->adev))
return 0;
+ if (dpm && !dpm->node_unload) {
+ primary_smu = smu_get_primary_dev(smu);
+ if (primary_smu)
+ smu_v15_0_8_notify_node_unload(primary_smu);
+ smu_v15_0_8_mark_node_unload(smu);
+ }
+
dev_dbg(smu->adev->dev, "Notify PMFW about driver unload");
/* Ignore return, just intimate FW that driver is not going to be there
*/
ctl->ops->send_msg(ctl, &args);
diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu15/smu_v15_0_8_ppt.h
b/drivers/gpu/drm/amd/pm/swsmu/smu15/smu_v15_0_8_ppt.h
index bc0f20e43e0a..dff601bc0f9a 100644
--- a/drivers/gpu/drm/amd/pm/swsmu/smu15/smu_v15_0_8_ppt.h
+++ b/drivers/gpu/drm/amd/pm/swsmu/smu15/smu_v15_0_8_ppt.h
@@ -33,6 +33,8 @@
#define SMU_15_0_8_MAX_MID 2
#define SMU_15_0_8_MAX_HBM_STACKS 12
#define SMU_15_0_8_CAP_NPM 1
+#define SMU_15_0_8_CAP_NODE_UNLOAD 2
+#define SMU_15_0_8_NODE_UNLOAD_MIN_FW_VERSION 0x027d0c00u /* 2.125.12.0 */
extern void smu_v15_0_8_set_ppt_funcs(struct smu_context *smu);
typedef struct {
diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu_cmn.c
b/drivers/gpu/drm/amd/pm/swsmu/smu_cmn.c
index 2bd3ea17e789..ff59bf19c3e7 100644
--- a/drivers/gpu/drm/amd/pm/swsmu/smu_cmn.c
+++ b/drivers/gpu/drm/amd/pm/swsmu/smu_cmn.c
@@ -27,6 +27,32 @@
#include "smu_cmn.h"
#include "soc15_common.h"
+#include "amdgpu_xgmi.h"
+
+struct smu_context *smu_get_primary_dev(struct smu_context *smu)
+{
+ struct amdgpu_device *adev = smu->adev;
+ struct amdgpu_hive_info *hive;
+ struct amdgpu_device *peer;
+
+ if (adev->gmc.xgmi.physical_node_id == 0)
+ return smu;
+
+ hive = amdgpu_get_xgmi_hive(adev);
+ if (!hive)
+ return NULL;
+
+ list_for_each_entry(peer, &hive->device_list, gmc.xgmi.head) {
+ if (peer->gmc.xgmi.physical_node_id == 0) {
+ amdgpu_put_xgmi_hive(hive);
+ return peer->powerplay.pp_handle;
+ }
+ }
+
+ amdgpu_put_xgmi_hive(hive);
+ return NULL;
+}
+
/*
* DO NOT use these for err/warn/info/debug messages.
* Use dev_err, dev_warn, dev_info and dev_dbg instead.
diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu_cmn.h
b/drivers/gpu/drm/amd/pm/swsmu/smu_cmn.h
index ae6742f5298f..6d7f47c934f2 100644
--- a/drivers/gpu/drm/amd/pm/swsmu/smu_cmn.h
+++ b/drivers/gpu/drm/amd/pm/swsmu/smu_cmn.h
@@ -249,6 +249,8 @@ int smu_cmn_dpm_pcie_gen_idx(int gen);
int smu_cmn_dpm_pcie_width_idx(int width);
int smu_cmn_check_fw_version(struct smu_context *smu);
+struct smu_context *smu_get_primary_dev(struct smu_context *smu);
+
int smu_cmn_get_pptable_from_firmware(struct smu_context *smu, void **table,
uint32_t *size, uint32_t pptable_id);
--
2.46.0