summaryrefslogtreecommitdiff
path: root/drivers/gpu/drm/amd/display/dmub/src
diff options
context:
space:
mode:
authorNicholas Kazlauskas <nicholas.kazlauskas@amd.com>2019-12-11 21:14:04 -0500
committerAlex Deucher <alexander.deucher@amd.com>2020-01-16 13:46:13 -0500
commitdee5d542836a911b0175f9cccc25b8f5733e2527 (patch)
treecd14a672f57c38bc1afcdf3e577149a9fa7f77d4 /drivers/gpu/drm/amd/display/dmub/src
parentb7408a06733f839c98a9903e204010204452fcd3 (diff)
drm/amd/display: Read inst_fb data back during DMUB loading
[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@amd.com> Reviewed-by: Tony Cheng <Tony.Cheng@amd.com> Acked-by: Harry Wentland <harry.wentland@amd.com> Acked-by: Rodrigo Siqueira <Rodrigo.Siqueira@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
Diffstat (limited to 'drivers/gpu/drm/amd/display/dmub/src')
-rw-r--r--drivers/gpu/drm/amd/display/dmub/src/dmub_srv.c27
1 files changed, 27 insertions, 0 deletions
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);
}