Commit 1689fca0 authored by Evan Quan's avatar Evan Quan Committed by Alex Deucher
Browse files

drm/amd/pm: fix Navi1x runtime resume failure V2



The RLC was put into a wrong state on runtime suspend. Thus the RLC
autoload will fail on the succeeding runtime resume. By adding an
intermediate PPSMC_MSG_PrepareMp1ForUnload(some GC hard reset involved,
designed for PnP), we can bring RLC back into the desired state.

V2: integrate INTERRUPTS_ENABLED flag clearing into current
    mp1 state set routines

Signed-off-by: default avatarEvan Quan <evan.quan@amd.com>
Reviewed-by: default avatarLijo Lazar <lijo.lazar@amd.com>
Reviewed-by: default avatarGuchun Chen <guchun.chen@amd.com>
Signed-off-by: default avatarAlex Deucher <alexander.deucher@amd.com>
parent 50ca2522
Loading
Loading
Loading
Loading
+6 −3
Original line number Diff line number Diff line
@@ -2146,9 +2146,12 @@ static int psp_load_smu_fw(struct psp_context *psp)
	if (!ucode->fw || amdgpu_sriov_vf(psp->adev))
		return 0;


	if (amdgpu_in_reset(adev) && ras && ras->supported &&
		adev->asic_type == CHIP_ARCTURUS) {
	if ((amdgpu_in_reset(adev) &&
	     ras && ras->supported &&
	     adev->asic_type == CHIP_ARCTURUS) ||
	     (adev->in_runpm &&
	      adev->asic_type >= CHIP_NAVI10 &&
	      adev->asic_type <= CHIP_NAVI12)) {
		ret = amdgpu_dpm_set_mp1_state(adev, PP_MP1_STATE_UNLOAD);
		if (ret) {
			DRM_WARN("Failed to set MP1 state prepare for reload\n");
+7 −0
Original line number Diff line number Diff line
@@ -806,6 +806,13 @@ struct pptable_funcs {
	 */
	int (*check_fw_status)(struct smu_context *smu);

	/**
	 * @set_mp1_state: put SMU into a correct state for comming
	 *                 resume from runpm or gpu reset.
	 */
	int (*set_mp1_state)(struct smu_context *smu,
			     enum pp_mp1_state mp1_state);

	/**
	 * @setup_pptable: Initialize the power play table and populate it with
	 *                 default values.
+4 −24
Original line number Diff line number Diff line
@@ -1908,36 +1908,16 @@ int smu_set_mp1_state(void *handle,
		      enum pp_mp1_state mp1_state)
{
	struct smu_context *smu = handle;
	uint16_t msg;
	int ret;
	int ret = 0;

	if (!smu->pm_enabled)
		return -EOPNOTSUPP;

	mutex_lock(&smu->mutex);

	switch (mp1_state) {
	case PP_MP1_STATE_SHUTDOWN:
		msg = SMU_MSG_PrepareMp1ForShutdown;
		break;
	case PP_MP1_STATE_UNLOAD:
		msg = SMU_MSG_PrepareMp1ForUnload;
		break;
	case PP_MP1_STATE_RESET:
		msg = SMU_MSG_PrepareMp1ForReset;
		break;
	case PP_MP1_STATE_NONE:
	default:
		mutex_unlock(&smu->mutex);
		return 0;
	}

	ret = smu_send_smc_msg(smu, msg, NULL);
	/* some asics may not support those messages */
	if (ret == -EINVAL)
		ret = 0;
	if (ret)
		dev_err(smu->adev->dev, "[PrepareMp1] Failed!\n");
	if (smu->ppt_funcs &&
	    smu->ppt_funcs->set_mp1_state)
		ret = smu->ppt_funcs->set_mp1_state(smu, mp1_state);

	mutex_unlock(&smu->mutex);

+1 −0
Original line number Diff line number Diff line
@@ -2365,6 +2365,7 @@ static const struct pptable_funcs arcturus_ppt_funcs = {
	.get_fan_parameters = arcturus_get_fan_parameters,
	.interrupt_work = smu_v11_0_interrupt_work,
	.set_light_sbr = smu_v11_0_set_light_sbr,
	.set_mp1_state = smu_cmn_set_mp1_state,
};

void arcturus_set_ppt_funcs(struct smu_context *smu)
+25 −0
Original line number Diff line number Diff line
@@ -431,6 +431,30 @@ static int navi10_store_powerplay_table(struct smu_context *smu)
	return 0;
}

static int navi10_set_mp1_state(struct smu_context *smu,
				enum pp_mp1_state mp1_state)
{
	struct amdgpu_device *adev = smu->adev;
	uint32_t mp1_fw_flags;
	int ret = 0;

	ret = smu_cmn_set_mp1_state(smu, mp1_state);
	if (ret)
		return ret;

	if (mp1_state == PP_MP1_STATE_UNLOAD) {
		mp1_fw_flags = RREG32_PCIE(MP1_Public |
					   (smnMP1_FIRMWARE_FLAGS & 0xffffffff));

		mp1_fw_flags &= ~MP1_FIRMWARE_FLAGS__INTERRUPTS_ENABLED_MASK;

		WREG32_PCIE(MP1_Public |
			    (smnMP1_FIRMWARE_FLAGS & 0xffffffff), mp1_fw_flags);
	}

	return 0;
}

static int navi10_setup_pptable(struct smu_context *smu)
{
	int ret = 0;
@@ -3031,6 +3055,7 @@ static const struct pptable_funcs navi10_ppt_funcs = {
	.get_fan_parameters = navi10_get_fan_parameters,
	.post_init = navi10_post_smu_init,
	.interrupt_work = smu_v11_0_interrupt_work,
	.set_mp1_state = navi10_set_mp1_state,
};

void navi10_set_ppt_funcs(struct smu_context *smu)
Loading