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

Commit d0c55cdf authored by Alex Deucher's avatar Alex Deucher
Browse files

drm/amdgpu/gfx: fix MEC interrupt enablement for pipes != 0



The interrupt registers are not indexed.

Fixes: 763a47b8 (drm/amdgpu: teach amdgpu how to enable interrupts for any pipe v3)
Acked-by: default avatarChristian König <christian.koenig@amd.com>
Signed-off-by: default avatarAlex Deucher <alexander.deucher@amd.com>
parent f06fed92
Loading
Loading
Loading
Loading
+40 −17
Original line number Diff line number Diff line
@@ -5015,28 +5015,51 @@ static void gfx_v7_0_set_compute_eop_interrupt_state(struct amdgpu_device *adev,
						     int me, int pipe,
						     enum amdgpu_interrupt_state state)
{
	/* Me 0 is for graphics and Me 2 is reserved for HW scheduling
	 * So we should only really be configuring ME 1 i.e. MEC0
	u32 mec_int_cntl, mec_int_cntl_reg;

	/*
	 * amdgpu controls only the first MEC. That's why this function only
	 * handles the setting of interrupts for this specific MEC. All other
	 * pipes' interrupts are set by amdkfd.
	 */
	if (me != 1) {
		DRM_ERROR("Ignoring request to enable interrupts for invalid me:%d\n", me);

	if (me == 1) {
		switch (pipe) {
		case 0:
			mec_int_cntl_reg = mmCP_ME1_PIPE0_INT_CNTL;
			break;
		case 1:
			mec_int_cntl_reg = mmCP_ME1_PIPE1_INT_CNTL;
			break;
		case 2:
			mec_int_cntl_reg = mmCP_ME1_PIPE2_INT_CNTL;
			break;
		case 3:
			mec_int_cntl_reg = mmCP_ME1_PIPE3_INT_CNTL;
			break;
		default:
			DRM_DEBUG("invalid pipe %d\n", pipe);
			return;
		}

	if (pipe >= adev->gfx.mec.num_pipe_per_mec) {
		DRM_ERROR("Ignoring request to enable interrupts for invalid "
				"me:%d pipe:%d\n", pipe, me);
	} else {
		DRM_DEBUG("invalid me %d\n", me);
		return;
	}

	mutex_lock(&adev->srbm_mutex);
	cik_srbm_select(adev, me, pipe, 0, 0);

	WREG32_FIELD(CPC_INT_CNTL, TIME_STAMP_INT_ENABLE,
			state == AMDGPU_IRQ_STATE_DISABLE ? 0 : 1);

	cik_srbm_select(adev, 0, 0, 0, 0);
	mutex_unlock(&adev->srbm_mutex);
	switch (state) {
	case AMDGPU_IRQ_STATE_DISABLE:
		mec_int_cntl = RREG32(mec_int_cntl_reg);
		mec_int_cntl &= ~CP_INT_CNTL_RING0__TIME_STAMP_INT_ENABLE_MASK;
		WREG32(mec_int_cntl_reg, mec_int_cntl);
		break;
	case AMDGPU_IRQ_STATE_ENABLE:
		mec_int_cntl = RREG32(mec_int_cntl_reg);
		mec_int_cntl |= CP_INT_CNTL_RING0__TIME_STAMP_INT_ENABLE_MASK;
		WREG32(mec_int_cntl_reg, mec_int_cntl);
		break;
	default:
		break;
	}
}

static int gfx_v7_0_set_priv_reg_fault_state(struct amdgpu_device *adev,
+41 −16
Original line number Diff line number Diff line
@@ -6610,26 +6610,51 @@ static void gfx_v8_0_set_compute_eop_interrupt_state(struct amdgpu_device *adev,
						     int me, int pipe,
						     enum amdgpu_interrupt_state state)
{
	/* Me 0 is reserved for graphics */
	if (me < 1 || me > adev->gfx.mec.num_mec) {
		DRM_ERROR("Ignoring request to enable interrupts for invalid me:%d\n", me);
	u32 mec_int_cntl, mec_int_cntl_reg;

	/*
	 * amdgpu controls only the first MEC. That's why this function only
	 * handles the setting of interrupts for this specific MEC. All other
	 * pipes' interrupts are set by amdkfd.
	 */

	if (me == 1) {
		switch (pipe) {
		case 0:
			mec_int_cntl_reg = mmCP_ME1_PIPE0_INT_CNTL;
			break;
		case 1:
			mec_int_cntl_reg = mmCP_ME1_PIPE1_INT_CNTL;
			break;
		case 2:
			mec_int_cntl_reg = mmCP_ME1_PIPE2_INT_CNTL;
			break;
		case 3:
			mec_int_cntl_reg = mmCP_ME1_PIPE3_INT_CNTL;
			break;
		default:
			DRM_DEBUG("invalid pipe %d\n", pipe);
			return;
		}

	if (pipe >= adev->gfx.mec.num_pipe_per_mec) {
		DRM_ERROR("Ignoring request to enable interrupts for invalid "
				"me:%d pipe:%d\n", pipe, me);
	} else {
		DRM_DEBUG("invalid me %d\n", me);
		return;
	}

	mutex_lock(&adev->srbm_mutex);
	vi_srbm_select(adev, me, pipe, 0, 0);

	WREG32_FIELD(CPC_INT_CNTL, TIME_STAMP_INT_ENABLE,
			state == AMDGPU_IRQ_STATE_DISABLE ? 0 : 1);

	vi_srbm_select(adev, 0, 0, 0, 0);
	mutex_unlock(&adev->srbm_mutex);
	switch (state) {
	case AMDGPU_IRQ_STATE_DISABLE:
		mec_int_cntl = RREG32(mec_int_cntl_reg);
		mec_int_cntl &= ~CP_INT_CNTL_RING0__TIME_STAMP_INT_ENABLE_MASK;
		WREG32(mec_int_cntl_reg, mec_int_cntl);
		break;
	case AMDGPU_IRQ_STATE_ENABLE:
		mec_int_cntl = RREG32(mec_int_cntl_reg);
		mec_int_cntl |= CP_INT_CNTL_RING0__TIME_STAMP_INT_ENABLE_MASK;
		WREG32(mec_int_cntl_reg, mec_int_cntl);
		break;
	default:
		break;
	}
}

static int gfx_v8_0_set_priv_reg_fault_state(struct amdgpu_device *adev,
+43 −16
Original line number Diff line number Diff line
@@ -3982,26 +3982,53 @@ static void gfx_v9_0_set_compute_eop_interrupt_state(struct amdgpu_device *adev,
						     int me, int pipe,
						     enum amdgpu_interrupt_state state)
{
	/* Me 0 is reserved for graphics */
	if (me < 1 || me > adev->gfx.mec.num_mec) {
		DRM_ERROR("Ignoring request to enable interrupts for invalid me:%d\n", me);
	u32 mec_int_cntl, mec_int_cntl_reg;

	/*
	 * amdgpu controls only the first MEC. That's why this function only
	 * handles the setting of interrupts for this specific MEC. All other
	 * pipes' interrupts are set by amdkfd.
	 */

	if (me == 1) {
		switch (pipe) {
		case 0:
			mec_int_cntl_reg = SOC15_REG_OFFSET(GC, 0, mmCP_ME1_PIPE0_INT_CNTL);
			break;
		case 1:
			mec_int_cntl_reg = SOC15_REG_OFFSET(GC, 0, mmCP_ME1_PIPE1_INT_CNTL);
			break;
		case 2:
			mec_int_cntl_reg = SOC15_REG_OFFSET(GC, 0, mmCP_ME1_PIPE2_INT_CNTL);
			break;
		case 3:
			mec_int_cntl_reg = SOC15_REG_OFFSET(GC, 0, mmCP_ME1_PIPE3_INT_CNTL);
			break;
		default:
			DRM_DEBUG("invalid pipe %d\n", pipe);
			return;
		}

	if (pipe >= adev->gfx.mec.num_pipe_per_mec) {
		DRM_ERROR("Ignoring request to enable interrupts for invalid "
				"me:%d pipe:%d\n", pipe, me);
	} else {
		DRM_DEBUG("invalid me %d\n", me);
		return;
	}

	mutex_lock(&adev->srbm_mutex);
	soc15_grbm_select(adev, me, pipe, 0, 0);

	WREG32_FIELD(CPC_INT_CNTL, TIME_STAMP_INT_ENABLE,
			state == AMDGPU_IRQ_STATE_DISABLE ? 0 : 1);

	soc15_grbm_select(adev, 0, 0, 0, 0);
	mutex_unlock(&adev->srbm_mutex);
	switch (state) {
	case AMDGPU_IRQ_STATE_DISABLE:
		mec_int_cntl = RREG32(mec_int_cntl_reg);
		mec_int_cntl = REG_SET_FIELD(mec_int_cntl, CP_ME1_PIPE0_INT_CNTL,
					     TIME_STAMP_INT_ENABLE, 0);
		WREG32(mec_int_cntl_reg, mec_int_cntl);
		break;
	case AMDGPU_IRQ_STATE_ENABLE:
		mec_int_cntl = RREG32(mec_int_cntl_reg);
		mec_int_cntl = REG_SET_FIELD(mec_int_cntl, CP_ME1_PIPE0_INT_CNTL,
					     TIME_STAMP_INT_ENABLE, 1);
		WREG32(mec_int_cntl_reg, mec_int_cntl);
		break;
	default:
		break;
	}
}

static int gfx_v9_0_set_priv_reg_fault_state(struct amdgpu_device *adev,