drm/amd/powerplay: Add interface to lock SMU HW I2C.
authorAndrey Grodzovsky <andrey.grodzovsky@amd.com>
Wed, 1 May 2019 22:19:48 +0000 (18:19 -0400)
committerAlex Deucher <alexander.deucher@amd.com>
Tue, 27 Aug 2019 13:17:42 +0000 (08:17 -0500)
v2:
PPSMC_MSG_RequestI2CBus seems not to work and so to avoid conflict
over I2C bus and engine disable thermal control access to
force SMU stop using the I2C bus until the issue is reslolved.

Expose and call vega20_is_smc_ram_running to skip locking when SMU
FW is not yet loaded.

v3:
Remove the prevoius hack as the SMU found the bug.

v5: Typo fix

Signed-off-by: Andrey Grodzovsky <andrey.grodzovsky@amd.com>
Reviewed-by: Alex Deucher <alexander.deucher@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
drivers/gpu/drm/amd/include/kgd_pp_interface.h
drivers/gpu/drm/amd/powerplay/amd_powerplay.c
drivers/gpu/drm/amd/powerplay/hwmgr/vega20_hwmgr.c
drivers/gpu/drm/amd/powerplay/inc/hwmgr.h
drivers/gpu/drm/amd/powerplay/smumgr/vega20_smumgr.c
drivers/gpu/drm/amd/powerplay/smumgr/vega20_smumgr.h

index 0de4e37fe7dae9841c430dc0a5e2cbbc44f4dfee..27cf0afaa0b4e63a90c65c0d81ba92fe53fdde95 100644 (file)
@@ -275,6 +275,7 @@ struct amd_pm_funcs {
        int (*set_power_profile_mode)(void *handle, long *input, uint32_t size);
        int (*odn_edit_dpm_table)(void *handle, uint32_t type, long *input, uint32_t size);
        int (*set_mp1_state)(void *handle, enum pp_mp1_state mp1_state);
+       int (*smu_i2c_bus_access)(void *handle, bool acquire);
 /* export to DC */
        u32 (*get_sclk)(void *handle, bool low);
        u32 (*get_mclk)(void *handle, bool low);
index 7ef202761998ef88e12863f2218ff7033b62b23a..fa636cb462c10b54029597b798dd0f84137c8a49 100644 (file)
@@ -1528,6 +1528,21 @@ static int pp_asic_reset_mode_2(void *handle)
        return ret;
 }
 
+static int pp_smu_i2c_bus_access(void *handle, bool acquire)
+{
+       struct pp_hwmgr *hwmgr = handle;
+
+       if (!hwmgr || !hwmgr->pm_en)
+               return -EINVAL;
+
+       if (hwmgr->hwmgr_func->smu_i2c_bus_access == NULL) {
+               pr_info_ratelimited("%s was not implemented.\n", __func__);
+               return -EINVAL;
+       }
+
+       return hwmgr->hwmgr_func->smu_i2c_bus_access(hwmgr, acquire);
+}
+
 static const struct amd_pm_funcs pp_dpm_funcs = {
        .load_firmware = pp_dpm_load_fw,
        .wait_for_fw_loading_complete = pp_dpm_fw_loading_complete,
@@ -1585,4 +1600,5 @@ static const struct amd_pm_funcs pp_dpm_funcs = {
        .get_ppfeature_status = pp_get_ppfeature_status,
        .set_ppfeature_status = pp_set_ppfeature_status,
        .asic_reset_mode_2 = pp_asic_reset_mode_2,
+       .smu_i2c_bus_access = pp_smu_i2c_bus_access,
 };
index 98a6f53059746db8abcfaabbd91bfca26600fb9a..03e8288c3a0da865a8e95fd05484fcda1d1e1790 100644 (file)
@@ -4089,6 +4089,24 @@ static int vega20_get_thermal_temperature_range(struct pp_hwmgr *hwmgr,
        return 0;
 }
 
+static int vega20_smu_i2c_bus_access(struct pp_hwmgr *hwmgr, bool acquire)
+{
+       int res;
+
+       /* I2C bus access can happen very early, when SMU not loaded yet */
+       if (!vega20_is_smc_ram_running(hwmgr))
+               return 0;
+
+       res = smum_send_msg_to_smc_with_parameter(hwmgr,
+                                                 (acquire ?
+                                                 PPSMC_MSG_RequestI2CBus :
+                                                 PPSMC_MSG_ReleaseI2CBus),
+                                                 0);
+
+       PP_ASSERT_WITH_CODE(!res, "[SmuI2CAccessBus] Failed to access bus!", return res);
+       return res;
+}
+
 static const struct pp_hwmgr_func vega20_hwmgr_funcs = {
        /* init/fini related */
        .backend_init = vega20_hwmgr_backend_init,
@@ -4156,6 +4174,7 @@ static const struct pp_hwmgr_func vega20_hwmgr_funcs = {
        .get_asic_baco_state = vega20_baco_get_state,
        .set_asic_baco_state = vega20_baco_set_state,
        .set_mp1_state = vega20_set_mp1_state,
+       .smu_i2c_bus_access = vega20_smu_i2c_bus_access,
 };
 
 int vega20_hwmgr_init(struct pp_hwmgr *hwmgr)
index abeff15702778f46c951e9c214b8114930bb1ef8..7bf9a14bfa0becba79a6e9e97a1120bfd637f413 100644 (file)
@@ -354,6 +354,7 @@ struct pp_hwmgr_func {
        int (*set_ppfeature_status)(struct pp_hwmgr *hwmgr, uint64_t ppfeature_masks);
        int (*set_mp1_state)(struct pp_hwmgr *hwmgr, enum pp_mp1_state mp1_state);
        int (*asic_reset)(struct pp_hwmgr *hwmgr, enum SMU_ASIC_RESET_MODE mode);
+       int (*smu_i2c_bus_access)(struct pp_hwmgr *hwmgr, bool aquire);
 };
 
 struct pp_table_func {
index 3e97b83950dcfa8811716bd46aa872ab87bcd3f1..b9089c6bea850463fc3cb04901f80dc27e52916b 100644 (file)
@@ -44,7 +44,7 @@
 #define smnMP0_FW_INTF                 0x30101c0
 #define smnMP1_PUB_CTRL                        0x3010b14
 
-static bool vega20_is_smc_ram_running(struct pp_hwmgr *hwmgr)
+bool vega20_is_smc_ram_running(struct pp_hwmgr *hwmgr)
 {
        struct amdgpu_device *adev = hwmgr->adev;
        uint32_t mp1_fw_flags;
index ec953ab13e87c1e478c8321f32e24b1af35c6f78..62ebbfd6068f3d145811dd9690d64f96c5add265 100644 (file)
@@ -57,5 +57,7 @@ int vega20_get_activity_monitor_coeff(struct pp_hwmgr *hwmgr,
                uint8_t *table, uint16_t workload_type);
 int vega20_set_pptable_driver_address(struct pp_hwmgr *hwmgr);
 
+bool vega20_is_smc_ram_running(struct pp_hwmgr *hwmgr);
+
 #endif