Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit ed1e8777 authored by Dave Airlie's avatar Dave Airlie
Browse files

Merge branch 'drm-next-3.19' of git://people.freedesktop.org/~agd5f/linux into drm-next

- More CI dpm fixes
- Initial DPM fan control for SI/CI (disabled by default)
- GPUVM multi-ring efficiency improvements
- Some cursor fixes

* 'drm-next-3.19' of git://people.freedesktop.org/~agd5f/linux: (22 commits)
  drm/radeon: update the VM after setting BO address v4
  drm/radeon: sync PT updates as shared v2
  drm/radeon: sync PD updates as shared
  drm/radeon: fence BO_VAs manually
  drm/radeon: use one VMID for each ring
  drm/radeon: track VM update fences separately
  drm/radeon: fence PT updates manually v2
  drm/radeon: split semaphore and sync object handling v2
  drm/radeon: remove unnecessary VM syncs
  drm/radeon: stop re-reserving the BO in radeon_vm_bo_set_addr
  drm/radeon: rework vm_flush parameters
  drm/radeon/ci: disable needless sclk changes
  drm/radeon/ci: force pcie level before sclk and mclk
  drm/radeon/ci: use different smc command for pcie dpm
  drm/radeon/ci: apply disp voltage changes before clk changes
  drm/radeon: fix PCC debugging message for CI DPM
  drm/radeon/dpm: add thermal dpm support for CI
  drm/radeon/dpm: add smc fan control for CI (v2)
  drm/radeon/dpm: add smc fan control for SI (v2)
  drm/radeon: work around a hw bug in MGCG on CIK
  ...
parents a3a1a667 2f2624c2
Loading
Loading
Loading
Loading
+2 −1
Original line number Diff line number Diff line
@@ -80,7 +80,8 @@ radeon-y += radeon_device.o radeon_asic.o radeon_kms.o \
	r600_dpm.o rs780_dpm.o rv6xx_dpm.o rv770_dpm.o rv730_dpm.o rv740_dpm.o \
	rv770_smc.o cypress_dpm.o btc_dpm.o sumo_dpm.o sumo_smc.o trinity_dpm.o \
	trinity_smc.o ni_dpm.o si_smc.o si_dpm.o kv_smc.o kv_dpm.o ci_smc.o \
	ci_dpm.o dce6_afmt.o radeon_vm.o radeon_ucode.o radeon_ib.o radeon_mn.o
	ci_dpm.o dce6_afmt.o radeon_vm.o radeon_ucode.o radeon_ib.o radeon_mn.o \
	radeon_sync.o

# add async DMA block
radeon-y += \
+402 −24
Original line number Diff line number Diff line
@@ -184,6 +184,9 @@ static int ci_set_overdrive_target_tdp(struct radeon_device *rdev,
				       u32 target_tdp);
static int ci_update_uvd_dpm(struct radeon_device *rdev, bool gate);

static PPSMC_Result ci_send_msg_to_smc_with_parameter(struct radeon_device *rdev,
						      PPSMC_Msg msg, u32 parameter);

static struct ci_power_info *ci_get_pi(struct radeon_device *rdev)
{
        struct ci_power_info *pi = rdev->pm.dpm.priv;
@@ -355,6 +358,21 @@ static int ci_populate_dw8(struct radeon_device *rdev)
	return 0;
}

static int ci_populate_fuzzy_fan(struct radeon_device *rdev)
{
	struct ci_power_info *pi = ci_get_pi(rdev);

	if ((rdev->pm.dpm.fan.fan_output_sensitivity & (1 << 15)) ||
	    (rdev->pm.dpm.fan.fan_output_sensitivity == 0))
		rdev->pm.dpm.fan.fan_output_sensitivity =
			rdev->pm.dpm.fan.default_fan_output_sensitivity;

	pi->smc_powertune_table.FuzzyFan_PwmSetDelta =
		cpu_to_be16(rdev->pm.dpm.fan.fan_output_sensitivity);

	return 0;
}

static int ci_min_max_v_gnbl_pm_lid_from_bapm_vddc(struct radeon_device *rdev)
{
	struct ci_power_info *pi = ci_get_pi(rdev);
@@ -478,6 +496,9 @@ static int ci_populate_pm_base(struct radeon_device *rdev)
		if (ret)
			return ret;
		ret = ci_populate_dw8(rdev);
		if (ret)
			return ret;
		ret = ci_populate_fuzzy_fan(rdev);
		if (ret)
			return ret;
		ret = ci_min_max_v_gnbl_pm_lid_from_bapm_vddc(rdev);
@@ -693,6 +714,25 @@ static int ci_enable_smc_cac(struct radeon_device *rdev, bool enable)
	return ret;
}

static int ci_enable_thermal_based_sclk_dpm(struct radeon_device *rdev,
					    bool enable)
{
	struct ci_power_info *pi = ci_get_pi(rdev);
	PPSMC_Result smc_result = PPSMC_Result_OK;

	if (pi->thermal_sclk_dpm_enabled) {
		if (enable)
			smc_result = ci_send_msg_to_smc(rdev, PPSMC_MSG_ENABLE_THERMAL_DPM);
		else
			smc_result = ci_send_msg_to_smc(rdev, PPSMC_MSG_DISABLE_THERMAL_DPM);
	}

	if (smc_result == PPSMC_Result_OK)
		return 0;
	else
		return -EINVAL;
}

static int ci_power_control_set_level(struct radeon_device *rdev)
{
	struct ci_power_info *pi = ci_get_pi(rdev);
@@ -859,6 +899,7 @@ static int ci_thermal_enable_alert(struct radeon_device *rdev,

	if (enable) {
		thermal_int &= ~(THERM_INT_MASK_HIGH | THERM_INT_MASK_LOW);
		WREG32_SMC(CG_THERMAL_INT, thermal_int);
		rdev->irq.dpm_thermal = false;
		result = ci_send_msg_to_smc(rdev, PPSMC_MSG_Thermal_Cntl_Enable);
		if (result != PPSMC_Result_OK) {
@@ -867,6 +908,7 @@ static int ci_thermal_enable_alert(struct radeon_device *rdev,
		}
	} else {
		thermal_int |= THERM_INT_MASK_HIGH | THERM_INT_MASK_LOW;
		WREG32_SMC(CG_THERMAL_INT, thermal_int);
		rdev->irq.dpm_thermal = true;
		result = ci_send_msg_to_smc(rdev, PPSMC_MSG_Thermal_Cntl_Disable);
		if (result != PPSMC_Result_OK) {
@@ -875,11 +917,324 @@ static int ci_thermal_enable_alert(struct radeon_device *rdev,
		}
	}

	WREG32_SMC(CG_THERMAL_INT, thermal_int);
	return 0;
}

static void ci_fan_ctrl_set_static_mode(struct radeon_device *rdev, u32 mode)
{
	struct ci_power_info *pi = ci_get_pi(rdev);
	u32 tmp;

	if (pi->fan_ctrl_is_in_default_mode) {
		tmp = (RREG32_SMC(CG_FDO_CTRL2) & FDO_PWM_MODE_MASK) >> FDO_PWM_MODE_SHIFT;
		pi->fan_ctrl_default_mode = tmp;
		tmp = (RREG32_SMC(CG_FDO_CTRL2) & TMIN_MASK) >> TMIN_SHIFT;
		pi->t_min = tmp;
		pi->fan_ctrl_is_in_default_mode = false;
	}

	tmp = RREG32_SMC(CG_FDO_CTRL2) & ~TMIN_MASK;
	tmp |= TMIN(0);
	WREG32_SMC(CG_FDO_CTRL2, tmp);

	tmp = RREG32_SMC(CG_FDO_CTRL2) & FDO_PWM_MODE_MASK;
	tmp |= FDO_PWM_MODE(mode);
	WREG32_SMC(CG_FDO_CTRL2, tmp);
}

static int ci_thermal_setup_fan_table(struct radeon_device *rdev)
{
	struct ci_power_info *pi = ci_get_pi(rdev);
	SMU7_Discrete_FanTable fan_table = { FDO_MODE_HARDWARE };
	u32 duty100;
	u32 t_diff1, t_diff2, pwm_diff1, pwm_diff2;
	u16 fdo_min, slope1, slope2;
	u32 reference_clock, tmp;
	int ret;
	u64 tmp64;

	if (!pi->fan_table_start) {
		rdev->pm.dpm.fan.ucode_fan_control = false;
		return 0;
	}

	duty100 = (RREG32_SMC(CG_FDO_CTRL1) & FMAX_DUTY100_MASK) >> FMAX_DUTY100_SHIFT;

	if (duty100 == 0) {
		rdev->pm.dpm.fan.ucode_fan_control = false;
		return 0;
	}

	tmp64 = (u64)rdev->pm.dpm.fan.pwm_min * duty100;
	do_div(tmp64, 10000);
	fdo_min = (u16)tmp64;

	t_diff1 = rdev->pm.dpm.fan.t_med - rdev->pm.dpm.fan.t_min;
	t_diff2 = rdev->pm.dpm.fan.t_high - rdev->pm.dpm.fan.t_med;

	pwm_diff1 = rdev->pm.dpm.fan.pwm_med - rdev->pm.dpm.fan.pwm_min;
	pwm_diff2 = rdev->pm.dpm.fan.pwm_high - rdev->pm.dpm.fan.pwm_med;

	slope1 = (u16)((50 + ((16 * duty100 * pwm_diff1) / t_diff1)) / 100);
	slope2 = (u16)((50 + ((16 * duty100 * pwm_diff2) / t_diff2)) / 100);

	fan_table.TempMin = cpu_to_be16((50 + rdev->pm.dpm.fan.t_min) / 100);
	fan_table.TempMed = cpu_to_be16((50 + rdev->pm.dpm.fan.t_med) / 100);
	fan_table.TempMax = cpu_to_be16((50 + rdev->pm.dpm.fan.t_max) / 100);

	fan_table.Slope1 = cpu_to_be16(slope1);
	fan_table.Slope2 = cpu_to_be16(slope2);

	fan_table.FdoMin = cpu_to_be16(fdo_min);

	fan_table.HystDown = cpu_to_be16(rdev->pm.dpm.fan.t_hyst);

	fan_table.HystUp = cpu_to_be16(1);

	fan_table.HystSlope = cpu_to_be16(1);

	fan_table.TempRespLim = cpu_to_be16(5);

	reference_clock = radeon_get_xclk(rdev);

	fan_table.RefreshPeriod = cpu_to_be32((rdev->pm.dpm.fan.cycle_delay *
					       reference_clock) / 1600);

	fan_table.FdoMax = cpu_to_be16((u16)duty100);

	tmp = (RREG32_SMC(CG_MULT_THERMAL_CTRL) & TEMP_SEL_MASK) >> TEMP_SEL_SHIFT;
	fan_table.TempSrc = (uint8_t)tmp;

	ret = ci_copy_bytes_to_smc(rdev,
				   pi->fan_table_start,
				   (u8 *)(&fan_table),
				   sizeof(fan_table),
				   pi->sram_end);

	if (ret) {
		DRM_ERROR("Failed to load fan table to the SMC.");
		rdev->pm.dpm.fan.ucode_fan_control = false;
	}

	return 0;
}

static int ci_fan_ctrl_start_smc_fan_control(struct radeon_device *rdev)
{
	struct ci_power_info *pi = ci_get_pi(rdev);
	PPSMC_Result ret;

	if (pi->caps_od_fuzzy_fan_control_support) {
		ret = ci_send_msg_to_smc_with_parameter(rdev,
							PPSMC_StartFanControl,
							FAN_CONTROL_FUZZY);
		if (ret != PPSMC_Result_OK)
			return -EINVAL;
		ret = ci_send_msg_to_smc_with_parameter(rdev,
							PPSMC_MSG_SetFanPwmMax,
							rdev->pm.dpm.fan.default_max_fan_pwm);
		if (ret != PPSMC_Result_OK)
			return -EINVAL;
	} else {
		ret = ci_send_msg_to_smc_with_parameter(rdev,
							PPSMC_StartFanControl,
							FAN_CONTROL_TABLE);
		if (ret != PPSMC_Result_OK)
			return -EINVAL;
	}

	return 0;
}

#if 0
static int ci_fan_ctrl_stop_smc_fan_control(struct radeon_device *rdev)
{
	PPSMC_Result ret;

	ret = ci_send_msg_to_smc(rdev, PPSMC_StopFanControl);
	if (ret == PPSMC_Result_OK)
		return 0;
	else
		return -EINVAL;
}

static int ci_fan_ctrl_get_fan_speed_percent(struct radeon_device *rdev,
					     u32 *speed)
{
	u32 duty, duty100;
	u64 tmp64;

	if (rdev->pm.no_fan)
		return -ENOENT;

	duty100 = (RREG32_SMC(CG_FDO_CTRL1) & FMAX_DUTY100_MASK) >> FMAX_DUTY100_SHIFT;
	duty = (RREG32_SMC(CG_THERMAL_STATUS) & FDO_PWM_DUTY_MASK) >> FDO_PWM_DUTY_SHIFT;

	if (duty100 == 0)
		return -EINVAL;

	tmp64 = (u64)duty * 100;
	do_div(tmp64, duty100);
	*speed = (u32)tmp64;

	if (*speed > 100)
		*speed = 100;

	return 0;
}

static int ci_fan_ctrl_set_fan_speed_percent(struct radeon_device *rdev,
					     u32 speed)
{
	u32 tmp;
	u32 duty, duty100;
	u64 tmp64;

	if (rdev->pm.no_fan)
		return -ENOENT;

	if (speed > 100)
		return -EINVAL;

	if (rdev->pm.dpm.fan.ucode_fan_control)
		ci_fan_ctrl_stop_smc_fan_control(rdev);

	duty100 = (RREG32_SMC(CG_FDO_CTRL1) & FMAX_DUTY100_MASK) >> FMAX_DUTY100_SHIFT;

	if (duty100 == 0)
		return -EINVAL;

	tmp64 = (u64)speed * duty100;
	do_div(tmp64, 100);
	duty = (u32)tmp64;

	tmp = RREG32_SMC(CG_FDO_CTRL0) & ~FDO_STATIC_DUTY_MASK;
	tmp |= FDO_STATIC_DUTY(duty);
	WREG32_SMC(CG_FDO_CTRL0, tmp);

	ci_fan_ctrl_set_static_mode(rdev, FDO_PWM_MODE_STATIC);

	return 0;
}

static int ci_fan_ctrl_get_fan_speed_rpm(struct radeon_device *rdev,
					 u32 *speed)
{
	u32 tach_period;
	u32 xclk = radeon_get_xclk(rdev);

	if (rdev->pm.no_fan)
		return -ENOENT;

	if (rdev->pm.fan_pulses_per_revolution == 0)
		return -ENOENT;

	tach_period = (RREG32_SMC(CG_TACH_STATUS) & TACH_PERIOD_MASK) >> TACH_PERIOD_SHIFT;
	if (tach_period == 0)
		return -ENOENT;

	*speed = 60 * xclk * 10000 / tach_period;

	return 0;
}

static int ci_fan_ctrl_set_fan_speed_rpm(struct radeon_device *rdev,
					 u32 speed)
{
	u32 tach_period, tmp;
	u32 xclk = radeon_get_xclk(rdev);

	if (rdev->pm.no_fan)
		return -ENOENT;

	if (rdev->pm.fan_pulses_per_revolution == 0)
		return -ENOENT;

	if ((speed < rdev->pm.fan_min_rpm) ||
	    (speed > rdev->pm.fan_max_rpm))
		return -EINVAL;

	if (rdev->pm.dpm.fan.ucode_fan_control)
		ci_fan_ctrl_stop_smc_fan_control(rdev);

	tach_period = 60 * xclk * 10000 / (8 * speed);
	tmp = RREG32_SMC(CG_TACH_CTRL) & ~TARGET_PERIOD_MASK;
	tmp |= TARGET_PERIOD(tach_period);
	WREG32_SMC(CG_TACH_CTRL, tmp);

	ci_fan_ctrl_set_static_mode(rdev, FDO_PWM_MODE_STATIC);

	return 0;
}
#endif

static void ci_fan_ctrl_set_default_mode(struct radeon_device *rdev)
{
	struct ci_power_info *pi = ci_get_pi(rdev);
	u32 tmp;

	if (!pi->fan_ctrl_is_in_default_mode) {
		tmp = RREG32_SMC(CG_FDO_CTRL2) & ~FDO_PWM_MODE_MASK;
		tmp |= FDO_PWM_MODE(pi->fan_ctrl_default_mode);
		WREG32_SMC(CG_FDO_CTRL2, tmp);

		tmp = RREG32_SMC(CG_FDO_CTRL2) & TMIN_MASK;
		tmp |= TMIN(pi->t_min);
		WREG32_SMC(CG_FDO_CTRL2, tmp);
		pi->fan_ctrl_is_in_default_mode = true;
	}
}

static void ci_thermal_start_smc_fan_control(struct radeon_device *rdev)
{
	if (rdev->pm.dpm.fan.ucode_fan_control) {
		ci_fan_ctrl_start_smc_fan_control(rdev);
		ci_fan_ctrl_set_static_mode(rdev, FDO_PWM_MODE_STATIC);
	}
}

static void ci_thermal_initialize(struct radeon_device *rdev)
{
	u32 tmp;

	if (rdev->pm.fan_pulses_per_revolution) {
		tmp = RREG32_SMC(CG_TACH_CTRL) & ~EDGE_PER_REV_MASK;
		tmp |= EDGE_PER_REV(rdev->pm.fan_pulses_per_revolution -1);
		WREG32_SMC(CG_TACH_CTRL, tmp);
	}

	tmp = RREG32_SMC(CG_FDO_CTRL2) & ~TACH_PWM_RESP_RATE_MASK;
	tmp |= TACH_PWM_RESP_RATE(0x28);
	WREG32_SMC(CG_FDO_CTRL2, tmp);
}

static int ci_thermal_start_thermal_controller(struct radeon_device *rdev)
{
	int ret;

	ci_thermal_initialize(rdev);
	ret = ci_thermal_set_temperature_range(rdev, R600_TEMP_RANGE_MIN, R600_TEMP_RANGE_MAX);
	if (ret)
		return ret;
	ret = ci_thermal_enable_alert(rdev, true);
	if (ret)
		return ret;
	if (rdev->pm.dpm.fan.ucode_fan_control) {
		ret = ci_thermal_setup_fan_table(rdev);
		if (ret)
			return ret;
		ci_thermal_start_smc_fan_control(rdev);
	}

	return 0;
}

static void ci_thermal_stop_thermal_controller(struct radeon_device *rdev)
{
	if (!rdev->pm.no_fan)
		ci_fan_ctrl_set_default_mode(rdev);
}

#if 0
static int ci_read_smc_soft_register(struct radeon_device *rdev,
				     u16 reg_offset, u32 *value)
@@ -3397,6 +3752,8 @@ static int ci_upload_dpm_level_enable_mask(struct radeon_device *rdev)
	struct ci_power_info *pi = ci_get_pi(rdev);
	PPSMC_Result result;

	ci_apply_disp_minimum_voltage_request(rdev);

	if (!pi->sclk_dpm_key_disabled) {
		if (pi->dpm_level_enable_mask.sclk_dpm_enable_mask) {
			result = ci_send_msg_to_smc_with_parameter(rdev,
@@ -3416,7 +3773,7 @@ static int ci_upload_dpm_level_enable_mask(struct radeon_device *rdev)
				return -EINVAL;
		}
	}

#if 0
	if (!pi->pcie_dpm_key_disabled) {
		if (pi->dpm_level_enable_mask.pcie_dpm_enable_mask) {
			result = ci_send_msg_to_smc_with_parameter(rdev,
@@ -3426,9 +3783,7 @@ static int ci_upload_dpm_level_enable_mask(struct radeon_device *rdev)
				return -EINVAL;
		}
	}

	ci_apply_disp_minimum_voltage_request(rdev);

#endif
	return 0;
}

@@ -3454,7 +3809,7 @@ static void ci_find_dpm_states_clocks_in_dpm_table(struct radeon_device *rdev,
		pi->need_update_smu7_dpm_table |= DPMTABLE_OD_UPDATE_SCLK;
	} else {
		/* XXX check display min clock requirements */
		if (0 != CISLAND_MINIMUM_ENGINE_CLOCK)
		if (CISLAND_MINIMUM_ENGINE_CLOCK != CISLAND_MINIMUM_ENGINE_CLOCK)
			pi->need_update_smu7_dpm_table |= DPMTABLE_UPDATE_SCLK;
	}

@@ -3788,57 +4143,57 @@ int ci_dpm_force_performance_level(struct radeon_device *rdev,
	int ret;

	if (level == RADEON_DPM_FORCED_LEVEL_HIGH) {
		if ((!pi->sclk_dpm_key_disabled) &&
		    pi->dpm_level_enable_mask.sclk_dpm_enable_mask) {
		if ((!pi->pcie_dpm_key_disabled) &&
		    pi->dpm_level_enable_mask.pcie_dpm_enable_mask) {
			levels = 0;
			tmp = pi->dpm_level_enable_mask.sclk_dpm_enable_mask;
			tmp = pi->dpm_level_enable_mask.pcie_dpm_enable_mask;
			while (tmp >>= 1)
				levels++;
			if (levels) {
				ret = ci_dpm_force_state_sclk(rdev, levels);
				ret = ci_dpm_force_state_pcie(rdev, level);
				if (ret)
					return ret;
				for (i = 0; i < rdev->usec_timeout; i++) {
					tmp = (RREG32_SMC(TARGET_AND_CURRENT_PROFILE_INDEX) &
					       CURR_SCLK_INDEX_MASK) >> CURR_SCLK_INDEX_SHIFT;
					tmp = (RREG32_SMC(TARGET_AND_CURRENT_PROFILE_INDEX_1) &
					       CURR_PCIE_INDEX_MASK) >> CURR_PCIE_INDEX_SHIFT;
					if (tmp == levels)
						break;
					udelay(1);
				}
			}
		}
		if ((!pi->mclk_dpm_key_disabled) &&
		    pi->dpm_level_enable_mask.mclk_dpm_enable_mask) {
		if ((!pi->sclk_dpm_key_disabled) &&
		    pi->dpm_level_enable_mask.sclk_dpm_enable_mask) {
			levels = 0;
			tmp = pi->dpm_level_enable_mask.mclk_dpm_enable_mask;
			tmp = pi->dpm_level_enable_mask.sclk_dpm_enable_mask;
			while (tmp >>= 1)
				levels++;
			if (levels) {
				ret = ci_dpm_force_state_mclk(rdev, levels);
				ret = ci_dpm_force_state_sclk(rdev, levels);
				if (ret)
					return ret;
				for (i = 0; i < rdev->usec_timeout; i++) {
					tmp = (RREG32_SMC(TARGET_AND_CURRENT_PROFILE_INDEX) &
					       CURR_MCLK_INDEX_MASK) >> CURR_MCLK_INDEX_SHIFT;
					       CURR_SCLK_INDEX_MASK) >> CURR_SCLK_INDEX_SHIFT;
					if (tmp == levels)
						break;
					udelay(1);
				}
			}
		}
		if ((!pi->pcie_dpm_key_disabled) &&
		    pi->dpm_level_enable_mask.pcie_dpm_enable_mask) {
		if ((!pi->mclk_dpm_key_disabled) &&
		    pi->dpm_level_enable_mask.mclk_dpm_enable_mask) {
			levels = 0;
			tmp = pi->dpm_level_enable_mask.pcie_dpm_enable_mask;
			tmp = pi->dpm_level_enable_mask.mclk_dpm_enable_mask;
			while (tmp >>= 1)
				levels++;
			if (levels) {
				ret = ci_dpm_force_state_pcie(rdev, level);
				ret = ci_dpm_force_state_mclk(rdev, levels);
				if (ret)
					return ret;
				for (i = 0; i < rdev->usec_timeout; i++) {
					tmp = (RREG32_SMC(TARGET_AND_CURRENT_PROFILE_INDEX_1) &
					       CURR_PCIE_INDEX_MASK) >> CURR_PCIE_INDEX_SHIFT;
					tmp = (RREG32_SMC(TARGET_AND_CURRENT_PROFILE_INDEX) &
					       CURR_MCLK_INDEX_MASK) >> CURR_MCLK_INDEX_SHIFT;
					if (tmp == levels)
						break;
					udelay(1);
@@ -3892,6 +4247,14 @@ int ci_dpm_force_performance_level(struct radeon_device *rdev,
			}
		}
	} else if (level == RADEON_DPM_FORCED_LEVEL_AUTO) {
		if (!pi->pcie_dpm_key_disabled) {
			PPSMC_Result smc_result;

			smc_result = ci_send_msg_to_smc(rdev,
							PPSMC_MSG_PCIeDPM_UnForceLevel);
			if (smc_result != PPSMC_Result_OK)
				return -EINVAL;
		}
		ret = ci_upload_dpm_level_enable_mask(rdev);
		if (ret)
			return ret;
@@ -4841,6 +5204,14 @@ int ci_dpm_enable(struct radeon_device *rdev)

	ci_enable_auto_throttle_source(rdev, RADEON_DPM_AUTO_THROTTLE_SRC_THERMAL, true);

	ret = ci_enable_thermal_based_sclk_dpm(rdev, true);
	if (ret) {
		DRM_ERROR("ci_enable_thermal_based_sclk_dpm failed\n");
		return ret;
	}

	ci_thermal_start_thermal_controller(rdev);

	ci_update_current_ps(rdev, boot_ps);

	return 0;
@@ -4886,6 +5257,8 @@ void ci_dpm_disable(struct radeon_device *rdev)
	if (!ci_is_smc_running(rdev))
		return;

	ci_thermal_stop_thermal_controller(rdev);

	if (pi->thermal_protection)
		ci_enable_thermal_protection(rdev, false);
	ci_enable_power_containment(rdev, false);
@@ -4900,6 +5273,7 @@ void ci_dpm_disable(struct radeon_device *rdev)
	ci_reset_to_default(rdev);
	ci_dpm_stop_smc(rdev);
	ci_force_switch_to_arb_f0(rdev);
	ci_enable_thermal_based_sclk_dpm(rdev, false);

	ci_update_current_ps(rdev, boot_ps);
}
@@ -5299,6 +5673,7 @@ int ci_dpm_init(struct radeon_device *rdev)
	pi->sclk_dpm_key_disabled = 0;
	pi->mclk_dpm_key_disabled = 0;
	pi->pcie_dpm_key_disabled = 0;
	pi->thermal_sclk_dpm_enabled = 0;

	/* mclk dpm is unstable on some R7 260X cards with the old mc ucode */
	if ((rdev->pdev->device == 0x6658) &&
@@ -5406,7 +5781,7 @@ int ci_dpm_init(struct radeon_device *rdev)
			tmp |= DPM_ENABLED;
			break;
		default:
			DRM_ERROR("Invalid PCC GPIO!");
			DRM_ERROR("Invalid PCC GPIO: %u!\n", gpio.shift);
			break;
		}
		WREG32_SMC(CNB_PWRMGT_CNTL, tmp);
@@ -5473,6 +5848,9 @@ int ci_dpm_init(struct radeon_device *rdev)
		rdev->pm.dpm.dyn_state.max_clock_voltage_on_dc =
			rdev->pm.dpm.dyn_state.max_clock_voltage_on_ac;

	pi->fan_ctrl_is_in_default_mode = true;
	rdev->pm.dpm.fan.ucode_fan_control = false;

	return 0;
}

+6 −0
Original line number Diff line number Diff line
@@ -239,6 +239,7 @@ struct ci_power_info {
	u32 sclk_dpm_key_disabled;
	u32 mclk_dpm_key_disabled;
	u32 pcie_dpm_key_disabled;
	u32 thermal_sclk_dpm_enabled;
	struct ci_pcie_perf_range pcie_gen_performance;
	struct ci_pcie_perf_range pcie_lane_performance;
	struct ci_pcie_perf_range pcie_gen_powersaving;
@@ -266,6 +267,7 @@ struct ci_power_info {
	bool caps_automatic_dc_transition;
	bool caps_sclk_throttle_low_notification;
	bool caps_dynamic_ac_timing;
	bool caps_od_fuzzy_fan_control_support;
	/* flags */
	bool thermal_protection;
	bool pcie_performance_request;
@@ -287,6 +289,10 @@ struct ci_power_info {
	struct ci_ps current_ps;
	struct radeon_ps requested_rps;
	struct ci_ps requested_ps;
	/* fan control */
	bool fan_ctrl_is_in_default_mode;
	u32 t_min;
	u32 fan_ctrl_default_mode;
};

#define CISLANDS_VOLTAGE_CONTROL_NONE                   0x0
+21 −27
Original line number Diff line number Diff line
@@ -3994,31 +3994,27 @@ struct radeon_fence *cik_copy_cpdma(struct radeon_device *rdev,
				    unsigned num_gpu_pages,
				    struct reservation_object *resv)
{
	struct radeon_semaphore *sem = NULL;
	struct radeon_fence *fence;
	struct radeon_sync sync;
	int ring_index = rdev->asic->copy.blit_ring_index;
	struct radeon_ring *ring = &rdev->ring[ring_index];
	u32 size_in_bytes, cur_size_in_bytes, control;
	int i, num_loops;
	int r = 0;

	r = radeon_semaphore_create(rdev, &sem);
	if (r) {
		DRM_ERROR("radeon: moving bo (%d).\n", r);
		return ERR_PTR(r);
	}
	radeon_sync_create(&sync);

	size_in_bytes = (num_gpu_pages << RADEON_GPU_PAGE_SHIFT);
	num_loops = DIV_ROUND_UP(size_in_bytes, 0x1fffff);
	r = radeon_ring_lock(rdev, ring, num_loops * 7 + 18);
	if (r) {
		DRM_ERROR("radeon: moving bo (%d).\n", r);
		radeon_semaphore_free(rdev, &sem, NULL);
		radeon_sync_free(rdev, &sync, NULL);
		return ERR_PTR(r);
	}

	radeon_semaphore_sync_resv(rdev, sem, resv, false);
	radeon_semaphore_sync_rings(rdev, sem, ring->idx);
	radeon_sync_resv(rdev, &sync, resv, false);
	radeon_sync_rings(rdev, &sync, ring->idx);

	for (i = 0; i < num_loops; i++) {
		cur_size_in_bytes = size_in_bytes;
@@ -4042,12 +4038,12 @@ struct radeon_fence *cik_copy_cpdma(struct radeon_device *rdev,
	r = radeon_fence_emit(rdev, &fence, ring->idx);
	if (r) {
		radeon_ring_unlock_undo(rdev, ring);
		radeon_semaphore_free(rdev, &sem, NULL);
		radeon_sync_free(rdev, &sync, NULL);
		return ERR_PTR(r);
	}

	radeon_ring_unlock_commit(rdev, ring, false);
	radeon_semaphore_free(rdev, &sem, fence);
	radeon_sync_free(rdev, &sync, fence);

	return fence;
}
@@ -4070,6 +4066,7 @@ struct radeon_fence *cik_copy_cpdma(struct radeon_device *rdev,
void cik_ring_ib_execute(struct radeon_device *rdev, struct radeon_ib *ib)
{
	struct radeon_ring *ring = &rdev->ring[ib->ring];
	unsigned vm_id = ib->vm ? ib->vm->ids[ib->ring].id : 0;
	u32 header, control = INDIRECT_BUFFER_VALID;

	if (ib->is_const_ib) {
@@ -4098,8 +4095,7 @@ void cik_ring_ib_execute(struct radeon_device *rdev, struct radeon_ib *ib)
		header = PACKET3(PACKET3_INDIRECT_BUFFER, 2);
	}

	control |= ib->length_dw |
		(ib->vm ? (ib->vm->id << 24) : 0);
	control |= ib->length_dw | (vm_id << 24);

	radeon_ring_write(ring, header);
	radeon_ring_write(ring,
@@ -5982,26 +5978,23 @@ static void cik_vm_decode_fault(struct radeon_device *rdev,
 * Update the page table base and flush the VM TLB
 * using the CP (CIK).
 */
void cik_vm_flush(struct radeon_device *rdev, int ridx, struct radeon_vm *vm)
void cik_vm_flush(struct radeon_device *rdev, struct radeon_ring *ring,
		  unsigned vm_id, uint64_t pd_addr)
{
	struct radeon_ring *ring = &rdev->ring[ridx];
	int usepfp = (ridx == RADEON_RING_TYPE_GFX_INDEX);

	if (vm == NULL)
		return;
	int usepfp = (ring->idx == RADEON_RING_TYPE_GFX_INDEX);

	radeon_ring_write(ring, PACKET3(PACKET3_WRITE_DATA, 3));
	radeon_ring_write(ring, (WRITE_DATA_ENGINE_SEL(usepfp) |
				 WRITE_DATA_DST_SEL(0)));
	if (vm->id < 8) {
	if (vm_id < 8) {
		radeon_ring_write(ring,
				  (VM_CONTEXT0_PAGE_TABLE_BASE_ADDR + (vm->id << 2)) >> 2);
				  (VM_CONTEXT0_PAGE_TABLE_BASE_ADDR + (vm_id << 2)) >> 2);
	} else {
		radeon_ring_write(ring,
				  (VM_CONTEXT8_PAGE_TABLE_BASE_ADDR + ((vm->id - 8) << 2)) >> 2);
				  (VM_CONTEXT8_PAGE_TABLE_BASE_ADDR + ((vm_id - 8) << 2)) >> 2);
	}
	radeon_ring_write(ring, 0);
	radeon_ring_write(ring, vm->pd_gpu_addr >> 12);
	radeon_ring_write(ring, pd_addr >> 12);

	/* update SH_MEM_* regs */
	radeon_ring_write(ring, PACKET3(PACKET3_WRITE_DATA, 3));
@@ -6009,7 +6002,7 @@ void cik_vm_flush(struct radeon_device *rdev, int ridx, struct radeon_vm *vm)
				 WRITE_DATA_DST_SEL(0)));
	radeon_ring_write(ring, SRBM_GFX_CNTL >> 2);
	radeon_ring_write(ring, 0);
	radeon_ring_write(ring, VMID(vm->id));
	radeon_ring_write(ring, VMID(vm_id));

	radeon_ring_write(ring, PACKET3(PACKET3_WRITE_DATA, 6));
	radeon_ring_write(ring, (WRITE_DATA_ENGINE_SEL(usepfp) |
@@ -6030,7 +6023,7 @@ void cik_vm_flush(struct radeon_device *rdev, int ridx, struct radeon_vm *vm)
	radeon_ring_write(ring, VMID(0));

	/* HDP flush */
	cik_hdp_flush_cp_ring_emit(rdev, ridx);
	cik_hdp_flush_cp_ring_emit(rdev, ring->idx);

	/* bits 0-15 are the VM contexts0-15 */
	radeon_ring_write(ring, PACKET3(PACKET3_WRITE_DATA, 3));
@@ -6038,7 +6031,7 @@ void cik_vm_flush(struct radeon_device *rdev, int ridx, struct radeon_vm *vm)
				 WRITE_DATA_DST_SEL(0)));
	radeon_ring_write(ring, VM_INVALIDATE_REQUEST >> 2);
	radeon_ring_write(ring, 0);
	radeon_ring_write(ring, 1 << vm->id);
	radeon_ring_write(ring, 1 << vm_id);

	/* compute doesn't have PFP */
	if (usepfp) {
@@ -6344,6 +6337,7 @@ static void cik_enable_mgcg(struct radeon_device *rdev, bool enable)
		}

		orig = data = RREG32(RLC_CGTT_MGCG_OVERRIDE);
		data |= 0x00000001;
		data &= 0xfffffffd;
		if (orig != data)
			WREG32(RLC_CGTT_MGCG_OVERRIDE, data);
@@ -6377,7 +6371,7 @@ static void cik_enable_mgcg(struct radeon_device *rdev, bool enable)
		}
	} else {
		orig = data = RREG32(RLC_CGTT_MGCG_OVERRIDE);
		data |= 0x00000002;
		data |= 0x00000003;
		if (orig != data)
			WREG32(RLC_CGTT_MGCG_OVERRIDE, data);

+17 −25
Original line number Diff line number Diff line
@@ -134,7 +134,7 @@ void cik_sdma_ring_ib_execute(struct radeon_device *rdev,
			      struct radeon_ib *ib)
{
	struct radeon_ring *ring = &rdev->ring[ib->ring];
	u32 extra_bits = (ib->vm ? ib->vm->id : 0) & 0xf;
	u32 extra_bits = (ib->vm ? ib->vm->ids[ib->ring].id : 0) & 0xf;

	if (rdev->wb.enabled) {
		u32 next_rptr = ring->wptr + 5;
@@ -541,31 +541,27 @@ struct radeon_fence *cik_copy_dma(struct radeon_device *rdev,
				  unsigned num_gpu_pages,
				  struct reservation_object *resv)
{
	struct radeon_semaphore *sem = NULL;
	struct radeon_fence *fence;
	struct radeon_sync sync;
	int ring_index = rdev->asic->copy.dma_ring_index;
	struct radeon_ring *ring = &rdev->ring[ring_index];
	u32 size_in_bytes, cur_size_in_bytes;
	int i, num_loops;
	int r = 0;

	r = radeon_semaphore_create(rdev, &sem);
	if (r) {
		DRM_ERROR("radeon: moving bo (%d).\n", r);
		return ERR_PTR(r);
	}
	radeon_sync_create(&sync);

	size_in_bytes = (num_gpu_pages << RADEON_GPU_PAGE_SHIFT);
	num_loops = DIV_ROUND_UP(size_in_bytes, 0x1fffff);
	r = radeon_ring_lock(rdev, ring, num_loops * 7 + 14);
	if (r) {
		DRM_ERROR("radeon: moving bo (%d).\n", r);
		radeon_semaphore_free(rdev, &sem, NULL);
		radeon_sync_free(rdev, &sync, NULL);
		return ERR_PTR(r);
	}

	radeon_semaphore_sync_resv(rdev, sem, resv, false);
	radeon_semaphore_sync_rings(rdev, sem, ring->idx);
	radeon_sync_resv(rdev, &sync, resv, false);
	radeon_sync_rings(rdev, &sync, ring->idx);

	for (i = 0; i < num_loops; i++) {
		cur_size_in_bytes = size_in_bytes;
@@ -586,12 +582,12 @@ struct radeon_fence *cik_copy_dma(struct radeon_device *rdev,
	r = radeon_fence_emit(rdev, &fence, ring->idx);
	if (r) {
		radeon_ring_unlock_undo(rdev, ring);
		radeon_semaphore_free(rdev, &sem, NULL);
		radeon_sync_free(rdev, &sync, NULL);
		return ERR_PTR(r);
	}

	radeon_ring_unlock_commit(rdev, ring, false);
	radeon_semaphore_free(rdev, &sem, fence);
	radeon_sync_free(rdev, &sync, fence);

	return fence;
}
@@ -901,25 +897,21 @@ void cik_sdma_vm_pad_ib(struct radeon_ib *ib)
 * Update the page table base and flush the VM TLB
 * using sDMA (CIK).
 */
void cik_dma_vm_flush(struct radeon_device *rdev, int ridx, struct radeon_vm *vm)
void cik_dma_vm_flush(struct radeon_device *rdev, struct radeon_ring *ring,
		      unsigned vm_id, uint64_t pd_addr)
{
	struct radeon_ring *ring = &rdev->ring[ridx];

	if (vm == NULL)
		return;

	radeon_ring_write(ring, SDMA_PACKET(SDMA_OPCODE_SRBM_WRITE, 0, 0xf000));
	if (vm->id < 8) {
		radeon_ring_write(ring, (VM_CONTEXT0_PAGE_TABLE_BASE_ADDR + (vm->id << 2)) >> 2);
	if (vm_id < 8) {
		radeon_ring_write(ring, (VM_CONTEXT0_PAGE_TABLE_BASE_ADDR + (vm_id << 2)) >> 2);
	} else {
		radeon_ring_write(ring, (VM_CONTEXT8_PAGE_TABLE_BASE_ADDR + ((vm->id - 8) << 2)) >> 2);
		radeon_ring_write(ring, (VM_CONTEXT8_PAGE_TABLE_BASE_ADDR + ((vm_id - 8) << 2)) >> 2);
	}
	radeon_ring_write(ring, vm->pd_gpu_addr >> 12);
	radeon_ring_write(ring, pd_addr >> 12);

	/* update SH_MEM_* regs */
	radeon_ring_write(ring, SDMA_PACKET(SDMA_OPCODE_SRBM_WRITE, 0, 0xf000));
	radeon_ring_write(ring, SRBM_GFX_CNTL >> 2);
	radeon_ring_write(ring, VMID(vm->id));
	radeon_ring_write(ring, VMID(vm_id));

	radeon_ring_write(ring, SDMA_PACKET(SDMA_OPCODE_SRBM_WRITE, 0, 0xf000));
	radeon_ring_write(ring, SH_MEM_BASES >> 2);
@@ -942,11 +934,11 @@ void cik_dma_vm_flush(struct radeon_device *rdev, int ridx, struct radeon_vm *vm
	radeon_ring_write(ring, VMID(0));

	/* flush HDP */
	cik_sdma_hdp_flush_ring_emit(rdev, ridx);
	cik_sdma_hdp_flush_ring_emit(rdev, ring->idx);

	/* flush TLB */
	radeon_ring_write(ring, SDMA_PACKET(SDMA_OPCODE_SRBM_WRITE, 0, 0xf000));
	radeon_ring_write(ring, VM_INVALIDATE_REQUEST >> 2);
	radeon_ring_write(ring, 1 << vm->id);
	radeon_ring_write(ring, 1 << vm_id);
}
Loading