Commit 401f8f33 authored by Leo Chen's avatar Leo Chen Committed by Alex Deucher
Browse files

drm/amd/display: dynamically clock gate before and after prefetch



[Why]
An invalidation request arriving during prefetch can potentially hang
the system if dynamic clock gating is enabled and memory power requests
are disabled.

[How]
• Disable clock gating and enable memory power requests for the duration
of the prefetch.
• Turn on clock gating and disable memory power requests again after
prefetch is complete.

Limit the scope for DCN35 and DCN42 only.

Reviewed-by: default avatarNicholas Kazlauskas <nicholas.kazlauskas@amd.com>
Signed-off-by: default avatarLeo Chen <leo.chen@amd.com>
Signed-off-by: default avatarFangzhi Zuo <jerry.zuo@amd.com>
Tested-by: default avatarDan Wheeler <daniel.wheeler@amd.com>
Signed-off-by: default avatarAlex Deucher <alexander.deucher@amd.com>
parent b6fffcc4
Loading
Loading
Loading
Loading
+4 −3
Original line number Diff line number Diff line
@@ -933,8 +933,8 @@ int hubbub31_init_dchub_sys_ctx(struct hubbub *hubbub,

		dcn20_vmid_setup(&hubbub2->vmid[15], &phys_config);
	}

	dcn21_dchvm_init(hubbub);
	if (hubbub->funcs->dchvm_init)
		hubbub->funcs->dchvm_init(hubbub);

	return NUM_VMID;
}
@@ -1071,7 +1071,8 @@ static const struct hubbub_funcs hubbub31_funcs = {
	.program_compbuf_size = dcn31_program_compbuf_size,
	.init_crb = dcn31_init_crb,
	.hubbub_read_state = hubbub2_read_state,
	.hubbub_read_reg_state = hubbub3_read_reg_state
	.hubbub_read_reg_state = hubbub3_read_reg_state,
	.dchvm_init  = dcn21_dchvm_init
};

void hubbub31_construct(struct dcn20_hubbub *hubbub31,
+51 −1
Original line number Diff line number Diff line
@@ -549,6 +549,55 @@ void hubbub35_init(struct hubbub *hubbub)
	memset(&hubbub2->watermarks.a.cstate_pstate, 0, sizeof(hubbub2->watermarks.a.cstate_pstate));
}

void dcn35_dchvm_init(struct hubbub *hubbub)
{
	struct dcn20_hubbub *hubbub2 = TO_DCN20_HUBBUB(hubbub);
	uint32_t riommu_active;
	int i;

	//Init DCHVM block
	REG_UPDATE(DCHVM_CTRL0, HOSTVM_INIT_REQ, 1);

	//Poll until RIOMMU_ACTIVE = 1
	for (i = 0; i < 100; i++) {
		REG_GET(DCHVM_RIOMMU_STAT0, RIOMMU_ACTIVE, &riommu_active);

		if (riommu_active)
			break;
		else
			udelay(5);
	}

	if (riommu_active) {
		// Disable gating and memory power requests
		REG_UPDATE(DCHVM_MEM_CTRL, HVM_GPUVMRET_PWR_REQ_DIS, 1);
		REG_UPDATE_4(DCHVM_CLK_CTRL,
						HVM_DISPCLK_R_GATE_DIS, 1,
						HVM_DISPCLK_G_GATE_DIS, 1,
						HVM_DCFCLK_R_GATE_DIS, 1,
						HVM_DCFCLK_G_GATE_DIS, 1);

		//Reflect the power status of DCHUBBUB
		REG_UPDATE(DCHVM_RIOMMU_CTRL0, HOSTVM_POWERSTATUS, 1);

		//Start rIOMMU prefetching
		REG_UPDATE(DCHVM_RIOMMU_CTRL0, HOSTVM_PREFETCH_REQ, 1);

		//Poll until HOSTVM_PREFETCH_DONE = 1
		REG_WAIT(DCHVM_RIOMMU_STAT0, HOSTVM_PREFETCH_DONE, 1, 5, 100);

		//Enable memory power requests
		REG_UPDATE(DCHVM_MEM_CTRL, HVM_GPUVMRET_PWR_REQ_DIS, 0);
		// Enable dynamic clock gating
		REG_UPDATE_4(DCHVM_CLK_CTRL,
						HVM_DISPCLK_R_GATE_DIS, 0,
						HVM_DISPCLK_G_GATE_DIS, 0,
						HVM_DCFCLK_R_GATE_DIS, 0,
						HVM_DCFCLK_G_GATE_DIS, 0);
		hubbub->riommu_active = true;
	}
}

/*static void hubbub35_set_request_limit(struct hubbub *hubbub,
				       int memory_channel_count,
				       int words_per_channel)
@@ -589,7 +638,8 @@ static const struct hubbub_funcs hubbub35_funcs = {
	.hubbub_read_state = hubbub2_read_state,
	.force_usr_retraining_allow = hubbub32_force_usr_retraining_allow,
	.dchubbub_init = hubbub35_init,
	.hubbub_read_reg_state = hubbub3_read_reg_state
	.hubbub_read_reg_state = hubbub3_read_reg_state,
	.dchvm_init = dcn35_dchvm_init
};

void hubbub35_construct(struct dcn20_hubbub *hubbub2,
+1 −0
Original line number Diff line number Diff line
@@ -168,4 +168,5 @@ void dcn35_program_compbuf_size(struct hubbub *hubbub,
	unsigned int compbuf_size_kb, bool safe_to_increase);
void dcn35_init_crb(struct hubbub *hubbub);
void hubbub35_init(struct hubbub *hubbub);
void dcn35_dchvm_init(struct hubbub *hubbub);
#endif
+2 −0
Original line number Diff line number Diff line
@@ -252,6 +252,8 @@ struct hubbub_funcs {
	void (*program_compbuf_segments)(struct hubbub *hubbub, unsigned compbuf_size_seg, bool safe_to_increase);
	void (*wait_for_det_update)(struct hubbub *hubbub, int hubp_inst);
	bool (*program_arbiter)(struct hubbub *hubbub, struct dml2_display_arb_regs *arb_regs, bool safe_to_lower);
	void (*dchvm_init)(struct hubbub *hubbub);

	struct hubbub_perfmon_funcs {
		void (*reset)(struct hubbub *hubbub);
		void (*start_measuring_max_memory_latency_ns)(