Skip to content

Commit

Permalink
drm/etnaviv: fix TS cache flushing on GPUs with BLT engine
Browse files Browse the repository at this point in the history
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: Jonathan Marek <[email protected]>
Signed-off-by: Lucas Stach <[email protected]>
  • Loading branch information
lynxeye-dev committed Mar 20, 2020
1 parent b72af44 commit f232d9e
Show file tree
Hide file tree
Showing 2 changed files with 57 additions and 5 deletions.
60 changes: 55 additions & 5 deletions drivers/gpu/drm/etnaviv/etnaviv_buffer.c
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@

#include "common.xml.h"
#include "state.xml.h"
#include "state_blt.xml.h"
#include "state_hi.xml.h"
#include "state_3d.xml.h"
#include "cmdstream.xml.h"
Expand Down Expand Up @@ -233,6 +234,8 @@ void etnaviv_buffer_end(struct etnaviv_gpu *gpu)
struct etnaviv_cmdbuf *buffer = &gpu->buffer;
unsigned int waitlink_offset = buffer->user_size - 16;
u32 link_target, flush = 0;
bool has_blt = !!(gpu->identity.minor_features5 &
chipMinorFeatures5_BLT_ENGINE);

lockdep_assert_held(&gpu->lock);

Expand All @@ -248,16 +251,38 @@ void etnaviv_buffer_end(struct etnaviv_gpu *gpu)
if (flush) {
unsigned int dwords = 7;

if (has_blt)
dwords += 10;

link_target = etnaviv_buffer_reserve(gpu, buffer, dwords);

CMD_SEM(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);
if (gpu->exec_state == ETNA_PIPE_3D)
CMD_LOAD_STATE(buffer, VIVS_TS_FLUSH_CACHE,
VIVS_TS_FLUSH_CACHE_FLUSH);
if (gpu->exec_state == ETNA_PIPE_3D) {
if (has_blt) {
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_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);

etnaviv_buffer_replace_wait(buffer, waitlink_offset,
Expand Down Expand Up @@ -323,6 +348,8 @@ void etnaviv_buffer_queue(struct etnaviv_gpu *gpu, u32 exec_state,
bool switch_mmu_context = gpu->mmu_context != mmu_context;
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 has_blt = !!(gpu->identity.minor_features5 &
chipMinorFeatures5_BLT_ENGINE);

lockdep_assert_held(&gpu->lock);

Expand Down Expand Up @@ -433,6 +460,15 @@ void etnaviv_buffer_queue(struct etnaviv_gpu *gpu, u32 exec_state,
* 2 semaphore stall + 1 event + 1 wait + 1 link.
*/
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);
CMD_LINK(cmdbuf, return_dwords, return_target);

Expand All @@ -447,11 +483,25 @@ void etnaviv_buffer_queue(struct etnaviv_gpu *gpu, u32 exec_state,
CMD_LOAD_STATE(buffer, VIVS_GL_FLUSH_CACHE,
VIVS_GL_FLUSH_CACHE_DEPTH |
VIVS_GL_FLUSH_CACHE_COLOR);
CMD_LOAD_STATE(buffer, VIVS_TS_FLUSH_CACHE,
VIVS_TS_FLUSH_CACHE_FLUSH);
if (has_blt) {
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_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) |
VIVS_GL_EVENT_FROM_PE);
CMD_WAIT(buffer);
Expand Down
2 changes: 2 additions & 0 deletions drivers/gpu/drm/etnaviv/state_blt.xml.h
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,8 @@ DEALINGS IN THE SOFTWARE.

/* 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_ENABLE 0x00000001

Expand Down

0 comments on commit f232d9e

Please sign in to comment.