Commit f232d9ec authored by Lucas Stach's avatar Lucas Stach

drm/etnaviv: fix TS cache flushing on GPUs with BLT engine

As seen in the Vivante kernel driver, most GPUs with the BLT engine have
a broken TS cache flush. The workaround is to temporarily set the BLT
command to CLEAR_IMAGE, without actually executing the clear. Apparently
this state change is enough to trigger the required TS cache flush. As
the BLT engine is completely asychronous, we also need a few more stall
states to synchronize the flush with the frontend.
Root-caused-by: default avatarJonathan Marek <jonathan@marek.ca>
Signed-off-by: default avatarLucas Stach <l.stach@pengutronix.de>
parent b72af445
...@@ -12,6 +12,7 @@ ...@@ -12,6 +12,7 @@
#include "common.xml.h" #include "common.xml.h"
#include "state.xml.h" #include "state.xml.h"
#include "state_blt.xml.h"
#include "state_hi.xml.h" #include "state_hi.xml.h"
#include "state_3d.xml.h" #include "state_3d.xml.h"
#include "cmdstream.xml.h" #include "cmdstream.xml.h"
...@@ -233,6 +234,8 @@ void etnaviv_buffer_end(struct etnaviv_gpu *gpu) ...@@ -233,6 +234,8 @@ void etnaviv_buffer_end(struct etnaviv_gpu *gpu)
struct etnaviv_cmdbuf *buffer = &gpu->buffer; struct etnaviv_cmdbuf *buffer = &gpu->buffer;
unsigned int waitlink_offset = buffer->user_size - 16; unsigned int waitlink_offset = buffer->user_size - 16;
u32 link_target, flush = 0; u32 link_target, flush = 0;
bool has_blt = !!(gpu->identity.minor_features5 &
chipMinorFeatures5_BLT_ENGINE);
lockdep_assert_held(&gpu->lock); lockdep_assert_held(&gpu->lock);
...@@ -248,16 +251,38 @@ void etnaviv_buffer_end(struct etnaviv_gpu *gpu) ...@@ -248,16 +251,38 @@ void etnaviv_buffer_end(struct etnaviv_gpu *gpu)
if (flush) { if (flush) {
unsigned int dwords = 7; unsigned int dwords = 7;
if (has_blt)
dwords += 10;
link_target = etnaviv_buffer_reserve(gpu, buffer, dwords); link_target = etnaviv_buffer_reserve(gpu, buffer, dwords);
CMD_SEM(buffer, SYNC_RECIPIENT_FE, SYNC_RECIPIENT_PE); CMD_SEM(buffer, SYNC_RECIPIENT_FE, SYNC_RECIPIENT_PE);
CMD_STALL(buffer, SYNC_RECIPIENT_FE, SYNC_RECIPIENT_PE); CMD_STALL(buffer, SYNC_RECIPIENT_FE, SYNC_RECIPIENT_PE);
if (has_blt) {
CMD_LOAD_STATE(buffer, VIVS_BLT_ENABLE, 0x1);
CMD_SEM(buffer, SYNC_RECIPIENT_FE, SYNC_RECIPIENT_BLT);
CMD_STALL(buffer, SYNC_RECIPIENT_FE, SYNC_RECIPIENT_BLT);
CMD_LOAD_STATE(buffer, VIVS_BLT_ENABLE, 0x0);
}
CMD_LOAD_STATE(buffer, VIVS_GL_FLUSH_CACHE, flush); CMD_LOAD_STATE(buffer, VIVS_GL_FLUSH_CACHE, flush);
if (gpu->exec_state == ETNA_PIPE_3D) if (gpu->exec_state == ETNA_PIPE_3D) {
CMD_LOAD_STATE(buffer, VIVS_TS_FLUSH_CACHE, if (has_blt) {
VIVS_TS_FLUSH_CACHE_FLUSH); CMD_LOAD_STATE(buffer, VIVS_BLT_ENABLE, 0x1);
CMD_LOAD_STATE(buffer, VIVS_BLT_SET_COMMAND, 0x1);
CMD_LOAD_STATE(buffer, VIVS_BLT_ENABLE, 0x0);
} else {
CMD_LOAD_STATE(buffer, VIVS_TS_FLUSH_CACHE,
VIVS_TS_FLUSH_CACHE_FLUSH);
}
}
CMD_SEM(buffer, SYNC_RECIPIENT_FE, SYNC_RECIPIENT_PE); CMD_SEM(buffer, SYNC_RECIPIENT_FE, SYNC_RECIPIENT_PE);
CMD_STALL(buffer, SYNC_RECIPIENT_FE, SYNC_RECIPIENT_PE); CMD_STALL(buffer, SYNC_RECIPIENT_FE, SYNC_RECIPIENT_PE);
if (has_blt) {
CMD_LOAD_STATE(buffer, VIVS_BLT_ENABLE, 0x1);
CMD_SEM(buffer, SYNC_RECIPIENT_FE, SYNC_RECIPIENT_BLT);
CMD_STALL(buffer, SYNC_RECIPIENT_FE, SYNC_RECIPIENT_BLT);
CMD_LOAD_STATE(buffer, VIVS_BLT_ENABLE, 0x0);
}
CMD_END(buffer); CMD_END(buffer);
etnaviv_buffer_replace_wait(buffer, waitlink_offset, etnaviv_buffer_replace_wait(buffer, waitlink_offset,
...@@ -323,6 +348,8 @@ void etnaviv_buffer_queue(struct etnaviv_gpu *gpu, u32 exec_state, ...@@ -323,6 +348,8 @@ void etnaviv_buffer_queue(struct etnaviv_gpu *gpu, u32 exec_state,
bool switch_mmu_context = gpu->mmu_context != mmu_context; bool switch_mmu_context = gpu->mmu_context != mmu_context;
unsigned int new_flush_seq = READ_ONCE(gpu->mmu_context->flush_seq); unsigned int new_flush_seq = READ_ONCE(gpu->mmu_context->flush_seq);
bool need_flush = switch_mmu_context || gpu->flush_seq != new_flush_seq; bool need_flush = switch_mmu_context || gpu->flush_seq != new_flush_seq;
bool has_blt = !!(gpu->identity.minor_features5 &
chipMinorFeatures5_BLT_ENGINE);
lockdep_assert_held(&gpu->lock); lockdep_assert_held(&gpu->lock);
...@@ -433,6 +460,15 @@ void etnaviv_buffer_queue(struct etnaviv_gpu *gpu, u32 exec_state, ...@@ -433,6 +460,15 @@ void etnaviv_buffer_queue(struct etnaviv_gpu *gpu, u32 exec_state,
* 2 semaphore stall + 1 event + 1 wait + 1 link. * 2 semaphore stall + 1 event + 1 wait + 1 link.
*/ */
return_dwords = 7; return_dwords = 7;
/*
* When the BLT engine is present we need 6 more dwords in the return
* target: 3 enable/flush/disable + 4 enable/semaphore stall/disable,
* but we don't need the normal TS flush state.
*/
if (has_blt)
return_dwords += 6;
return_target = etnaviv_buffer_reserve(gpu, buffer, return_dwords); return_target = etnaviv_buffer_reserve(gpu, buffer, return_dwords);
CMD_LINK(cmdbuf, return_dwords, return_target); CMD_LINK(cmdbuf, return_dwords, return_target);
...@@ -447,11 +483,25 @@ void etnaviv_buffer_queue(struct etnaviv_gpu *gpu, u32 exec_state, ...@@ -447,11 +483,25 @@ void etnaviv_buffer_queue(struct etnaviv_gpu *gpu, u32 exec_state,
CMD_LOAD_STATE(buffer, VIVS_GL_FLUSH_CACHE, CMD_LOAD_STATE(buffer, VIVS_GL_FLUSH_CACHE,
VIVS_GL_FLUSH_CACHE_DEPTH | VIVS_GL_FLUSH_CACHE_DEPTH |
VIVS_GL_FLUSH_CACHE_COLOR); VIVS_GL_FLUSH_CACHE_COLOR);
CMD_LOAD_STATE(buffer, VIVS_TS_FLUSH_CACHE, if (has_blt) {
VIVS_TS_FLUSH_CACHE_FLUSH); CMD_LOAD_STATE(buffer, VIVS_BLT_ENABLE, 0x1);
CMD_LOAD_STATE(buffer, VIVS_BLT_SET_COMMAND, 0x1);
CMD_LOAD_STATE(buffer, VIVS_BLT_ENABLE, 0x0);
} else {
CMD_LOAD_STATE(buffer, VIVS_TS_FLUSH_CACHE,
VIVS_TS_FLUSH_CACHE_FLUSH);
}
} }
CMD_SEM(buffer, SYNC_RECIPIENT_FE, SYNC_RECIPIENT_PE); CMD_SEM(buffer, SYNC_RECIPIENT_FE, SYNC_RECIPIENT_PE);
CMD_STALL(buffer, SYNC_RECIPIENT_FE, SYNC_RECIPIENT_PE); CMD_STALL(buffer, SYNC_RECIPIENT_FE, SYNC_RECIPIENT_PE);
if (has_blt) {
CMD_LOAD_STATE(buffer, VIVS_BLT_ENABLE, 0x1);
CMD_SEM(buffer, SYNC_RECIPIENT_FE, SYNC_RECIPIENT_BLT);
CMD_STALL(buffer, SYNC_RECIPIENT_FE, SYNC_RECIPIENT_BLT);
CMD_LOAD_STATE(buffer, VIVS_BLT_ENABLE, 0x0);
}
CMD_LOAD_STATE(buffer, VIVS_GL_EVENT, VIVS_GL_EVENT_EVENT_ID(event) | CMD_LOAD_STATE(buffer, VIVS_GL_EVENT, VIVS_GL_EVENT_EVENT_ID(event) |
VIVS_GL_EVENT_FROM_PE); VIVS_GL_EVENT_FROM_PE);
CMD_WAIT(buffer); CMD_WAIT(buffer);
......
...@@ -46,6 +46,8 @@ DEALINGS IN THE SOFTWARE. ...@@ -46,6 +46,8 @@ DEALINGS IN THE SOFTWARE.
/* This is a cut-down version of the state_blt.xml.h file */ /* This is a cut-down version of the state_blt.xml.h file */
#define VIVS_BLT_SET_COMMAND 0x000140ac
#define VIVS_BLT_ENABLE 0x000140b8 #define VIVS_BLT_ENABLE 0x000140b8
#define VIVS_BLT_ENABLE_ENABLE 0x00000001 #define VIVS_BLT_ENABLE_ENABLE 0x00000001
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment