[PATCH 09/43] drm/amd/display: Read inst_fb data back during DMUB loading

Rodrigo Siqueira Rodrigo.Siqueira at amd.com
Fri Jan 10 14:46:21 UTC 2020


From: Nicholas Kazlauskas <nicholas.kazlauskas at amd.com>

[Why]
The inst firmware isn't necessarily fully flushed to framebuffer
memory and the DMCUB can hang due to invalid inst being parsed.

[How]
Like the fix to flush ringbuffer commands before updating the inbox
write pointer we need to read back inst memory before writing the
CW0 registers.

Add a helper to read 64-byte chunks to avoid a large temporary buffer.
Read the remaining leftover bytes if the inst_fb isn't fully aligned.

Signed-off-by: Nicholas Kazlauskas <nicholas.kazlauskas at amd.com>
Reviewed-by: Tony Cheng <Tony.Cheng at amd.com>
Acked-by: Harry Wentland <harry.wentland at amd.com>
Acked-by: Rodrigo Siqueira <Rodrigo.Siqueira at amd.com>
---
 .../gpu/drm/amd/display/dmub/src/dmub_srv.c   | 27 +++++++++++++++++++
 1 file changed, 27 insertions(+)

diff --git a/drivers/gpu/drm/amd/display/dmub/src/dmub_srv.c b/drivers/gpu/drm/amd/display/dmub/src/dmub_srv.c
index 23ca1fe97757..dee676335d73 100644
--- a/drivers/gpu/drm/amd/display/dmub/src/dmub_srv.c
+++ b/drivers/gpu/drm/amd/display/dmub/src/dmub_srv.c
@@ -67,6 +67,26 @@ static inline uint32_t dmub_align(uint32_t val, uint32_t factor)
 	return (val + factor - 1) / factor * factor;
 }
 
+static void dmub_flush_buffer_mem(const struct dmub_fb *fb)
+{
+	const uint8_t *base = (const uint8_t *)fb->cpu_addr;
+	uint8_t buf[64];
+	uint32_t pos, end;
+
+	/**
+	 * Read 64-byte chunks since we don't want to store a
+	 * large temporary buffer for this purpose.
+	 */
+	end = fb->size / sizeof(buf) * sizeof(buf);
+
+	for (pos = 0; pos < end; pos += sizeof(buf))
+		dmub_memcpy(buf, base + pos, sizeof(buf));
+
+	/* Read anything leftover into the buffer. */
+	if (end < fb->size)
+		dmub_memcpy(buf, base + pos, fb->size - end);
+}
+
 static const struct dmub_fw_meta_info *
 dmub_get_fw_meta_info(const uint8_t *fw_bss_data, uint32_t fw_bss_data_size)
 {
@@ -329,6 +349,13 @@ enum dmub_status dmub_srv_hw_init(struct dmub_srv *dmub,
 		cw1.region.base = DMUB_CW1_BASE;
 		cw1.region.top = cw1.region.base + stack_fb->size - 1;
 
+		/**
+		 * Read back all the instruction memory so we don't hang the
+		 * DMCUB when backdoor loading if the write from x86 hasn't been
+		 * flushed yet. This only occurs in backdoor loading.
+		 */
+		dmub_flush_buffer_mem(inst_fb);
+
 		if (params->load_inst_const && dmub->hw_funcs.backdoor_load)
 			dmub->hw_funcs.backdoor_load(dmub, &cw0, &cw1);
 	}
-- 
2.24.1



More information about the amd-gfx mailing list