Skip to content

Commit f232d9e

Browse files
committed
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: Jonathan Marek <[email protected]> Signed-off-by: Lucas Stach <[email protected]>
1 parent b72af44 commit f232d9e

File tree

2 files changed

+57
-5
lines changed

2 files changed

+57
-5
lines changed

drivers/gpu/drm/etnaviv/etnaviv_buffer.c

Lines changed: 55 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212

1313
#include "common.xml.h"
1414
#include "state.xml.h"
15+
#include "state_blt.xml.h"
1516
#include "state_hi.xml.h"
1617
#include "state_3d.xml.h"
1718
#include "cmdstream.xml.h"
@@ -233,6 +234,8 @@ void etnaviv_buffer_end(struct etnaviv_gpu *gpu)
233234
struct etnaviv_cmdbuf *buffer = &gpu->buffer;
234235
unsigned int waitlink_offset = buffer->user_size - 16;
235236
u32 link_target, flush = 0;
237+
bool has_blt = !!(gpu->identity.minor_features5 &
238+
chipMinorFeatures5_BLT_ENGINE);
236239

237240
lockdep_assert_held(&gpu->lock);
238241

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

254+
if (has_blt)
255+
dwords += 10;
256+
251257
link_target = etnaviv_buffer_reserve(gpu, buffer, dwords);
252258

253259
CMD_SEM(buffer, SYNC_RECIPIENT_FE, SYNC_RECIPIENT_PE);
254260
CMD_STALL(buffer, SYNC_RECIPIENT_FE, SYNC_RECIPIENT_PE);
261+
if (has_blt) {
262+
CMD_LOAD_STATE(buffer, VIVS_BLT_ENABLE, 0x1);
263+
CMD_SEM(buffer, SYNC_RECIPIENT_FE, SYNC_RECIPIENT_BLT);
264+
CMD_STALL(buffer, SYNC_RECIPIENT_FE, SYNC_RECIPIENT_BLT);
265+
CMD_LOAD_STATE(buffer, VIVS_BLT_ENABLE, 0x0);
266+
}
255267
CMD_LOAD_STATE(buffer, VIVS_GL_FLUSH_CACHE, flush);
256-
if (gpu->exec_state == ETNA_PIPE_3D)
257-
CMD_LOAD_STATE(buffer, VIVS_TS_FLUSH_CACHE,
258-
VIVS_TS_FLUSH_CACHE_FLUSH);
268+
if (gpu->exec_state == ETNA_PIPE_3D) {
269+
if (has_blt) {
270+
CMD_LOAD_STATE(buffer, VIVS_BLT_ENABLE, 0x1);
271+
CMD_LOAD_STATE(buffer, VIVS_BLT_SET_COMMAND, 0x1);
272+
CMD_LOAD_STATE(buffer, VIVS_BLT_ENABLE, 0x0);
273+
} else {
274+
CMD_LOAD_STATE(buffer, VIVS_TS_FLUSH_CACHE,
275+
VIVS_TS_FLUSH_CACHE_FLUSH);
276+
}
277+
}
259278
CMD_SEM(buffer, SYNC_RECIPIENT_FE, SYNC_RECIPIENT_PE);
260279
CMD_STALL(buffer, SYNC_RECIPIENT_FE, SYNC_RECIPIENT_PE);
280+
if (has_blt) {
281+
CMD_LOAD_STATE(buffer, VIVS_BLT_ENABLE, 0x1);
282+
CMD_SEM(buffer, SYNC_RECIPIENT_FE, SYNC_RECIPIENT_BLT);
283+
CMD_STALL(buffer, SYNC_RECIPIENT_FE, SYNC_RECIPIENT_BLT);
284+
CMD_LOAD_STATE(buffer, VIVS_BLT_ENABLE, 0x0);
285+
}
261286
CMD_END(buffer);
262287

263288
etnaviv_buffer_replace_wait(buffer, waitlink_offset,
@@ -323,6 +348,8 @@ void etnaviv_buffer_queue(struct etnaviv_gpu *gpu, u32 exec_state,
323348
bool switch_mmu_context = gpu->mmu_context != mmu_context;
324349
unsigned int new_flush_seq = READ_ONCE(gpu->mmu_context->flush_seq);
325350
bool need_flush = switch_mmu_context || gpu->flush_seq != new_flush_seq;
351+
bool has_blt = !!(gpu->identity.minor_features5 &
352+
chipMinorFeatures5_BLT_ENGINE);
326353

327354
lockdep_assert_held(&gpu->lock);
328355

@@ -433,6 +460,15 @@ void etnaviv_buffer_queue(struct etnaviv_gpu *gpu, u32 exec_state,
433460
* 2 semaphore stall + 1 event + 1 wait + 1 link.
434461
*/
435462
return_dwords = 7;
463+
464+
/*
465+
* When the BLT engine is present we need 6 more dwords in the return
466+
* target: 3 enable/flush/disable + 4 enable/semaphore stall/disable,
467+
* but we don't need the normal TS flush state.
468+
*/
469+
if (has_blt)
470+
return_dwords += 6;
471+
436472
return_target = etnaviv_buffer_reserve(gpu, buffer, return_dwords);
437473
CMD_LINK(cmdbuf, return_dwords, return_target);
438474

@@ -447,11 +483,25 @@ void etnaviv_buffer_queue(struct etnaviv_gpu *gpu, u32 exec_state,
447483
CMD_LOAD_STATE(buffer, VIVS_GL_FLUSH_CACHE,
448484
VIVS_GL_FLUSH_CACHE_DEPTH |
449485
VIVS_GL_FLUSH_CACHE_COLOR);
450-
CMD_LOAD_STATE(buffer, VIVS_TS_FLUSH_CACHE,
451-
VIVS_TS_FLUSH_CACHE_FLUSH);
486+
if (has_blt) {
487+
CMD_LOAD_STATE(buffer, VIVS_BLT_ENABLE, 0x1);
488+
CMD_LOAD_STATE(buffer, VIVS_BLT_SET_COMMAND, 0x1);
489+
CMD_LOAD_STATE(buffer, VIVS_BLT_ENABLE, 0x0);
490+
} else {
491+
CMD_LOAD_STATE(buffer, VIVS_TS_FLUSH_CACHE,
492+
VIVS_TS_FLUSH_CACHE_FLUSH);
493+
}
452494
}
453495
CMD_SEM(buffer, SYNC_RECIPIENT_FE, SYNC_RECIPIENT_PE);
454496
CMD_STALL(buffer, SYNC_RECIPIENT_FE, SYNC_RECIPIENT_PE);
497+
498+
if (has_blt) {
499+
CMD_LOAD_STATE(buffer, VIVS_BLT_ENABLE, 0x1);
500+
CMD_SEM(buffer, SYNC_RECIPIENT_FE, SYNC_RECIPIENT_BLT);
501+
CMD_STALL(buffer, SYNC_RECIPIENT_FE, SYNC_RECIPIENT_BLT);
502+
CMD_LOAD_STATE(buffer, VIVS_BLT_ENABLE, 0x0);
503+
}
504+
455505
CMD_LOAD_STATE(buffer, VIVS_GL_EVENT, VIVS_GL_EVENT_EVENT_ID(event) |
456506
VIVS_GL_EVENT_FROM_PE);
457507
CMD_WAIT(buffer);

drivers/gpu/drm/etnaviv/state_blt.xml.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,8 @@ DEALINGS IN THE SOFTWARE.
4646

4747
/* This is a cut-down version of the state_blt.xml.h file */
4848

49+
#define VIVS_BLT_SET_COMMAND 0x000140ac
50+
4951
#define VIVS_BLT_ENABLE 0x000140b8
5052
#define VIVS_BLT_ENABLE_ENABLE 0x00000001
5153

0 commit comments

Comments
 (0)