Commit 1cf8c930 authored by Evan Quan's avatar Evan Quan Committed by Alex Deucher
Browse files

drm/amd/powerplay: fix navi10 system intermittent reboot issue V2



This workaround is needed only for Navi10 12 Gbps SKUs.

V2: added SMU firmware version guard

Signed-off-by: default avatarEvan Quan <evan.quan@amd.com>
Reviewed-by: default avatarFeifei Xu <Feifei.Xu@amd.com>
Signed-off-by: default avatarAlex Deucher <alexander.deucher@amd.com>
Cc: stable@vger.kernel.org
parent f38abc15
Loading
Loading
Loading
Loading
+18 −0
Original line number Diff line number Diff line
@@ -21,6 +21,7 @@
 */

#include <linux/firmware.h>
#include <linux/pci.h>

#include "pp_debug.h"
#include "amdgpu.h"
@@ -1137,6 +1138,23 @@ static int smu_smc_table_hw_init(struct smu_context *smu,
		ret = smu_system_features_control(smu, true);
		if (ret)
			return ret;

		if (adev->asic_type == CHIP_NAVI10) {
			if ((adev->pdev->device == 0x731f && (adev->pdev->revision == 0xc2 ||
							      adev->pdev->revision == 0xc3 ||
							      adev->pdev->revision == 0xca ||
							      adev->pdev->revision == 0xcb)) ||
			    (adev->pdev->device == 0x66af && (adev->pdev->revision == 0xf3 ||
							      adev->pdev->revision == 0xf4 ||
							      adev->pdev->revision == 0xf5 ||
							      adev->pdev->revision == 0xf6))) {
				ret = smu_disable_umc_cdr_12gbps_workaround(smu);
				if (ret) {
					pr_err("Workaround failed to disable UMC CDR feature on 12Gbps SKU!\n");
					return ret;
				}
			}
		}
	}
	if (adev->asic_type != CHIP_ARCTURUS) {
		ret = smu_notify_display_change(smu);
+1 −0
Original line number Diff line number Diff line
@@ -565,6 +565,7 @@ struct pptable_funcs {
	int (*set_soft_freq_limited_range)(struct smu_context *smu, enum smu_clk_type clk_type, uint32_t min, uint32_t max);
	int (*override_pcie_parameters)(struct smu_context *smu);
	uint32_t (*get_pptable_power_limit)(struct smu_context *smu);
	int (*disable_umc_cdr_12gbps_workaround)(struct smu_context *smu);
};

int smu_load_microcode(struct smu_context *smu);
+2 −0
Original line number Diff line number Diff line
@@ -170,6 +170,8 @@
	__SMU_DUMMY_MAP(SetSoftMinJpeg),              \
	__SMU_DUMMY_MAP(SetHardMinFclkByFreq),        \
	__SMU_DUMMY_MAP(DFCstateControl), \
	__SMU_DUMMY_MAP(DAL_DISABLE_DUMMY_PSTATE_CHANGE), \
	__SMU_DUMMY_MAP(DAL_ENABLE_DUMMY_PSTATE_CHANGE), \

#undef __SMU_DUMMY_MAP
#define __SMU_DUMMY_MAP(type)	SMU_MSG_##type
+4 −1
Original line number Diff line number Diff line
@@ -120,7 +120,10 @@
#define PPSMC_MSG_GetVoltageByDpmOverdrive       0x45
#define PPSMC_MSG_BacoAudioD3PME                 0x48

#define PPSMC_Message_Count                      0x49
#define PPSMC_MSG_DALDisableDummyPstateChange    0x49
#define PPSMC_MSG_DALEnableDummyPstateChange     0x4A

#define PPSMC_Message_Count                      0x4B

typedef uint32_t PPSMC_Result;
typedef uint32_t PPSMC_Msg;
+58 −0
Original line number Diff line number Diff line
@@ -119,6 +119,8 @@ static struct smu_11_0_cmn2aisc_mapping navi10_message_map[SMU_MSG_MAX_COUNT] =
	MSG_MAP(PowerDownJpeg,		PPSMC_MSG_PowerDownJpeg),
	MSG_MAP(BacoAudioD3PME,		PPSMC_MSG_BacoAudioD3PME),
	MSG_MAP(ArmD3,			PPSMC_MSG_ArmD3),
	MSG_MAP(DAL_DISABLE_DUMMY_PSTATE_CHANGE,PPSMC_MSG_DALDisableDummyPstateChange),
	MSG_MAP(DAL_ENABLE_DUMMY_PSTATE_CHANGE,	PPSMC_MSG_DALEnableDummyPstateChange),
};

static struct smu_11_0_cmn2aisc_mapping navi10_clk_map[SMU_CLK_COUNT] = {
@@ -2093,6 +2095,61 @@ static int navi10_run_btc(struct smu_context *smu)
	return ret;
}

static int navi10_dummy_pstate_control(struct smu_context *smu, bool enable)
{
	int result = 0;

	if (!enable)
		result = smu_send_smc_msg(smu, SMU_MSG_DAL_DISABLE_DUMMY_PSTATE_CHANGE);
	else
		result = smu_send_smc_msg(smu, SMU_MSG_DAL_ENABLE_DUMMY_PSTATE_CHANGE);

	return result;
}

static int navi10_disable_umc_cdr_12gbps_workaround(struct smu_context *smu)
{
	uint32_t uclk_count, uclk_min, uclk_max;
	uint32_t smu_version;
	int ret = 0;

	ret = smu_get_smc_version(smu, NULL, &smu_version);
	if (ret)
		return ret;

	/* This workaround is available only for 42.50 or later SMC firmwares */
	if (smu_version < 0x2A3200)
		return 0;

	ret = smu_get_dpm_level_count(smu, SMU_UCLK, &uclk_count);
	if (ret)
		return ret;

	ret = smu_get_dpm_freq_by_index(smu, SMU_UCLK, (uint16_t)0, &uclk_min);
	if (ret)
		return ret;

	ret = smu_get_dpm_freq_by_index(smu, SMU_UCLK, (uint16_t)(uclk_count - 1), &uclk_max);
	if (ret)
		return ret;

	/* Force UCLK out of the highest DPM */
	ret = smu_set_hard_freq_range(smu, SMU_UCLK, 0, uclk_min);
	if (ret)
		return ret;

	/* Revert the UCLK Hardmax */
	ret = smu_set_hard_freq_range(smu, SMU_UCLK, 0, uclk_max);
	if (ret)
		return ret;

	/*
	 * In this case, SMU already disabled dummy pstate during enablement
	 * of UCLK DPM, we have to re-enabled it.
	 * */
	return navi10_dummy_pstate_control(smu, true);
}

static const struct pptable_funcs navi10_ppt_funcs = {
	.tables_init = navi10_tables_init,
	.alloc_dpm_context = navi10_allocate_dpm_context,
@@ -2187,6 +2244,7 @@ static const struct pptable_funcs navi10_ppt_funcs = {
	.od_edit_dpm_table = navi10_od_edit_dpm_table,
	.get_pptable_power_limit = navi10_get_pptable_power_limit,
	.run_btc = navi10_run_btc,
	.disable_umc_cdr_12gbps_workaround = navi10_disable_umc_cdr_12gbps_workaround,
};

void navi10_set_ppt_funcs(struct smu_context *smu)
Loading