Commit 8cc438be authored by Kenneth Feng's avatar Kenneth Feng Committed by Alex Deucher
Browse files

drm/amd/pm: correct the workload setting



Correct the workload setting in order not to mix the setting
with the end user. Update the workload mask accordingly.

v2: changes as below:
1. the end user can not erase the workload from driver except default workload.
2. always shows the real highest priority workoad to the end user.
3. the real workload mask is combined with driver workload mask and end user workload mask.

v3: apply this to the other ASICs as well.
v4: simplify the code
v5: refine the code based on the review comments.

Signed-off-by: default avatarKenneth Feng <kenneth.feng@amd.com>
Acked-by: default avatarAlex Deucher <alexander.deucher@amd.com>
Signed-off-by: default avatarAlex Deucher <alexander.deucher@amd.com>
parent e5ad7177
Loading
Loading
Loading
Loading
+35 −14
Original line number Diff line number Diff line
@@ -1261,26 +1261,33 @@ static int smu_sw_init(struct amdgpu_ip_block *ip_block)
	smu->watermarks_bitmap = 0;
	smu->power_profile_mode = PP_SMC_POWER_PROFILE_BOOTUP_DEFAULT;
	smu->default_power_profile_mode = PP_SMC_POWER_PROFILE_BOOTUP_DEFAULT;
	smu->user_dpm_profile.user_workload_mask = 0;

	atomic_set(&smu->smu_power.power_gate.vcn_gated, 1);
	atomic_set(&smu->smu_power.power_gate.jpeg_gated, 1);
	atomic_set(&smu->smu_power.power_gate.vpe_gated, 1);
	atomic_set(&smu->smu_power.power_gate.umsch_mm_gated, 1);

	smu->workload_prority[PP_SMC_POWER_PROFILE_BOOTUP_DEFAULT] = 0;
	smu->workload_prority[PP_SMC_POWER_PROFILE_FULLSCREEN3D] = 1;
	smu->workload_prority[PP_SMC_POWER_PROFILE_POWERSAVING] = 2;
	smu->workload_prority[PP_SMC_POWER_PROFILE_VIDEO] = 3;
	smu->workload_prority[PP_SMC_POWER_PROFILE_VR] = 4;
	smu->workload_prority[PP_SMC_POWER_PROFILE_COMPUTE] = 5;
	smu->workload_prority[PP_SMC_POWER_PROFILE_CUSTOM] = 6;
	smu->workload_priority[PP_SMC_POWER_PROFILE_BOOTUP_DEFAULT] = 0;
	smu->workload_priority[PP_SMC_POWER_PROFILE_FULLSCREEN3D] = 1;
	smu->workload_priority[PP_SMC_POWER_PROFILE_POWERSAVING] = 2;
	smu->workload_priority[PP_SMC_POWER_PROFILE_VIDEO] = 3;
	smu->workload_priority[PP_SMC_POWER_PROFILE_VR] = 4;
	smu->workload_priority[PP_SMC_POWER_PROFILE_COMPUTE] = 5;
	smu->workload_priority[PP_SMC_POWER_PROFILE_CUSTOM] = 6;

	if (smu->is_apu ||
	    !smu_is_workload_profile_available(smu, PP_SMC_POWER_PROFILE_FULLSCREEN3D))
		smu->workload_mask = 1 << smu->workload_prority[PP_SMC_POWER_PROFILE_BOOTUP_DEFAULT];
	else
		smu->workload_mask = 1 << smu->workload_prority[PP_SMC_POWER_PROFILE_FULLSCREEN3D];
	    !smu_is_workload_profile_available(smu, PP_SMC_POWER_PROFILE_FULLSCREEN3D)) {
		smu->driver_workload_mask =
			1 << smu->workload_priority[PP_SMC_POWER_PROFILE_BOOTUP_DEFAULT];
	} else {
		smu->driver_workload_mask =
			1 << smu->workload_priority[PP_SMC_POWER_PROFILE_FULLSCREEN3D];
		smu->default_power_profile_mode = PP_SMC_POWER_PROFILE_FULLSCREEN3D;
	}

	smu->workload_mask = smu->driver_workload_mask |
							smu->user_dpm_profile.user_workload_mask;
	smu->workload_setting[0] = PP_SMC_POWER_PROFILE_BOOTUP_DEFAULT;
	smu->workload_setting[1] = PP_SMC_POWER_PROFILE_FULLSCREEN3D;
	smu->workload_setting[2] = PP_SMC_POWER_PROFILE_POWERSAVING;
@@ -2355,17 +2362,20 @@ static int smu_switch_power_profile(void *handle,
		return -EINVAL;

	if (!en) {
		smu->workload_mask &= ~(1 << smu->workload_prority[type]);
		smu->driver_workload_mask &= ~(1 << smu->workload_priority[type]);
		index = fls(smu->workload_mask);
		index = index > 0 && index <= WORKLOAD_POLICY_MAX ? index - 1 : 0;
		workload[0] = smu->workload_setting[index];
	} else {
		smu->workload_mask |= (1 << smu->workload_prority[type]);
		smu->driver_workload_mask |= (1 << smu->workload_priority[type]);
		index = fls(smu->workload_mask);
		index = index <= WORKLOAD_POLICY_MAX ? index - 1 : 0;
		workload[0] = smu->workload_setting[index];
	}

	smu->workload_mask = smu->driver_workload_mask |
						 smu->user_dpm_profile.user_workload_mask;

	if (smu_dpm_ctx->dpm_level != AMD_DPM_FORCED_LEVEL_MANUAL &&
		smu_dpm_ctx->dpm_level != AMD_DPM_FORCED_LEVEL_PERF_DETERMINISM)
		smu_bump_power_profile_mode(smu, workload, 0);
@@ -3056,12 +3066,23 @@ static int smu_set_power_profile_mode(void *handle,
				      uint32_t param_size)
{
	struct smu_context *smu = handle;
	int ret;

	if (!smu->pm_enabled || !smu->adev->pm.dpm_enabled ||
	    !smu->ppt_funcs->set_power_profile_mode)
		return -EOPNOTSUPP;

	return smu_bump_power_profile_mode(smu, param, param_size);
	if (smu->user_dpm_profile.user_workload_mask &
	   (1 << smu->workload_priority[param[param_size]]))
	   return 0;

	smu->user_dpm_profile.user_workload_mask =
		(1 << smu->workload_priority[param[param_size]]);
	smu->workload_mask = smu->user_dpm_profile.user_workload_mask |
		smu->driver_workload_mask;
	ret = smu_bump_power_profile_mode(smu, param, param_size);

	return ret;
}

static int smu_get_fan_control_mode(void *handle, u32 *fan_mode)
+3 −1
Original line number Diff line number Diff line
@@ -240,6 +240,7 @@ struct smu_user_dpm_profile {
	/* user clock state information */
	uint32_t clk_mask[SMU_CLK_COUNT];
	uint32_t clk_dependency;
	uint32_t user_workload_mask;
};

#define SMU_TABLE_INIT(tables, table_id, s, a, d)	\
@@ -557,7 +558,8 @@ struct smu_context {
	bool disable_uclk_switch;

	uint32_t workload_mask;
	uint32_t workload_prority[WORKLOAD_POLICY_MAX];
	uint32_t driver_workload_mask;
	uint32_t workload_priority[WORKLOAD_POLICY_MAX];
	uint32_t workload_setting[WORKLOAD_POLICY_MAX];
	uint32_t power_profile_mode;
	uint32_t default_power_profile_mode;
+2 −3
Original line number Diff line number Diff line
@@ -1455,7 +1455,6 @@ static int arcturus_set_power_profile_mode(struct smu_context *smu,
		return -EINVAL;
	}


	if ((profile_mode == PP_SMC_POWER_PROFILE_CUSTOM) &&
	     (smu->smc_fw_version >= 0x360d00)) {
		if (size != 10)
@@ -1523,14 +1522,14 @@ static int arcturus_set_power_profile_mode(struct smu_context *smu,

	ret = smu_cmn_send_smc_msg_with_param(smu,
					  SMU_MSG_SetWorkloadMask,
					  1 << workload_type,
					  smu->workload_mask,
					  NULL);
	if (ret) {
		dev_err(smu->adev->dev, "Fail to set workload type %d\n", workload_type);
		return ret;
	}

	smu->power_profile_mode = profile_mode;
	smu_cmn_assign_power_profile(smu);

	return 0;
}
+4 −1
Original line number Diff line number Diff line
@@ -2083,10 +2083,13 @@ static int navi10_set_power_profile_mode(struct smu_context *smu, long *input, u
						       smu->power_profile_mode);
	if (workload_type < 0)
		return -EINVAL;

	ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_SetWorkloadMask,
				    1 << workload_type, NULL);
				    smu->workload_mask, NULL);
	if (ret)
		dev_err(smu->adev->dev, "[%s] Failed to set work load mask!", __func__);
	else
		smu_cmn_assign_power_profile(smu);

	return ret;
}
+4 −1
Original line number Diff line number Diff line
@@ -1788,10 +1788,13 @@ static int sienna_cichlid_set_power_profile_mode(struct smu_context *smu, long *
						       smu->power_profile_mode);
	if (workload_type < 0)
		return -EINVAL;

	ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_SetWorkloadMask,
				    1 << workload_type, NULL);
				    smu->workload_mask, NULL);
	if (ret)
		dev_err(smu->adev->dev, "[%s] Failed to set work load mask!", __func__);
	else
		smu_cmn_assign_power_profile(smu);

	return ret;
}
Loading