[PATCH 25/36] drm/amd/display: Fix warning caused by an attempt to configure a non-otg master

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



From: Rodrigo Siqueira <rodrigo.siqueira@xxxxxxx>

When booting the system with DCN401, the driver adds the following dmesg
warning:

WARNING: CPU: 8 PID: 175 at
drivers/gpu/drm/amd/amdgpu/../display/dc/core/dc_resource.c:1923
resource_get_opp_heads_for_otg_master+0x13/0x70 [amdgpu]

Modules linked in: amdgpu(+) hid_generic amdxcp i2c_algo_bit
drm_ttm_helper ttm drm_exec gpu_sched drm_suballoc_helper drm_buddy
drm_display_helper drm_kms_helper usbhid hid drm i2c_piix4 ahci igc
libahci video wmi

CPU: 8 PID: 175 Comm: systemd-udevd Not tainted 6.8.0-EXTRA-PROMO-MAY-29+ #66
Hardware name: ASUS System Product Name/TUF GAMING X570-PRO (WI-FI),
BIOS 4021 08/10/2021

RIP: 0010:resource_get_opp_heads_for_otg_master+0x13/0x70 [amdgpu]
Code: 8b 66 0f 1f 44 00 00 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90
90 0f 1f 44 00 00 55 48 83 bf f8 07 00 00 00 48 89 e5 74 0c <0f> 0b 31
f6 89 f0 5d e9 0c 65 01 e5 48 83 bf e0 07 00 00 00 75 ea

RSP: 0018:ffffa5f000816ed8 EFLAGS: 00010246
[...]
PKRU: 55555554
Call Trace:
 <TASK>
 ? show_regs+0x65/0x70
 ? __warn+0x85/0x160
 ? resource_get_opp_heads_for_otg_master+0x13/0x70 [amdgpu]
 ? report_bug+0x192/0x1c0
 ? handle_bug+0x44/0x90
 ? exc_invalid_op+0x18/0x70
[...]

This warning is triggered by a check in the function
resource_get_opp_heads_for_otg_master that validates if the request
operation is in a master OTG pipe; if not, the warning above is
displayed. In other words, another part of the code might be calling
this function in a non-OTG master pipe context, resulting in the log
message.

The reason the ASSERT was triggered is that the current state wasn't
updated after applying the context to the hardware. This means that the
update_dsc_for_odm_change might be called from a non-OTG-MASTER. To
prevent this, it's crucial to check if the current reference is pointing
to an OTG master before operate in the old OTG master reference. If it's
not, the function must set the old OTG reference to NULL and avoid
calling resource_get_opp_heads_for_otg_master before the context is
updated.

Reviewed-by: Wenjing Liu <wenjing.liu@xxxxxxx>
Acked-by: Hamza Mahfooz <hamza.mahfooz@xxxxxxx>
Co-developed-by: Wenjing Liu <wenjing.liu@xxxxxxx>
Signed-off-by: Wenjing Liu <wenjing.liu@xxxxxxx>
Signed-off-by: Rodrigo Siqueira <rodrigo.siqueira@xxxxxxx>
---
 .../amd/display/dc/hwss/dcn401/dcn401_hwseq.c | 24 ++++++++++++++-----
 1 file changed, 18 insertions(+), 6 deletions(-)

diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dcn401/dcn401_hwseq.c b/drivers/gpu/drm/amd/display/dc/hwss/dcn401/dcn401_hwseq.c
index 0fafbec442b1..cb8e417fb032 100644
--- a/drivers/gpu/drm/amd/display/dc/hwss/dcn401/dcn401_hwseq.c
+++ b/drivers/gpu/drm/amd/display/dc/hwss/dcn401/dcn401_hwseq.c
@@ -1561,16 +1561,28 @@ static void update_dsc_for_odm_change(struct dc *dc, struct dc_state *context,
 	struct pipe_ctx *new_pipe;
 	struct pipe_ctx *old_opp_heads[MAX_PIPES];
 	struct dccg *dccg = dc->res_pool->dccg;
-	struct pipe_ctx *old_otg_master =
-			&dc->current_state->res_ctx.pipe_ctx[otg_master->pipe_idx];
-	int old_opp_head_count = resource_get_opp_heads_for_otg_master(
-			old_otg_master, &dc->current_state->res_ctx,
-			old_opp_heads);
+	struct pipe_ctx *old_otg_master;
+	int old_opp_head_count = 0;
+
+	old_otg_master = &dc->current_state->res_ctx.pipe_ctx[otg_master->pipe_idx];
+
+	if (resource_is_pipe_type(old_otg_master, OTG_MASTER)) {
+		old_opp_head_count = resource_get_opp_heads_for_otg_master(old_otg_master,
+									   &dc->current_state->res_ctx,
+									   old_opp_heads);
+	} else {
+		// DC cannot assume that the current state and the new state
+		// share the same OTG pipe since this is not true when called
+		// in the context of a commit stream not checked. Hence, set
+		// old_otg_master to NULL to skip the DSC configuration.
+		old_otg_master = NULL;
+	}
+
 
 	if (otg_master->stream_res.dsc)
 		dcn32_update_dsc_on_stream(otg_master,
 				otg_master->stream->timing.flags.DSC);
-	if (old_otg_master->stream_res.dsc) {
+	if (old_otg_master && old_otg_master->stream_res.dsc) {
 		for (i = 0; i < old_opp_head_count; i++) {
 			old_pipe = old_opp_heads[i];
 			new_pipe = &context->res_ctx.pipe_ctx[old_pipe->pipe_idx];
-- 
2.45.1




[Index of Archives]     [Linux USB Devel]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux