Commit 9530273e authored by Evan Quan's avatar Evan Quan Committed by Alex Deucher
Browse files

drm/amd/powerplay: cover the powerplay implementation details V3



This can save users much troubles. As they do not
actually need to care whether swSMU or traditional
powerplay routine should be used.

V2: apply the fixes to vi.c and cik.c also
V3: squash in oops fix

Signed-off-by: default avatarEvan Quan <evan.quan@amd.com>
Reviewed-by: default avatarAlex Deucher <alexander.deucher@amd.com>
Signed-off-by: default avatarAlex Deucher <alexander.deucher@amd.com>
parent a434b94c
Loading
Loading
Loading
Loading
+3 −9
Original line number Diff line number Diff line
@@ -613,12 +613,6 @@ void amdgpu_amdkfd_set_compute_idle(struct kgd_dev *kgd, bool idle)
{
	struct amdgpu_device *adev = (struct amdgpu_device *)kgd;

	if (is_support_sw_smu(adev))
		smu_switch_power_profile(&adev->smu,
					 PP_SMC_POWER_PROFILE_COMPUTE,
					 !idle);
	else if (adev->powerplay.pp_funcs &&
		 adev->powerplay.pp_funcs->switch_power_profile)
	amdgpu_dpm_switch_power_profile(adev,
					PP_SMC_POWER_PROFILE_COMPUTE,
					!idle);
+6 −47
Original line number Diff line number Diff line
@@ -2345,14 +2345,7 @@ static int amdgpu_device_ip_suspend_phase2(struct amdgpu_device *adev)
		adev->ip_blocks[i].status.hw = false;
		/* handle putting the SMC in the appropriate state */
		if (adev->ip_blocks[i].version->type == AMD_IP_BLOCK_TYPE_SMC) {
			if (is_support_sw_smu(adev)) {
				r = smu_set_mp1_state(&adev->smu, adev->mp1_state);
			} else if (adev->powerplay.pp_funcs &&
					   adev->powerplay.pp_funcs->set_mp1_state) {
				r = adev->powerplay.pp_funcs->set_mp1_state(
					adev->powerplay.pp_handle,
					adev->mp1_state);
			}
			r = amdgpu_dpm_set_mp1_state(adev, adev->mp1_state);
			if (r) {
				DRM_ERROR("SMC failed to set mp1 state %d, %d\n",
					  adev->mp1_state, r);
@@ -4359,56 +4352,22 @@ int amdgpu_device_baco_enter(struct drm_device *dev)
	if (ras && ras->supported)
		adev->nbio.funcs->enable_doorbell_interrupt(adev, false);

	if (is_support_sw_smu(adev)) {
		struct smu_context *smu = &adev->smu;
		int ret;

		ret = smu_baco_enter(smu);
		if (ret)
			return ret;
	} else {
		void *pp_handle = adev->powerplay.pp_handle;
		const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs;

		if (!pp_funcs ||!pp_funcs->get_asic_baco_state ||!pp_funcs->set_asic_baco_state)
			return -ENOENT;

		/* enter BACO state */
		if (pp_funcs->set_asic_baco_state(pp_handle, 1))
			return -EIO;
	}

	return 0;
	return amdgpu_dpm_baco_enter(adev);
}

int amdgpu_device_baco_exit(struct drm_device *dev)
{
	struct amdgpu_device *adev = dev->dev_private;
	struct amdgpu_ras *ras = amdgpu_ras_get_context(adev);
	int ret = 0;

	if (!amdgpu_device_supports_baco(adev->ddev))
		return -ENOTSUPP;

	if (is_support_sw_smu(adev)) {
		struct smu_context *smu = &adev->smu;
		int ret;

		ret = smu_baco_exit(smu);
	ret = amdgpu_dpm_baco_exit(adev);
	if (ret)
		return ret;

	} else {
		void *pp_handle = adev->powerplay.pp_handle;
		const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs;

		if (!pp_funcs ||!pp_funcs->get_asic_baco_state ||!pp_funcs->set_asic_baco_state)
			return -ENOENT;

		/* exit BACO state */
		if (pp_funcs->set_asic_baco_state(pp_handle, 0))
			return -EIO;
	}

	if (ras && ras->supported)
		adev->nbio.funcs->enable_doorbell_interrupt(adev, true);

+160 −0
Original line number Diff line number Diff line
@@ -983,3 +983,163 @@ int amdgpu_dpm_set_powergating_by_smu(struct amdgpu_device *adev, uint32_t block

	return ret;
}

int amdgpu_dpm_baco_enter(struct amdgpu_device *adev)
{
	const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs;
	void *pp_handle = adev->powerplay.pp_handle;
	struct smu_context *smu = &adev->smu;
	int ret = 0;

	if (is_support_sw_smu(adev)) {
		ret = smu_baco_enter(smu);
	} else {
		if (!pp_funcs || !pp_funcs->set_asic_baco_state)
			return -ENOENT;

		/* enter BACO state */
		ret = pp_funcs->set_asic_baco_state(pp_handle, 1);
	}

	return ret;
}

int amdgpu_dpm_baco_exit(struct amdgpu_device *adev)
{
	const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs;
	void *pp_handle = adev->powerplay.pp_handle;
	struct smu_context *smu = &adev->smu;
	int ret = 0;

	if (is_support_sw_smu(adev)) {
		ret = smu_baco_exit(smu);
	} else {
		if (!pp_funcs || !pp_funcs->set_asic_baco_state)
			return -ENOENT;

		/* exit BACO state */
		ret = pp_funcs->set_asic_baco_state(pp_handle, 0);
	}

	return ret;
}

int amdgpu_dpm_set_mp1_state(struct amdgpu_device *adev,
			     enum pp_mp1_state mp1_state)
{
	int ret = 0;

	if (is_support_sw_smu(adev)) {
		ret = smu_set_mp1_state(&adev->smu, mp1_state);
	} else if (adev->powerplay.pp_funcs &&
		   adev->powerplay.pp_funcs->set_mp1_state) {
		ret = adev->powerplay.pp_funcs->set_mp1_state(
				adev->powerplay.pp_handle,
				mp1_state);
	}

	return ret;
}

bool amdgpu_dpm_is_baco_supported(struct amdgpu_device *adev)
{
	const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs;
	void *pp_handle = adev->powerplay.pp_handle;
	struct smu_context *smu = &adev->smu;
	bool baco_cap;

	if (is_support_sw_smu(adev)) {
		return smu_baco_is_support(smu);
	} else {
		if (!pp_funcs || !pp_funcs->get_asic_baco_capability)
			return false;

		if (pp_funcs->get_asic_baco_capability(pp_handle, &baco_cap))
			return false;

		return baco_cap ? true : false;
	}
}

int amdgpu_dpm_mode2_reset(struct amdgpu_device *adev)
{
	const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs;
	void *pp_handle = adev->powerplay.pp_handle;
	struct smu_context *smu = &adev->smu;

	if (is_support_sw_smu(adev)) {
		return smu_mode2_reset(smu);
	} else {
		if (!pp_funcs || !pp_funcs->asic_reset_mode_2)
			return -ENOENT;

		return pp_funcs->asic_reset_mode_2(pp_handle);
	}
}

int amdgpu_dpm_baco_reset(struct amdgpu_device *adev)
{
	const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs;
	void *pp_handle = adev->powerplay.pp_handle;
	struct smu_context *smu = &adev->smu;
	int ret = 0;

	dev_info(adev->dev, "GPU BACO reset\n");

	if (is_support_sw_smu(adev)) {
		ret = smu_baco_enter(smu);
		if (ret)
			return ret;

		ret = smu_baco_exit(smu);
		if (ret)
			return ret;
	} else {
		if (!pp_funcs
		    || !pp_funcs->set_asic_baco_state)
			return -ENOENT;

		/* enter BACO state */
		ret = pp_funcs->set_asic_baco_state(pp_handle, 1);
		if (ret)
			return ret;

		/* exit BACO state */
		ret = pp_funcs->set_asic_baco_state(pp_handle, 0);
		if (ret)
			return ret;
	}

	return 0;
}

int amdgpu_dpm_switch_power_profile(struct amdgpu_device *adev,
				    enum PP_SMC_POWER_PROFILE type,
				    bool en)
{
	int ret = 0;

	if (is_support_sw_smu(adev))
		ret = smu_switch_power_profile(&adev->smu, type, en);
	else if (adev->powerplay.pp_funcs &&
		 adev->powerplay.pp_funcs->switch_power_profile)
		ret = adev->powerplay.pp_funcs->switch_power_profile(
			adev->powerplay.pp_handle, type, en);

	return ret;
}

int amdgpu_dpm_set_xgmi_pstate(struct amdgpu_device *adev,
			       uint32_t pstate)
{
	int ret = 0;

	if (is_support_sw_smu_xgmi(adev))
		ret = smu_set_xgmi_pstate(&adev->smu, pstate);
	else if (adev->powerplay.pp_funcs &&
		 adev->powerplay.pp_funcs->set_xgmi_pstate)
		ret = adev->powerplay.pp_funcs->set_xgmi_pstate(adev->powerplay.pp_handle,
								pstate);

	return ret;
}
+20 −4
Original line number Diff line number Diff line
@@ -341,10 +341,6 @@ enum amdgpu_pcie_gen {
		((adev)->powerplay.pp_funcs->reset_power_profile_state(\
			(adev)->powerplay.pp_handle, request))

#define amdgpu_dpm_switch_power_profile(adev, type, en) \
		((adev)->powerplay.pp_funcs->switch_power_profile(\
			(adev)->powerplay.pp_handle, type, en))

#define amdgpu_dpm_set_clockgating_by_smu(adev, msg_id) \
		((adev)->powerplay.pp_funcs->set_clockgating_by_smu(\
			(adev)->powerplay.pp_handle, msg_id))
@@ -517,4 +513,24 @@ extern int amdgpu_dpm_get_sclk(struct amdgpu_device *adev, bool low);

extern int amdgpu_dpm_get_mclk(struct amdgpu_device *adev, bool low);

int amdgpu_dpm_set_xgmi_pstate(struct amdgpu_device *adev,
			       uint32_t pstate);

int amdgpu_dpm_switch_power_profile(struct amdgpu_device *adev,
				    enum PP_SMC_POWER_PROFILE type,
				    bool en);

int amdgpu_dpm_baco_reset(struct amdgpu_device *adev);

int amdgpu_dpm_mode2_reset(struct amdgpu_device *adev);

bool amdgpu_dpm_is_baco_supported(struct amdgpu_device *adev);

int amdgpu_dpm_set_mp1_state(struct amdgpu_device *adev,
			     enum pp_mp1_state mp1_state);

int amdgpu_dpm_baco_exit(struct amdgpu_device *adev);

int amdgpu_dpm_baco_enter(struct amdgpu_device *adev);

#endif
+0 −6
Original line number Diff line number Diff line
@@ -543,12 +543,6 @@ void amdgpu_gfx_off_ctrl(struct amdgpu_device *adev, bool enable)
	if (!(adev->pm.pp_feature & PP_GFXOFF_MASK))
		return;

	if (!is_support_sw_smu(adev) &&
	    (!adev->powerplay.pp_funcs ||
	     !adev->powerplay.pp_funcs->set_powergating_by_smu))
		return;


	mutex_lock(&adev->gfx.gfx_off_mutex);

	if (!enable)
Loading