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

Reply via email to