* drm/etnaviv: Add support for running a PPU flop reset
@ 2025-06-18 20:43 Gert Wollny
2025-06-18 20:43 ` [PATCH v2 1/6] drm/etnaviv: Add command stream definitions required for " Gert Wollny
` (6 more replies)
0 siblings, 7 replies; 18+ messages in thread
From: Gert Wollny @ 2025-06-18 20:43 UTC (permalink / raw)
To: Lucas Stach, Russell King, Christian Gmeiner
Cc: etnaviv, dri-devel, linux-kernel
Dear all,
this is the second version of the patches to add a PPU flop reset to
drm/etnaviv. The first version of the series was send as an RFC to
etnaviv@lists.freedesktop.org only.
This series adds running the PPU flop reset which is required for some
hardware. This implementation was tested with the STM vendor kernel based on
linux-6.6.48 that is provided with
https://github.com/STMicroelectronics/oe-manifest/
Release: openstlinux-6.6-yocto-scarthgap-mpu-v25.04.30
The command stream is based on the stream that is emitted in the acccording
code of the galcore kernel. Since I have only a stm32mp257f-ev1 board t
test this for all parts that are emitted conditionally in the galcore kernel
only the part that is required for this board is submitted here.
Changes since v1 (RFC):
- clean up some code according to comments by Lucas,
- move the ppu flop reset data into drm_private as suggested by Lucas
- initialize flop reset data only once if any GPU needs it,
For this is was also required to move the identification
of the hardware to etnaviv_gpu_bind,
- move VIVS_ definitions out of etnaviv_flop_reset.c,
- add a module parameter that makes it possible to force running the
PPU flop reset.
Thanks for any comments,
Gert
^ permalink raw reply [flat|nested] 18+ messages in thread
* [PATCH v2 1/6] drm/etnaviv: Add command stream definitions required for a PPU flop reset
2025-06-18 20:43 drm/etnaviv: Add support for running a PPU flop reset Gert Wollny
@ 2025-06-18 20:43 ` Gert Wollny
2025-06-18 20:43 ` [PATCH v2 2/6] drm/etnaviv: move some functions to a header to be able to use them externally Gert Wollny
` (5 subsequent siblings)
6 siblings, 0 replies; 18+ messages in thread
From: Gert Wollny @ 2025-06-18 20:43 UTC (permalink / raw)
To: Lucas Stach, Russell King, Christian Gmeiner
Cc: etnaviv, dri-devel, linux-kernel, Gert Wollny
v2: move some defines into the header that resided
in etnaviv_flop_reset.c
Signed-off-by: Gert Wollny <gert.wollny@collabora.com>
---
drivers/gpu/drm/etnaviv/state_3d.xml.h | 97 ++++++++++++++++++++++++++
1 file changed, 97 insertions(+)
diff --git a/drivers/gpu/drm/etnaviv/state_3d.xml.h b/drivers/gpu/drm/etnaviv/state_3d.xml.h
index ebbd4fcf3096..f728cd6a0301 100644
--- a/drivers/gpu/drm/etnaviv/state_3d.xml.h
+++ b/drivers/gpu/drm/etnaviv/state_3d.xml.h
@@ -4,6 +4,103 @@
/* This is a cut-down version of the state_3d.xml.h file */
+#define VIVS_CL_CONFIG 0x00000900
+#define VIVS_CL_CONFIG_DIMENSIONS__MASK 0x00000003
+#define VIVS_CL_CONFIG_DIMENSIONS__SHIFT 0
+#define VIVS_CL_CONFIG_DIMENSIONS(x) (((x) << VIVS_CL_CONFIG_DIMENSIONS__SHIFT) & VIVS_CL_CONFIG_DIMENSIONS__MASK)
+#define VIVS_CL_CONFIG_TRAVERSE_ORDER__MASK 0x00000070
+#define VIVS_CL_CONFIG_TRAVERSE_ORDER__SHIFT 4
+#define VIVS_CL_CONFIG_TRAVERSE_ORDER(x) (((x) << VIVS_CL_CONFIG_TRAVERSE_ORDER__SHIFT) & VIVS_CL_CONFIG_TRAVERSE_ORDER__MASK)
+#define VIVS_CL_CONFIG_ENABLE_SWATH_X 0x00000100
+#define VIVS_CL_CONFIG_ENABLE_SWATH_Y 0x00000200
+#define VIVS_CL_CONFIG_ENABLE_SWATH_Z 0x00000400
+#define VIVS_CL_CONFIG_SWATH_SIZE_X__MASK 0x0000f000
+#define VIVS_CL_CONFIG_SWATH_SIZE_X__SHIFT 12
+#define VIVS_CL_CONFIG_SWATH_SIZE_X(x) (((x) << VIVS_CL_CONFIG_SWATH_SIZE_X__SHIFT) & VIVS_CL_CONFIG_SWATH_SIZE_X__MASK)
+#define VIVS_CL_CONFIG_SWATH_SIZE_Y__MASK 0x000f0000
+#define VIVS_CL_CONFIG_SWATH_SIZE_Y__SHIFT 16
+#define VIVS_CL_CONFIG_SWATH_SIZE_Y(x) (((x) << VIVS_CL_CONFIG_SWATH_SIZE_Y__SHIFT) & VIVS_CL_CONFIG_SWATH_SIZE_Y__MASK)
+#define VIVS_CL_CONFIG_SWATH_SIZE_Z__MASK 0x00f00000
+#define VIVS_CL_CONFIG_SWATH_SIZE_Z__SHIFT 20
+#define VIVS_CL_CONFIG_SWATH_SIZE_Z(x) (((x) << VIVS_CL_CONFIG_SWATH_SIZE_Z__SHIFT) & VIVS_CL_CONFIG_SWATH_SIZE_Z__MASK)
+
+#define VIVS_CL_CONFIG_DIMENSIONS__MASK 0x00000003
+#define VIVS_CL_CONFIG_DIMENSIONS__SHIFT 0
+#define VIVS_CL_CONFIG_DIMENSIONS(x) (((x) << VIVS_CL_CONFIG_DIMENSIONS__SHIFT) & VIVS_CL_CONFIG_DIMENSIONS__MASK)
+
+#define VIVS_CL_CONFIG_VALUE_ORDER__MASK 0x07000000
+#define VIVS_CL_CONFIG_VALUE_ORDER__SHIFT 24
+#define VIVS_CL_CONFIG_VALUE_ORDER(x) (((x) << VIVS_CL_CONFIG_VALUE_ORDER__SHIFT) & VIVS_CL_CONFIG_VALUE_ORDER__MASK)
+
+#define VIVS_CL_GLOBAL_WORK_OFFSET_X 0x0000092c
+#define VIVS_CL_GLOBAL_WORK_OFFSET_Y 0x00000934
+#define VIVS_CL_GLOBAL_WORK_OFFSET_Z 0x0000093c
+
+#define VIVS_CL_KICKER 0x00000920
+#define VIVS_CL_THREAD_ALLOCATION 0x0000091c
+#define VIVS_CL_UNK00924 0x00000924
+
+#define VIVS_CL_WORKGROUP_COUNT_X 0x00000940
+#define VIVS_CL_WORKGROUP_COUNT_Y 0x00000944
+#define VIVS_CL_WORKGROUP_COUNT_Z 0x00000948
+#define VIVS_CL_WORKGROUP_SIZE_X 0x0000094c
+#define VIVS_CL_WORKGROUP_SIZE_Y 0x00000950
+#define VIVS_CL_WORKGROUP_SIZE_Z 0x00000954
+
+#define VIVS_CL_GLOBAL_SCALE_X 0x00000958
+#define VIVS_CL_GLOBAL_SCALE_Y 0x0000095c
+#define VIVS_CL_GLOBAL_SCALE_Z 0x00000960
+
+#define VIVS_PA_VS_OUTPUT_COUNT 0x00000aa8
+#define VIVS_PS_CONTROL_EXT 0x00001030
+#define VIVS_PS_ICACHE_COUNT 0x00001094
+#define VIVS_PS_ICACHE_PREFETCH 0x00001048
+
+#define VIVS_PS_INPUT_COUNT 0x00001008
+#define VIVS_PS_INPUT_COUNT_COUNT__MASK 0x0000001f
+#define VIVS_PS_INPUT_COUNT_COUNT__SHIFT 0
+#define VIVS_PS_INPUT_COUNT_COUNT(x) (((x) << VIVS_PS_INPUT_COUNT_COUNT__SHIFT) & VIVS_PS_INPUT_COUNT_COUNT__MASK)
+
+
+#define VIVS_PS_NEWRANGE_LOW 0x0000087c
+#define VIVS_PS_NEWRANGE_HIGH 0x00001090
+#define VIVS_PS_SAMPLER_BASE 0x00001058
+
+#define VIVS_PS_UNIFORM_BASE 0x00001024
+#define VIVS_PS_INST_ADDR 0x00001028
+
+#define VIVS_PS_TEMP_REGISTER_CONTROL 0x0000100c
+#define VIVS_PS_TEMP_REGISTER_CONTROL_NUM_TEMPS__MASK 0x0000003f
+#define VIVS_PS_TEMP_REGISTER_CONTROL_NUM_TEMPS__SHIFT 0
+#define VIVS_PS_TEMP_REGISTER_CONTROL_NUM_TEMPS(x) (((x) << VIVS_PS_TEMP_REGISTER_CONTROL_NUM_TEMPS__SHIFT) & VIVS_PS_TEMP_REGISTER_CONTROL_NUM_TEMPS__MASK)
+
+#define VIVS_PS_VARYING_NUM_COMPONENTS(i0) (0x00001080 + 0x4*(i0))
+#define VIVS_PS_VARYING_NUM_COMPONENTS__ESIZE 0x00000004
+#define VIVS_PS_VARYING_NUM_COMPONENTS__LEN 0x00000004
+
+#define VIVS_SH_CONFIG 0x00015600
+#define VIVS_SH_CONFIG_RTNE_ROUNDING 0x00000002
+
+#define VIVS_SH_HALTI5_UNIFORMS(i0) (0x00036000 + 0x4*(i0))
+#define VIVS_SH_HALTI5_UNIFORMS__ESIZE 0x00000004
+#define VIVS_SH_HALTI5_UNIFORMS__LEN 0x00000800
+
+#define VIVS_VS_HALTI5_UNK008A0 0x000008a0
+#define VIVS_VS_HALTI5_UNK008A0_A__MASK 0x0000003f
+#define VIVS_VS_HALTI5_UNK008A0_A__SHIFT 0
+#define VIVS_VS_HALTI5_UNK008A0_A(x) (((x) << VIVS_VS_HALTI5_UNK008A0_A__SHIFT) & VIVS_VS_HALTI5_UNK008A0_A__MASK)
+
+
+#define VIVS_VS_ICACHE_CONTROL 0x00000868
+#define VIVS_VS_ICACHE_CONTROL_ENABLE 0x00000001
+
+#define VIVS_VS_ICACHE_INVALIDATE 0x000008b0
+
+#define VIVS_VS_OUTPUT_COUNT 0x00000804
+#define VIVS_VS_OUTPUT_COUNT_COUNT__MASK 0x000000ff
+#define VIVS_VS_OUTPUT_COUNT_COUNT__SHIFT 0
+#define VIVS_VS_OUTPUT_COUNT_COUNT(x) (((x) << VIVS_VS_OUTPUT_COUNT_COUNT__SHIFT) & VIVS_VS_OUTPUT_COUNT_COUNT__MASK)
+
#define VIVS_TS_FLUSH_CACHE 0x00001650
#define VIVS_TS_FLUSH_CACHE_FLUSH 0x00000001
--
2.49.0
^ permalink raw reply related [flat|nested] 18+ messages in thread
* [PATCH v2 2/6] drm/etnaviv: move some functions to a header to be able to use them externally
2025-06-18 20:43 drm/etnaviv: Add support for running a PPU flop reset Gert Wollny
2025-06-18 20:43 ` [PATCH v2 1/6] drm/etnaviv: Add command stream definitions required for " Gert Wollny
@ 2025-06-18 20:43 ` Gert Wollny
2025-06-18 20:43 ` [PATCH v2 3/6] drm/etnaviv: Add a new function to emit a series of states to cmd stream Gert Wollny
` (4 subsequent siblings)
6 siblings, 0 replies; 18+ messages in thread
From: Gert Wollny @ 2025-06-18 20:43 UTC (permalink / raw)
To: Lucas Stach, Russell King, Christian Gmeiner
Cc: etnaviv, dri-devel, linux-kernel, Gert Wollny
Signed-off-by: Gert Wollny <gert.wollny@collabora.com>
---
drivers/gpu/drm/etnaviv/etnaviv_buffer.c | 71 +-------------------
drivers/gpu/drm/etnaviv/etnaviv_buffer.h | 85 ++++++++++++++++++++++++
2 files changed, 86 insertions(+), 70 deletions(-)
create mode 100644 drivers/gpu/drm/etnaviv/etnaviv_buffer.h
diff --git a/drivers/gpu/drm/etnaviv/etnaviv_buffer.c b/drivers/gpu/drm/etnaviv/etnaviv_buffer.c
index b13a17276d07..9e007d977efe 100644
--- a/drivers/gpu/drm/etnaviv/etnaviv_buffer.c
+++ b/drivers/gpu/drm/etnaviv/etnaviv_buffer.c
@@ -9,6 +9,7 @@
#include "etnaviv_gpu.h"
#include "etnaviv_gem.h"
#include "etnaviv_mmu.h"
+#include "etnaviv_buffer.h"
#include "common.xml.h"
#include "state.xml.h"
@@ -17,76 +18,6 @@
#include "state_3d.xml.h"
#include "cmdstream.xml.h"
-/*
- * Command Buffer helper:
- */
-
-
-static inline void OUT(struct etnaviv_cmdbuf *buffer, u32 data)
-{
- u32 *vaddr = (u32 *)buffer->vaddr;
-
- BUG_ON(buffer->user_size >= buffer->size);
-
- vaddr[buffer->user_size / 4] = data;
- buffer->user_size += 4;
-}
-
-static inline void CMD_LOAD_STATE(struct etnaviv_cmdbuf *buffer,
- u32 reg, u32 value)
-{
- u32 index = reg >> VIV_FE_LOAD_STATE_HEADER_OFFSET__SHR;
-
- buffer->user_size = ALIGN(buffer->user_size, 8);
-
- /* write a register via cmd stream */
- OUT(buffer, VIV_FE_LOAD_STATE_HEADER_OP_LOAD_STATE |
- VIV_FE_LOAD_STATE_HEADER_COUNT(1) |
- VIV_FE_LOAD_STATE_HEADER_OFFSET(index));
- OUT(buffer, value);
-}
-
-static inline void CMD_END(struct etnaviv_cmdbuf *buffer)
-{
- buffer->user_size = ALIGN(buffer->user_size, 8);
-
- OUT(buffer, VIV_FE_END_HEADER_OP_END);
-}
-
-static inline void CMD_WAIT(struct etnaviv_cmdbuf *buffer,
- unsigned int waitcycles)
-{
- buffer->user_size = ALIGN(buffer->user_size, 8);
-
- OUT(buffer, VIV_FE_WAIT_HEADER_OP_WAIT | waitcycles);
-}
-
-static inline void CMD_LINK(struct etnaviv_cmdbuf *buffer,
- u16 prefetch, u32 address)
-{
- buffer->user_size = ALIGN(buffer->user_size, 8);
-
- OUT(buffer, VIV_FE_LINK_HEADER_OP_LINK |
- VIV_FE_LINK_HEADER_PREFETCH(prefetch));
- OUT(buffer, address);
-}
-
-static inline void CMD_STALL(struct etnaviv_cmdbuf *buffer,
- u32 from, u32 to)
-{
- buffer->user_size = ALIGN(buffer->user_size, 8);
-
- OUT(buffer, VIV_FE_STALL_HEADER_OP_STALL);
- OUT(buffer, VIV_FE_STALL_TOKEN_FROM(from) | VIV_FE_STALL_TOKEN_TO(to));
-}
-
-static inline void CMD_SEM(struct etnaviv_cmdbuf *buffer, u32 from, u32 to)
-{
- CMD_LOAD_STATE(buffer, VIVS_GL_SEMAPHORE_TOKEN,
- VIVS_GL_SEMAPHORE_TOKEN_FROM(from) |
- VIVS_GL_SEMAPHORE_TOKEN_TO(to));
-}
-
static void etnaviv_cmd_select_pipe(struct etnaviv_gpu *gpu,
struct etnaviv_cmdbuf *buffer, u8 pipe)
{
diff --git a/drivers/gpu/drm/etnaviv/etnaviv_buffer.h b/drivers/gpu/drm/etnaviv/etnaviv_buffer.h
new file mode 100644
index 000000000000..caf820d91ef5
--- /dev/null
+++ b/drivers/gpu/drm/etnaviv/etnaviv_buffer.h
@@ -0,0 +1,85 @@
+
+
+#ifndef etnaviv_buffer_h
+#define etnaviv_buffer_h
+
+#include "etnaviv_cmdbuf.h"
+#include "etnaviv_gpu.h"
+#include "etnaviv_gem.h"
+#include "etnaviv_mmu.h"
+
+#include "common.xml.h"
+#include "linux/printk.h"
+#include "state.xml.h"
+#include "state_blt.xml.h"
+#include "state_hi.xml.h"
+#include "state_3d.xml.h"
+#include "cmdstream.xml.h"
+
+static inline void OUT(struct etnaviv_cmdbuf *buffer, u32 data)
+{
+ u32 *vaddr = (u32 *)buffer->vaddr;
+
+ BUG_ON(buffer->user_size >= buffer->size);
+
+ vaddr[buffer->user_size / 4] = data;
+ buffer->user_size += 4;
+}
+
+static inline void CMD_LOAD_STATE(struct etnaviv_cmdbuf *buffer,
+ u32 reg, u32 value)
+{
+
+ u32 index = reg >> VIV_FE_LOAD_STATE_HEADER_OFFSET__SHR;
+
+ buffer->user_size = ALIGN(buffer->user_size, 8);
+
+ /* write a register via cmd stream */
+ OUT(buffer, VIV_FE_LOAD_STATE_HEADER_OP_LOAD_STATE |
+ VIV_FE_LOAD_STATE_HEADER_COUNT(1) |
+ VIV_FE_LOAD_STATE_HEADER_OFFSET(index));
+ OUT(buffer, value);
+}
+
+static inline void CMD_END(struct etnaviv_cmdbuf *buffer)
+{
+ buffer->user_size = ALIGN(buffer->user_size, 8);
+
+ OUT(buffer, VIV_FE_END_HEADER_OP_END);
+}
+
+static inline void CMD_WAIT(struct etnaviv_cmdbuf *buffer,
+ unsigned int waitcycles)
+{
+ buffer->user_size = ALIGN(buffer->user_size, 8);
+
+ OUT(buffer, VIV_FE_WAIT_HEADER_OP_WAIT | waitcycles);
+}
+
+static inline void CMD_LINK(struct etnaviv_cmdbuf *buffer,
+ u16 prefetch, u32 address)
+{
+ buffer->user_size = ALIGN(buffer->user_size, 8);
+
+ OUT(buffer, VIV_FE_LINK_HEADER_OP_LINK |
+ VIV_FE_LINK_HEADER_PREFETCH(prefetch));
+ OUT(buffer, address);
+}
+
+static inline void CMD_STALL(struct etnaviv_cmdbuf *buffer,
+ u32 from, u32 to)
+{
+ buffer->user_size = ALIGN(buffer->user_size, 8);
+
+ OUT(buffer, VIV_FE_STALL_HEADER_OP_STALL);
+ OUT(buffer, VIV_FE_STALL_TOKEN_FROM(from) | VIV_FE_STALL_TOKEN_TO(to));
+}
+
+static inline void CMD_SEM(struct etnaviv_cmdbuf *buffer, u32 from, u32 to)
+{
+ CMD_LOAD_STATE(buffer, VIVS_GL_SEMAPHORE_TOKEN,
+ VIVS_GL_SEMAPHORE_TOKEN_FROM(from) |
+ VIVS_GL_SEMAPHORE_TOKEN_TO(to));
+}
+
+#endif
--
2.49.0
^ permalink raw reply related [flat|nested] 18+ messages in thread
* [PATCH v2 3/6] drm/etnaviv: Add a new function to emit a series of states to cmd stream
2025-06-18 20:43 drm/etnaviv: Add support for running a PPU flop reset Gert Wollny
2025-06-18 20:43 ` [PATCH v2 1/6] drm/etnaviv: Add command stream definitions required for " Gert Wollny
2025-06-18 20:43 ` [PATCH v2 2/6] drm/etnaviv: move some functions to a header to be able to use them externally Gert Wollny
@ 2025-06-18 20:43 ` Gert Wollny
2025-06-18 20:43 ` [PATCH v2 4/6] drm/etnaviv: Identify GPU already when binding Gert Wollny
` (3 subsequent siblings)
6 siblings, 0 replies; 18+ messages in thread
From: Gert Wollny @ 2025-06-18 20:43 UTC (permalink / raw)
To: Lucas Stach, Russell King, Christian Gmeiner
Cc: etnaviv, dri-devel, linux-kernel, Gert Wollny
v2: fix formatting and remove superfluous masking (Lucas)
Signed-off-by: Gert Wollny <gert.wollny@collabora.com>
---
drivers/gpu/drm/etnaviv/etnaviv_buffer.h | 13 +++++++++++++
1 file changed, 13 insertions(+)
diff --git a/drivers/gpu/drm/etnaviv/etnaviv_buffer.h b/drivers/gpu/drm/etnaviv/etnaviv_buffer.h
index caf820d91ef5..842a7ca55c44 100644
--- a/drivers/gpu/drm/etnaviv/etnaviv_buffer.h
+++ b/drivers/gpu/drm/etnaviv/etnaviv_buffer.h
@@ -41,6 +41,19 @@ static inline void CMD_LOAD_STATE(struct etnaviv_cmdbuf *buffer,
OUT(buffer, value);
}
+static inline void CMD_LOAD_STATES_START(struct etnaviv_cmdbuf *buffer,
+ u32 reg, u32 nvalues)
+{
+ u32 index = reg >> VIV_FE_LOAD_STATE_HEADER_OFFSET__SHR;
+
+ buffer->user_size = ALIGN(buffer->user_size, 8);
+
+ /* write a register via cmd stream */
+ OUT(buffer, VIV_FE_LOAD_STATE_HEADER_OP_LOAD_STATE |
+ VIV_FE_LOAD_STATE_HEADER_OFFSET(index) |
+ VIV_FE_LOAD_STATE_HEADER_COUNT(nvalues));
+}
+
static inline void CMD_END(struct etnaviv_cmdbuf *buffer)
{
buffer->user_size = ALIGN(buffer->user_size, 8);
--
2.49.0
^ permalink raw reply related [flat|nested] 18+ messages in thread
* [PATCH v2 4/6] drm/etnaviv: Identify GPU already when binding
2025-06-18 20:43 drm/etnaviv: Add support for running a PPU flop reset Gert Wollny
` (2 preceding siblings ...)
2025-06-18 20:43 ` [PATCH v2 3/6] drm/etnaviv: Add a new function to emit a series of states to cmd stream Gert Wollny
@ 2025-06-18 20:43 ` Gert Wollny
2025-06-20 20:11 ` Lucas Stach
2025-06-18 20:43 ` [PATCH v2 5/6] drm/etnaviv: Add PPU flop reset Gert Wollny
` (2 subsequent siblings)
6 siblings, 1 reply; 18+ messages in thread
From: Gert Wollny @ 2025-06-18 20:43 UTC (permalink / raw)
To: Lucas Stach, Russell King, Christian Gmeiner
Cc: etnaviv, dri-devel, linux-kernel, Gert Wollny
This is required to know whether to be able to avoid allocating
the flop reset data if non of the available GPUs actually need
it.
Signed-off-by: Gert Wollny <gert.wollny@collabora.com>
---
drivers/gpu/drm/etnaviv/etnaviv_gpu.c | 15 +++++++--------
1 file changed, 7 insertions(+), 8 deletions(-)
diff --git a/drivers/gpu/drm/etnaviv/etnaviv_gpu.c b/drivers/gpu/drm/etnaviv/etnaviv_gpu.c
index cf0d9049bcf1..dc8a7ff3e797 100644
--- a/drivers/gpu/drm/etnaviv/etnaviv_gpu.c
+++ b/drivers/gpu/drm/etnaviv/etnaviv_gpu.c
@@ -829,14 +829,6 @@ int etnaviv_gpu_init(struct etnaviv_gpu *gpu)
goto fail;
}
- etnaviv_hw_identify(gpu);
-
- if (gpu->identity.model == 0) {
- dev_err(gpu->dev, "Unknown GPU model\n");
- ret = -ENXIO;
- goto fail;
- }
-
if (gpu->identity.nn_core_count > 0)
dev_warn(gpu->dev, "etnaviv has been instantiated on a NPU, "
"for which the UAPI is still experimental\n");
@@ -1808,6 +1800,13 @@ static int etnaviv_gpu_bind(struct device *dev, struct device *master,
INIT_WORK(&gpu->sync_point_work, sync_point_worker);
init_waitqueue_head(&gpu->fence_event);
+ etnaviv_hw_identify(gpu);
+
+ if (gpu->identity.model == 0) {
+ dev_err(gpu->dev, "Unknown GPU model\n");
+ ret = -ENXIO;
+ goto out_sched;
+ }
priv->gpu[priv->num_gpus++] = gpu;
return 0;
--
2.49.0
^ permalink raw reply related [flat|nested] 18+ messages in thread
* [PATCH v2 5/6] drm/etnaviv: Add PPU flop reset
2025-06-18 20:43 drm/etnaviv: Add support for running a PPU flop reset Gert Wollny
` (3 preceding siblings ...)
2025-06-18 20:43 ` [PATCH v2 4/6] drm/etnaviv: Identify GPU already when binding Gert Wollny
@ 2025-06-18 20:43 ` Gert Wollny
2025-06-20 20:22 ` Lucas Stach
2025-06-18 20:43 ` [PATCH v2 6/6] drm/etnaviv: Add module parameter to force " Gert Wollny
2025-06-30 20:26 ` [PATCH v3 0/5] drm/etnaviv: Add support for running a " Gert Wollny
6 siblings, 1 reply; 18+ messages in thread
From: Gert Wollny @ 2025-06-18 20:43 UTC (permalink / raw)
To: Lucas Stach, Russell King, Christian Gmeiner
Cc: etnaviv, dri-devel, linux-kernel, Gert Wollny
The PPU flop reset is required on some hardware to clear the
temporary registers. This implementation follows the code
implemented in the public galcore kernel module code to this
for the PPU.
v2: - Move flop reset data to etnaviv_drm_private and initialize it
from etnaviv_gpu_bind (Lucas)
- Prepare code for more chip IDs and other flop reset types
- do some cleanups and function name renaming
Signed-off-by: Gert Wollny <gert.wollny@collabora.com>
---
drivers/gpu/drm/etnaviv/Makefile | 1 +
drivers/gpu/drm/etnaviv/etnaviv_buffer.c | 6 +
drivers/gpu/drm/etnaviv/etnaviv_drv.c | 2 +
drivers/gpu/drm/etnaviv/etnaviv_drv.h | 3 +
drivers/gpu/drm/etnaviv/etnaviv_flop_reset.c | 205 +++++++++++++++++++
drivers/gpu/drm/etnaviv/etnaviv_flop_reset.h | 25 +++
drivers/gpu/drm/etnaviv/etnaviv_gpu.c | 6 +
7 files changed, 248 insertions(+)
create mode 100644 drivers/gpu/drm/etnaviv/etnaviv_flop_reset.c
create mode 100644 drivers/gpu/drm/etnaviv/etnaviv_flop_reset.h
diff --git a/drivers/gpu/drm/etnaviv/Makefile b/drivers/gpu/drm/etnaviv/Makefile
index 46e5ffad69a6..903101e8751a 100644
--- a/drivers/gpu/drm/etnaviv/Makefile
+++ b/drivers/gpu/drm/etnaviv/Makefile
@@ -14,6 +14,7 @@ etnaviv-y := \
etnaviv_iommu.o \
etnaviv_mmu.o \
etnaviv_perfmon.o \
+ etnaviv_flop_reset.o \
etnaviv_sched.o
obj-$(CONFIG_DRM_ETNAVIV) += etnaviv.o
diff --git a/drivers/gpu/drm/etnaviv/etnaviv_buffer.c b/drivers/gpu/drm/etnaviv/etnaviv_buffer.c
index 9e007d977efe..a2da3212592f 100644
--- a/drivers/gpu/drm/etnaviv/etnaviv_buffer.c
+++ b/drivers/gpu/drm/etnaviv/etnaviv_buffer.c
@@ -18,6 +18,8 @@
#include "state_3d.xml.h"
#include "cmdstream.xml.h"
+#include "etnaviv_flop_reset.h"
+
static void etnaviv_cmd_select_pipe(struct etnaviv_gpu *gpu,
struct etnaviv_cmdbuf *buffer, u8 pipe)
{
@@ -100,6 +102,10 @@ u16 etnaviv_buffer_init(struct etnaviv_gpu *gpu)
/* initialize buffer */
buffer->user_size = 0;
+ /* Queue in PPU flop reset */
+ if (etnaviv_flop_reset_ppu_require(&gpu->identity))
+ etnaviv_flop_reset_ppu_run(gpu);
+
CMD_WAIT(buffer, gpu->fe_waitcycles);
CMD_LINK(buffer, 2,
etnaviv_cmdbuf_get_va(buffer, &gpu->mmu_context->cmdbuf_mapping)
diff --git a/drivers/gpu/drm/etnaviv/etnaviv_drv.c b/drivers/gpu/drm/etnaviv/etnaviv_drv.c
index 3e91747ed339..73dc1c00c027 100644
--- a/drivers/gpu/drm/etnaviv/etnaviv_drv.c
+++ b/drivers/gpu/drm/etnaviv/etnaviv_drv.c
@@ -604,6 +604,8 @@ static void etnaviv_unbind(struct device *dev)
xa_destroy(&priv->active_contexts);
+ kfree(priv->flop_reset_data_ppu);
+
drm->dev_private = NULL;
kfree(priv);
diff --git a/drivers/gpu/drm/etnaviv/etnaviv_drv.h b/drivers/gpu/drm/etnaviv/etnaviv_drv.h
index b3eb1662e90c..20dad16fd554 100644
--- a/drivers/gpu/drm/etnaviv/etnaviv_drv.h
+++ b/drivers/gpu/drm/etnaviv/etnaviv_drv.h
@@ -48,6 +48,9 @@ struct etnaviv_drm_private {
/* list of GEM objects: */
struct mutex gem_lock;
struct list_head gem_list;
+
+ /* ppu flop reset data */
+ struct etnaviv_cmdbuf *flop_reset_data_ppu;
};
int etnaviv_ioctl_gem_submit(struct drm_device *dev, void *data,
diff --git a/drivers/gpu/drm/etnaviv/etnaviv_flop_reset.c b/drivers/gpu/drm/etnaviv/etnaviv_flop_reset.c
new file mode 100644
index 000000000000..c33647e96636
--- /dev/null
+++ b/drivers/gpu/drm/etnaviv/etnaviv_flop_reset.c
@@ -0,0 +1,205 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2025 Etnaviv Project
+ */
+
+#include "asm-generic/int-ll64.h"
+#include "etnaviv_buffer.h"
+#include "etnaviv_cmdbuf.h"
+#include "state_3d.xml.h"
+
+#include "etnaviv_flop_reset.h"
+
+enum etnaviv_flop_reset_type {
+ flop_reset_ppu = 1 << 0,
+ flop_reset_nn = 1 << 1,
+ flop_reset_tp = 1 << 2
+};
+
+#define PPU_IMAGE_STRIDE 64
+#define PPU_IMAGE_XSIZE 64
+#define PPU_IMAGE_YSIZE 6
+
+#define PPU_FLOP_RESET_INSTR_DWORD_COUNT 16
+
+static void
+etnaviv_emit_flop_reset_state_ppu(struct etnaviv_cmdbuf *cmdbuf,
+ u32 buffer_base,
+ u32 input_offset,
+ u32 output_offset,
+ u32 shader_offset,
+ u32 shader_size,
+ u32 shader_register_count)
+{
+ CMD_LOAD_STATE(cmdbuf, VIVS_GL_API_MODE,
+ VIVS_GL_API_MODE_OPENCL);
+ CMD_SEM(cmdbuf, SYNC_RECIPIENT_FE, SYNC_RECIPIENT_PE);
+ CMD_STALL(cmdbuf, SYNC_RECIPIENT_FE, SYNC_RECIPIENT_PE);
+
+ CMD_LOAD_STATES_START(cmdbuf, VIVS_SH_HALTI5_UNIFORMS(0), 4);
+
+ OUT(cmdbuf, buffer_base + input_offset);
+ OUT(cmdbuf, PPU_IMAGE_STRIDE);
+ OUT(cmdbuf, PPU_IMAGE_XSIZE | (PPU_IMAGE_YSIZE << 16));
+ OUT(cmdbuf, 0x444051f0);
+ OUT(cmdbuf, 0xffffffff);
+
+ CMD_LOAD_STATES_START(cmdbuf, VIVS_SH_HALTI5_UNIFORMS(4), 4);
+ OUT(cmdbuf, buffer_base + output_offset);
+ OUT(cmdbuf, PPU_IMAGE_STRIDE);
+ OUT(cmdbuf, PPU_IMAGE_XSIZE | (PPU_IMAGE_YSIZE << 16));
+ OUT(cmdbuf, 0x444051f0);
+ OUT(cmdbuf, 0xffffffff);
+
+ CMD_LOAD_STATE(cmdbuf, VIVS_CL_CONFIG,
+ VIVS_CL_CONFIG_DIMENSIONS(2) |
+ VIVS_CL_CONFIG_VALUE_ORDER(3));
+ CMD_LOAD_STATE(cmdbuf, VIVS_VS_ICACHE_INVALIDATE, 0x1f);
+ CMD_LOAD_STATE(cmdbuf, VIVS_PS_VARYING_NUM_COMPONENTS(0), 0);
+ CMD_LOAD_STATE(cmdbuf, VIVS_PS_TEMP_REGISTER_CONTROL,
+ shader_register_count);
+ CMD_LOAD_STATE(cmdbuf, VIVS_PS_SAMPLER_BASE, 0x0);
+ CMD_LOAD_STATE(cmdbuf, VIVS_PS_UNIFORM_BASE, 0x0);
+ CMD_LOAD_STATE(cmdbuf, VIVS_PS_NEWRANGE_LOW, 0x0);
+ CMD_LOAD_STATE(cmdbuf, VIVS_PS_NEWRANGE_HIGH,
+ shader_size / 16);
+ CMD_LOAD_STATE(cmdbuf, VIVS_PS_INST_ADDR,
+ buffer_base + shader_offset);
+ CMD_LOAD_STATE(cmdbuf, VIVS_SH_CONFIG,
+ VIVS_SH_CONFIG_RTNE_ROUNDING);
+ CMD_LOAD_STATE(cmdbuf, VIVS_VS_ICACHE_CONTROL,
+ VIVS_VS_ICACHE_CONTROL_ENABLE);
+ CMD_LOAD_STATE(cmdbuf, VIVS_PS_ICACHE_COUNT,
+ shader_size / 16 - 1);
+ CMD_LOAD_STATE(cmdbuf, VIVS_PS_INPUT_COUNT, 0x1f01);
+ CMD_LOAD_STATE(cmdbuf, VIVS_VS_HALTI5_UNK008A0, 0x0);
+ CMD_LOAD_STATE(cmdbuf, VIVS_PA_VS_OUTPUT_COUNT, 0x0);
+ CMD_LOAD_STATE(cmdbuf, VIVS_GL_VARYING_TOTAL_COMPONENTS, 0x0);
+ CMD_LOAD_STATE(cmdbuf, VIVS_PS_CONTROL_EXT, 0x0);
+ CMD_LOAD_STATE(cmdbuf, VIVS_VS_OUTPUT_COUNT, 0x1);
+ CMD_LOAD_STATE(cmdbuf, VIVS_GL_HALTI5_SH_SPECIALS, 0x0);
+ CMD_LOAD_STATE(cmdbuf, VIVS_PS_ICACHE_PREFETCH, 0x0);
+ CMD_LOAD_STATE(cmdbuf, VIVS_CL_UNK00924, 0x0);
+ CMD_LOAD_STATE(cmdbuf, VIVS_CL_THREAD_ALLOCATION, 0x1);
+
+ CMD_LOAD_STATE(cmdbuf, VIVS_CL_GLOBAL_WORK_OFFSET_X, 0x0);
+ CMD_LOAD_STATE(cmdbuf, VIVS_CL_GLOBAL_WORK_OFFSET_Y, 0x0);
+ CMD_LOAD_STATE(cmdbuf, VIVS_CL_GLOBAL_WORK_OFFSET_Z, 0x0);
+
+ CMD_LOAD_STATES_START(cmdbuf, VIVS_CL_WORKGROUP_COUNT_X, 9);
+ OUT(cmdbuf, 0xf);
+ OUT(cmdbuf, 0x5);
+ OUT(cmdbuf, 0xffffffff);
+ OUT(cmdbuf, 0x0);
+ OUT(cmdbuf, 0x0);
+ OUT(cmdbuf, 0x3ff);
+ OUT(cmdbuf, 0x0);
+ OUT(cmdbuf, 0x4);
+ OUT(cmdbuf, 0x1);
+ OUT(cmdbuf, 0x0);
+
+ CMD_LOAD_STATE(cmdbuf, VIVS_CL_KICKER, 0xbadabeeb);
+ CMD_LOAD_STATE(cmdbuf, VIVS_GL_FLUSH_CACHE,
+ VIVS_GL_FLUSH_CACHE_SHADER_L1 |
+ VIVS_GL_FLUSH_CACHE_UNK10 |
+ VIVS_GL_FLUSH_CACHE_UNK11);
+}
+
+static void
+etnaviv_flop_reset_ppu_fill_input(u32 *buffer, u32 size)
+{
+ for (int i = 0; i < size/4; ++i, ++buffer)
+ *buffer = 0x01010101;
+}
+
+static void
+etnaviv_flop_reset_ppu_set_shader(u8 *dest)
+{
+ const u32 inst[PPU_FLOP_RESET_INSTR_DWORD_COUNT] = {
+ /* img_load.u8 r1, c0, r0.xy */
+ 0x78011779, 0x39000804, 0x00A90050, 0x00000000,
+ /* img_load.u8 r2, c0, r0.xy */
+ 0x78021779, 0x39000804, 0x00A90050, 0x00000000,
+ /* dp2x8 r1, r1, r2, c3_512 */
+ 0xB8017145, 0x390018FC, 0x01C90140, 0x40390028,
+ /* img_store.u8 r1, c2, r0.xy, r1 */
+ 0x380007BA, 0x39001804, 0x00A90050, 0x00390018,
+ };
+ memcpy(dest, inst, sizeof(inst));
+}
+
+static struct etnaviv_flop_reset_entry {
+ u16 chip_model;
+ u16 revision;
+ u32 flags;
+} etnaviv_flop_reset_db [] = {
+ {
+ .chip_model = 0x8000,
+ .revision = 0x6205,
+ .flags = flop_reset_ppu
+ },
+};
+
+bool
+etnaviv_flop_reset_ppu_require(const struct etnaviv_chip_identity *chip_id)
+{
+ const struct etnaviv_flop_reset_entry *e = etnaviv_flop_reset_db;
+
+ for (int i = 0; i < ARRAY_SIZE(etnaviv_flop_reset_db); ++i, ++e) {
+ if (chip_id->model == e->chip_model &&
+ chip_id->revision == e->revision)
+ return (e->flags & flop_reset_ppu) != 0;
+ }
+
+ return false;
+}
+
+static const u32 image_data_size = PPU_IMAGE_STRIDE * PPU_IMAGE_YSIZE;
+static const u32 output_offset = ALIGN(image_data_size, 64);
+static const u32 shader_offset = ALIGN(output_offset + image_data_size, 64);
+static const u32 shader_size = PPU_FLOP_RESET_INSTR_DWORD_COUNT * sizeof(u32);
+static const u32 shader_register_count = 3;
+static const u32 buffer_size = shader_offset + shader_size;
+
+void
+etnaviv_flop_reset_ppu_init(struct etnaviv_drm_private *priv)
+{
+ /* Get some space from the rung buffer to put the payload
+ (input and output image, and shader), we keep this buffer
+ for the whole life time the driver is bound */
+ priv->flop_reset_data_ppu =
+ kzalloc(sizeof(*priv->flop_reset_data_ppu), GFP_KERNEL);
+
+ etnaviv_cmdbuf_init(priv->cmdbuf_suballoc,
+ priv->flop_reset_data_ppu, buffer_size);
+
+ void *buffer_base = priv->flop_reset_data_ppu->vaddr;
+
+ u32 *input_data = (u32 *)buffer_base;
+ etnaviv_flop_reset_ppu_fill_input(input_data, image_data_size);
+
+ u8 *shader_data = (u8 *)buffer_base + shader_offset;
+ etnaviv_flop_reset_ppu_set_shader(shader_data);
+}
+
+void
+etnaviv_flop_reset_ppu_run(struct etnaviv_gpu *gpu)
+{
+ struct etnaviv_drm_private *priv = gpu->drm->dev_private;
+
+ if (!priv->flop_reset_data_ppu) {
+ pr_err("Flop reset data was not initialized, skipping\n");
+ return;
+ }
+
+ u32 buffer_base = etnaviv_cmdbuf_get_va(priv->flop_reset_data_ppu,
+ &gpu->mmu_context->cmdbuf_mapping);
+
+ etnaviv_emit_flop_reset_state_ppu(&gpu->buffer,
+ buffer_base,
+ 0,
+ output_offset,
+ shader_offset,
+ shader_size,
+ shader_register_count);
+}
diff --git a/drivers/gpu/drm/etnaviv/etnaviv_flop_reset.h b/drivers/gpu/drm/etnaviv/etnaviv_flop_reset.h
new file mode 100644
index 000000000000..f51cece75507
--- /dev/null
+++ b/drivers/gpu/drm/etnaviv/etnaviv_flop_reset.h
@@ -0,0 +1,25 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2025 Etnaviv Project
+ */
+
+
+#ifndef etnaviv_flop_reset_h
+#define etnaviv_flop_reset_h
+
+#include <linux/types.h>
+
+struct etnaviv_chip_identity;
+struct etnaviv_drm_private;
+struct etnaviv_gpu;
+
+bool
+etnaviv_flop_reset_ppu_require(const struct etnaviv_chip_identity *chip_id);
+
+void
+etnaviv_flop_reset_ppu_init(struct etnaviv_drm_private *priv);
+
+void
+etnaviv_flop_reset_ppu_run(struct etnaviv_gpu *gpu);
+
+#endif
diff --git a/drivers/gpu/drm/etnaviv/etnaviv_gpu.c b/drivers/gpu/drm/etnaviv/etnaviv_gpu.c
index dc8a7ff3e797..0d1dc1b1d98d 100644
--- a/drivers/gpu/drm/etnaviv/etnaviv_gpu.c
+++ b/drivers/gpu/drm/etnaviv/etnaviv_gpu.c
@@ -18,6 +18,7 @@
#include "etnaviv_cmdbuf.h"
#include "etnaviv_dump.h"
+#include "etnaviv_flop_reset.h"
#include "etnaviv_gpu.h"
#include "etnaviv_gem.h"
#include "etnaviv_mmu.h"
@@ -1807,6 +1808,11 @@ static int etnaviv_gpu_bind(struct device *dev, struct device *master,
ret = -ENXIO;
goto out_sched;
}
+
+ if (etnaviv_flop_reset_ppu_require(&gpu->identity) &&
+ !priv->flop_reset_data_ppu)
+ etnaviv_flop_reset_ppu_init(priv);
+
priv->gpu[priv->num_gpus++] = gpu;
return 0;
--
2.49.0
^ permalink raw reply related [flat|nested] 18+ messages in thread
* [PATCH v2 6/6] drm/etnaviv: Add module parameter to force PPU flop reset
2025-06-18 20:43 drm/etnaviv: Add support for running a PPU flop reset Gert Wollny
` (4 preceding siblings ...)
2025-06-18 20:43 ` [PATCH v2 5/6] drm/etnaviv: Add PPU flop reset Gert Wollny
@ 2025-06-18 20:43 ` Gert Wollny
2025-06-20 20:24 ` Lucas Stach
2025-06-30 20:26 ` [PATCH v3 0/5] drm/etnaviv: Add support for running a " Gert Wollny
6 siblings, 1 reply; 18+ messages in thread
From: Gert Wollny @ 2025-06-18 20:43 UTC (permalink / raw)
To: Lucas Stach, Russell King, Christian Gmeiner
Cc: etnaviv, dri-devel, linux-kernel, Gert Wollny
Signed-off-by: Gert Wollny <gert.wollny@collabora.com>
---
drivers/gpu/drm/etnaviv/etnaviv_flop_reset.c | 9 +++++++++
1 file changed, 9 insertions(+)
diff --git a/drivers/gpu/drm/etnaviv/etnaviv_flop_reset.c b/drivers/gpu/drm/etnaviv/etnaviv_flop_reset.c
index c33647e96636..bf4cae4be815 100644
--- a/drivers/gpu/drm/etnaviv/etnaviv_flop_reset.c
+++ b/drivers/gpu/drm/etnaviv/etnaviv_flop_reset.c
@@ -16,6 +16,9 @@ enum etnaviv_flop_reset_type {
flop_reset_tp = 1 << 2
};
+static int etnaviv_force_flop_reset = 0;
+module_param_named(force_flop_reset, etnaviv_force_flop_reset, int , 0);
+
#define PPU_IMAGE_STRIDE 64
#define PPU_IMAGE_XSIZE 64
#define PPU_IMAGE_YSIZE 6
@@ -151,6 +154,12 @@ etnaviv_flop_reset_ppu_require(const struct etnaviv_chip_identity *chip_id)
return (e->flags & flop_reset_ppu) != 0;
}
+ if (etnaviv_force_flop_reset & flop_reset_ppu) {
+ pr_warn("Forcing flop reset for model: 0x%04x, revision: 0x%04x\n",
+ chip_id->model, chip_id->revision);
+ return true;
+ }
+
return false;
}
--
2.49.0
^ permalink raw reply related [flat|nested] 18+ messages in thread
* Re: [PATCH v2 4/6] drm/etnaviv: Identify GPU already when binding
2025-06-18 20:43 ` [PATCH v2 4/6] drm/etnaviv: Identify GPU already when binding Gert Wollny
@ 2025-06-20 20:11 ` Lucas Stach
0 siblings, 0 replies; 18+ messages in thread
From: Lucas Stach @ 2025-06-20 20:11 UTC (permalink / raw)
To: Gert Wollny, Russell King, Christian Gmeiner
Cc: etnaviv, dri-devel, linux-kernel
Am Mittwoch, dem 18.06.2025 um 22:43 +0200 schrieb Gert Wollny:
> This is required to know whether to be able to avoid allocating
> the flop reset data if non of the available GPUs actually need
> it.
>
I'm surprised that this works on your platform at all. You can not move
the identification here, as the GPU is still treated as suspended in
etnaviv_gpu_bind, so on platforms with clock or power gating reading
the ID registers will cause aborts or system hangs.
Regards,
Lucas
> Signed-off-by: Gert Wollny <gert.wollny@collabora.com>
> ---
> drivers/gpu/drm/etnaviv/etnaviv_gpu.c | 15 +++++++--------
> 1 file changed, 7 insertions(+), 8 deletions(-)
>
> diff --git a/drivers/gpu/drm/etnaviv/etnaviv_gpu.c b/drivers/gpu/drm/etnaviv/etnaviv_gpu.c
> index cf0d9049bcf1..dc8a7ff3e797 100644
> --- a/drivers/gpu/drm/etnaviv/etnaviv_gpu.c
> +++ b/drivers/gpu/drm/etnaviv/etnaviv_gpu.c
> @@ -829,14 +829,6 @@ int etnaviv_gpu_init(struct etnaviv_gpu *gpu)
> goto fail;
> }
>
> - etnaviv_hw_identify(gpu);
> -
> - if (gpu->identity.model == 0) {
> - dev_err(gpu->dev, "Unknown GPU model\n");
> - ret = -ENXIO;
> - goto fail;
> - }
> -
> if (gpu->identity.nn_core_count > 0)
> dev_warn(gpu->dev, "etnaviv has been instantiated on a NPU, "
> "for which the UAPI is still experimental\n");
> @@ -1808,6 +1800,13 @@ static int etnaviv_gpu_bind(struct device *dev, struct device *master,
> INIT_WORK(&gpu->sync_point_work, sync_point_worker);
> init_waitqueue_head(&gpu->fence_event);
>
> + etnaviv_hw_identify(gpu);
> +
> + if (gpu->identity.model == 0) {
> + dev_err(gpu->dev, "Unknown GPU model\n");
> + ret = -ENXIO;
> + goto out_sched;
> + }
> priv->gpu[priv->num_gpus++] = gpu;
>
> return 0;
^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [PATCH v2 5/6] drm/etnaviv: Add PPU flop reset
2025-06-18 20:43 ` [PATCH v2 5/6] drm/etnaviv: Add PPU flop reset Gert Wollny
@ 2025-06-20 20:22 ` Lucas Stach
2025-06-23 12:05 ` Gert Wollny
0 siblings, 1 reply; 18+ messages in thread
From: Lucas Stach @ 2025-06-20 20:22 UTC (permalink / raw)
To: Gert Wollny, Russell King, Christian Gmeiner
Cc: etnaviv, dri-devel, linux-kernel
Am Mittwoch, dem 18.06.2025 um 22:43 +0200 schrieb Gert Wollny:
> The PPU flop reset is required on some hardware to clear the
> temporary registers. This implementation follows the code
> implemented in the public galcore kernel module code to this
> for the PPU.
>
> v2: - Move flop reset data to etnaviv_drm_private and initialize it
> from etnaviv_gpu_bind (Lucas)
> - Prepare code for more chip IDs and other flop reset types
> - do some cleanups and function name renaming
>
> Signed-off-by: Gert Wollny <gert.wollny@collabora.com>
> ---
> drivers/gpu/drm/etnaviv/Makefile | 1 +
> drivers/gpu/drm/etnaviv/etnaviv_buffer.c | 6 +
> drivers/gpu/drm/etnaviv/etnaviv_drv.c | 2 +
> drivers/gpu/drm/etnaviv/etnaviv_drv.h | 3 +
> drivers/gpu/drm/etnaviv/etnaviv_flop_reset.c | 205 +++++++++++++++++++
> drivers/gpu/drm/etnaviv/etnaviv_flop_reset.h | 25 +++
> drivers/gpu/drm/etnaviv/etnaviv_gpu.c | 6 +
> 7 files changed, 248 insertions(+)
> create mode 100644 drivers/gpu/drm/etnaviv/etnaviv_flop_reset.c
> create mode 100644 drivers/gpu/drm/etnaviv/etnaviv_flop_reset.h
>
> diff --git a/drivers/gpu/drm/etnaviv/Makefile b/drivers/gpu/drm/etnaviv/Makefile
> index 46e5ffad69a6..903101e8751a 100644
> --- a/drivers/gpu/drm/etnaviv/Makefile
> +++ b/drivers/gpu/drm/etnaviv/Makefile
> @@ -14,6 +14,7 @@ etnaviv-y := \
> etnaviv_iommu.o \
> etnaviv_mmu.o \
> etnaviv_perfmon.o \
> + etnaviv_flop_reset.o \
> etnaviv_sched.o
>
> obj-$(CONFIG_DRM_ETNAVIV) += etnaviv.o
> diff --git a/drivers/gpu/drm/etnaviv/etnaviv_buffer.c b/drivers/gpu/drm/etnaviv/etnaviv_buffer.c
> index 9e007d977efe..a2da3212592f 100644
> --- a/drivers/gpu/drm/etnaviv/etnaviv_buffer.c
> +++ b/drivers/gpu/drm/etnaviv/etnaviv_buffer.c
> @@ -18,6 +18,8 @@
> #include "state_3d.xml.h"
> #include "cmdstream.xml.h"
>
> +#include "etnaviv_flop_reset.h"
> +
> static void etnaviv_cmd_select_pipe(struct etnaviv_gpu *gpu,
> struct etnaviv_cmdbuf *buffer, u8 pipe)
> {
> @@ -100,6 +102,10 @@ u16 etnaviv_buffer_init(struct etnaviv_gpu *gpu)
> /* initialize buffer */
> buffer->user_size = 0;
>
> + /* Queue in PPU flop reset */
> + if (etnaviv_flop_reset_ppu_require(&gpu->identity))
> + etnaviv_flop_reset_ppu_run(gpu);
> +
> CMD_WAIT(buffer, gpu->fe_waitcycles);
> CMD_LINK(buffer, 2,
> etnaviv_cmdbuf_get_va(buffer, &gpu->mmu_context->cmdbuf_mapping)
> diff --git a/drivers/gpu/drm/etnaviv/etnaviv_drv.c b/drivers/gpu/drm/etnaviv/etnaviv_drv.c
> index 3e91747ed339..73dc1c00c027 100644
> --- a/drivers/gpu/drm/etnaviv/etnaviv_drv.c
> +++ b/drivers/gpu/drm/etnaviv/etnaviv_drv.c
> @@ -604,6 +604,8 @@ static void etnaviv_unbind(struct device *dev)
>
> xa_destroy(&priv->active_contexts);
>
> + kfree(priv->flop_reset_data_ppu);
> +
Missing etnaviv_cmdbuf_free().
> drm->dev_private = NULL;
> kfree(priv);
>
> diff --git a/drivers/gpu/drm/etnaviv/etnaviv_drv.h b/drivers/gpu/drm/etnaviv/etnaviv_drv.h
> index b3eb1662e90c..20dad16fd554 100644
> --- a/drivers/gpu/drm/etnaviv/etnaviv_drv.h
> +++ b/drivers/gpu/drm/etnaviv/etnaviv_drv.h
> @@ -48,6 +48,9 @@ struct etnaviv_drm_private {
> /* list of GEM objects: */
> struct mutex gem_lock;
> struct list_head gem_list;
> +
> + /* ppu flop reset data */
> + struct etnaviv_cmdbuf *flop_reset_data_ppu;
> };
>
> int etnaviv_ioctl_gem_submit(struct drm_device *dev, void *data,
> diff --git a/drivers/gpu/drm/etnaviv/etnaviv_flop_reset.c b/drivers/gpu/drm/etnaviv/etnaviv_flop_reset.c
> new file mode 100644
> index 000000000000..c33647e96636
> --- /dev/null
> +++ b/drivers/gpu/drm/etnaviv/etnaviv_flop_reset.c
> @@ -0,0 +1,205 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * Copyright (C) 2025 Etnaviv Project
> + */
> +
> +#include "asm-generic/int-ll64.h"
> +#include "etnaviv_buffer.h"
> +#include "etnaviv_cmdbuf.h"
> +#include "state_3d.xml.h"
> +
> +#include "etnaviv_flop_reset.h"
> +
> +enum etnaviv_flop_reset_type {
> + flop_reset_ppu = 1 << 0,
> + flop_reset_nn = 1 << 1,
> + flop_reset_tp = 1 << 2
> +};
> +
> +#define PPU_IMAGE_STRIDE 64
> +#define PPU_IMAGE_XSIZE 64
> +#define PPU_IMAGE_YSIZE 6
> +
> +#define PPU_FLOP_RESET_INSTR_DWORD_COUNT 16
> +
> +static void
> +etnaviv_emit_flop_reset_state_ppu(struct etnaviv_cmdbuf *cmdbuf,
> + u32 buffer_base,
> + u32 input_offset,
> + u32 output_offset,
> + u32 shader_offset,
> + u32 shader_size,
> + u32 shader_register_count)
> +{
> + CMD_LOAD_STATE(cmdbuf, VIVS_GL_API_MODE,
> + VIVS_GL_API_MODE_OPENCL);
> + CMD_SEM(cmdbuf, SYNC_RECIPIENT_FE, SYNC_RECIPIENT_PE);
> + CMD_STALL(cmdbuf, SYNC_RECIPIENT_FE, SYNC_RECIPIENT_PE);
> +
> + CMD_LOAD_STATES_START(cmdbuf, VIVS_SH_HALTI5_UNIFORMS(0), 4);
> +
> + OUT(cmdbuf, buffer_base + input_offset);
> + OUT(cmdbuf, PPU_IMAGE_STRIDE);
> + OUT(cmdbuf, PPU_IMAGE_XSIZE | (PPU_IMAGE_YSIZE << 16));
> + OUT(cmdbuf, 0x444051f0);
> + OUT(cmdbuf, 0xffffffff);
> +
> + CMD_LOAD_STATES_START(cmdbuf, VIVS_SH_HALTI5_UNIFORMS(4), 4);
> + OUT(cmdbuf, buffer_base + output_offset);
> + OUT(cmdbuf, PPU_IMAGE_STRIDE);
> + OUT(cmdbuf, PPU_IMAGE_XSIZE | (PPU_IMAGE_YSIZE << 16));
> + OUT(cmdbuf, 0x444051f0);
> + OUT(cmdbuf, 0xffffffff);
> +
> + CMD_LOAD_STATE(cmdbuf, VIVS_CL_CONFIG,
> + VIVS_CL_CONFIG_DIMENSIONS(2) |
> + VIVS_CL_CONFIG_VALUE_ORDER(3));
> + CMD_LOAD_STATE(cmdbuf, VIVS_VS_ICACHE_INVALIDATE, 0x1f);
> + CMD_LOAD_STATE(cmdbuf, VIVS_PS_VARYING_NUM_COMPONENTS(0), 0);
> + CMD_LOAD_STATE(cmdbuf, VIVS_PS_TEMP_REGISTER_CONTROL,
> + shader_register_count);
> + CMD_LOAD_STATE(cmdbuf, VIVS_PS_SAMPLER_BASE, 0x0);
> + CMD_LOAD_STATE(cmdbuf, VIVS_PS_UNIFORM_BASE, 0x0);
> + CMD_LOAD_STATE(cmdbuf, VIVS_PS_NEWRANGE_LOW, 0x0);
> + CMD_LOAD_STATE(cmdbuf, VIVS_PS_NEWRANGE_HIGH,
> + shader_size / 16);
> + CMD_LOAD_STATE(cmdbuf, VIVS_PS_INST_ADDR,
> + buffer_base + shader_offset);
> + CMD_LOAD_STATE(cmdbuf, VIVS_SH_CONFIG,
> + VIVS_SH_CONFIG_RTNE_ROUNDING);
> + CMD_LOAD_STATE(cmdbuf, VIVS_VS_ICACHE_CONTROL,
> + VIVS_VS_ICACHE_CONTROL_ENABLE);
> + CMD_LOAD_STATE(cmdbuf, VIVS_PS_ICACHE_COUNT,
> + shader_size / 16 - 1);
> + CMD_LOAD_STATE(cmdbuf, VIVS_PS_INPUT_COUNT, 0x1f01);
> + CMD_LOAD_STATE(cmdbuf, VIVS_VS_HALTI5_UNK008A0, 0x0);
> + CMD_LOAD_STATE(cmdbuf, VIVS_PA_VS_OUTPUT_COUNT, 0x0);
> + CMD_LOAD_STATE(cmdbuf, VIVS_GL_VARYING_TOTAL_COMPONENTS, 0x0);
> + CMD_LOAD_STATE(cmdbuf, VIVS_PS_CONTROL_EXT, 0x0);
> + CMD_LOAD_STATE(cmdbuf, VIVS_VS_OUTPUT_COUNT, 0x1);
> + CMD_LOAD_STATE(cmdbuf, VIVS_GL_HALTI5_SH_SPECIALS, 0x0);
> + CMD_LOAD_STATE(cmdbuf, VIVS_PS_ICACHE_PREFETCH, 0x0);
> + CMD_LOAD_STATE(cmdbuf, VIVS_CL_UNK00924, 0x0);
> + CMD_LOAD_STATE(cmdbuf, VIVS_CL_THREAD_ALLOCATION, 0x1);
> +
> + CMD_LOAD_STATE(cmdbuf, VIVS_CL_GLOBAL_WORK_OFFSET_X, 0x0);
> + CMD_LOAD_STATE(cmdbuf, VIVS_CL_GLOBAL_WORK_OFFSET_Y, 0x0);
> + CMD_LOAD_STATE(cmdbuf, VIVS_CL_GLOBAL_WORK_OFFSET_Z, 0x0);
> +
> + CMD_LOAD_STATES_START(cmdbuf, VIVS_CL_WORKGROUP_COUNT_X, 9);
> + OUT(cmdbuf, 0xf);
> + OUT(cmdbuf, 0x5);
> + OUT(cmdbuf, 0xffffffff);
> + OUT(cmdbuf, 0x0);
> + OUT(cmdbuf, 0x0);
> + OUT(cmdbuf, 0x3ff);
> + OUT(cmdbuf, 0x0);
> + OUT(cmdbuf, 0x4);
> + OUT(cmdbuf, 0x1);
> + OUT(cmdbuf, 0x0);
> +
> + CMD_LOAD_STATE(cmdbuf, VIVS_CL_KICKER, 0xbadabeeb);
> + CMD_LOAD_STATE(cmdbuf, VIVS_GL_FLUSH_CACHE,
> + VIVS_GL_FLUSH_CACHE_SHADER_L1 |
> + VIVS_GL_FLUSH_CACHE_UNK10 |
> + VIVS_GL_FLUSH_CACHE_UNK11);
> +}
> +
> +static void
> +etnaviv_flop_reset_ppu_fill_input(u32 *buffer, u32 size)
> +{
> + for (int i = 0; i < size/4; ++i, ++buffer)
> + *buffer = 0x01010101;
> +}
> +
> +static void
> +etnaviv_flop_reset_ppu_set_shader(u8 *dest)
> +{
> + const u32 inst[PPU_FLOP_RESET_INSTR_DWORD_COUNT] = {
> + /* img_load.u8 r1, c0, r0.xy */
> + 0x78011779, 0x39000804, 0x00A90050, 0x00000000,
> + /* img_load.u8 r2, c0, r0.xy */
> + 0x78021779, 0x39000804, 0x00A90050, 0x00000000,
> + /* dp2x8 r1, r1, r2, c3_512 */
> + 0xB8017145, 0x390018FC, 0x01C90140, 0x40390028,
> + /* img_store.u8 r1, c2, r0.xy, r1 */
> + 0x380007BA, 0x39001804, 0x00A90050, 0x00390018,
> + };
> + memcpy(dest, inst, sizeof(inst));
> +}
> +
> +static struct etnaviv_flop_reset_entry {
> + u16 chip_model;
> + u16 revision;
> + u32 flags;
> +} etnaviv_flop_reset_db [] = {
> + {
> + .chip_model = 0x8000,
> + .revision = 0x6205,
> + .flags = flop_reset_ppu
> + },
> +};
> +
> +bool
> +etnaviv_flop_reset_ppu_require(const struct etnaviv_chip_identity *chip_id)
> +{
> + const struct etnaviv_flop_reset_entry *e = etnaviv_flop_reset_db;
> +
> + for (int i = 0; i < ARRAY_SIZE(etnaviv_flop_reset_db); ++i, ++e) {
> + if (chip_id->model == e->chip_model &&
> + chip_id->revision == e->revision)
> + return (e->flags & flop_reset_ppu) != 0;
> + }
> +
> + return false;
> +}
> +
> +static const u32 image_data_size = PPU_IMAGE_STRIDE * PPU_IMAGE_YSIZE;
> +static const u32 output_offset = ALIGN(image_data_size, 64);
> +static const u32 shader_offset = ALIGN(output_offset + image_data_size, 64);
> +static const u32 shader_size = PPU_FLOP_RESET_INSTR_DWORD_COUNT * sizeof(u32);
> +static const u32 shader_register_count = 3;
> +static const u32 buffer_size = shader_offset + shader_size;
> +
> +void
> +etnaviv_flop_reset_ppu_init(struct etnaviv_drm_private *priv)
> +{
> + /* Get some space from the rung buffer to put the payload
^ ring
> + (input and output image, and shader), we keep this buffer
> + for the whole life time the driver is bound */
This isn't the comment style used throughout the driver.
> + priv->flop_reset_data_ppu =
> + kzalloc(sizeof(*priv->flop_reset_data_ppu), GFP_KERNEL);
> +
> + etnaviv_cmdbuf_init(priv->cmdbuf_suballoc,
> + priv->flop_reset_data_ppu, buffer_size);
> +
> + void *buffer_base = priv->flop_reset_data_ppu->vaddr;
> +
> + u32 *input_data = (u32 *)buffer_base;
> + etnaviv_flop_reset_ppu_fill_input(input_data, image_data_size);
> +
> + u8 *shader_data = (u8 *)buffer_base + shader_offset;
> + etnaviv_flop_reset_ppu_set_shader(shader_data);
> +}
> +
> +void
> +etnaviv_flop_reset_ppu_run(struct etnaviv_gpu *gpu)
> +{
> + struct etnaviv_drm_private *priv = gpu->drm->dev_private;
> +
> + if (!priv->flop_reset_data_ppu) {
> + pr_err("Flop reset data was not initialized, skipping\n");
> + return;
> + }
> +
> + u32 buffer_base = etnaviv_cmdbuf_get_va(priv->flop_reset_data_ppu,
> + &gpu->mmu_context->cmdbuf_mapping);
> +
> + etnaviv_emit_flop_reset_state_ppu(&gpu->buffer,
> + buffer_base,
> + 0,
> + output_offset,
> + shader_offset,
> + shader_size,
> + shader_register_count);
> +}
> diff --git a/drivers/gpu/drm/etnaviv/etnaviv_flop_reset.h b/drivers/gpu/drm/etnaviv/etnaviv_flop_reset.h
> new file mode 100644
> index 000000000000..f51cece75507
> --- /dev/null
> +++ b/drivers/gpu/drm/etnaviv/etnaviv_flop_reset.h
> @@ -0,0 +1,25 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * Copyright (C) 2025 Etnaviv Project
> + */
> +
> +
> +#ifndef etnaviv_flop_reset_h
> +#define etnaviv_flop_reset_h
> +
> +#include <linux/types.h>
> +
> +struct etnaviv_chip_identity;
> +struct etnaviv_drm_private;
> +struct etnaviv_gpu;
> +
> +bool
> +etnaviv_flop_reset_ppu_require(const struct etnaviv_chip_identity *chip_id);
> +
> +void
> +etnaviv_flop_reset_ppu_init(struct etnaviv_drm_private *priv);
> +
> +void
> +etnaviv_flop_reset_ppu_run(struct etnaviv_gpu *gpu);
> +
> +#endif
> diff --git a/drivers/gpu/drm/etnaviv/etnaviv_gpu.c b/drivers/gpu/drm/etnaviv/etnaviv_gpu.c
> index dc8a7ff3e797..0d1dc1b1d98d 100644
> --- a/drivers/gpu/drm/etnaviv/etnaviv_gpu.c
> +++ b/drivers/gpu/drm/etnaviv/etnaviv_gpu.c
> @@ -18,6 +18,7 @@
>
> #include "etnaviv_cmdbuf.h"
> #include "etnaviv_dump.h"
> +#include "etnaviv_flop_reset.h"
> #include "etnaviv_gpu.h"
> #include "etnaviv_gem.h"
> #include "etnaviv_mmu.h"
> @@ -1807,6 +1808,11 @@ static int etnaviv_gpu_bind(struct device *dev, struct device *master,
> ret = -ENXIO;
> goto out_sched;
> }
> +
> + if (etnaviv_flop_reset_ppu_require(&gpu->identity) &&
> + !priv->flop_reset_data_ppu)
> + etnaviv_flop_reset_ppu_init(priv);
> +
I don't see why you would need to do this in the bind callback. You
should be able to move this to etnaviv_gpu_init(), so you have the
needed identification data. gpu_init is also executed serially over all
GPUs in the device, so there is no problem with potential races there.
Regards,
Lucas
> priv->gpu[priv->num_gpus++] = gpu;
>
> return 0;
^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [PATCH v2 6/6] drm/etnaviv: Add module parameter to force PPU flop reset
2025-06-18 20:43 ` [PATCH v2 6/6] drm/etnaviv: Add module parameter to force " Gert Wollny
@ 2025-06-20 20:24 ` Lucas Stach
0 siblings, 0 replies; 18+ messages in thread
From: Lucas Stach @ 2025-06-20 20:24 UTC (permalink / raw)
To: Gert Wollny, Russell King, Christian Gmeiner
Cc: etnaviv, dri-devel, linux-kernel
Am Mittwoch, dem 18.06.2025 um 22:43 +0200 schrieb Gert Wollny:
> Signed-off-by: Gert Wollny <gert.wollny@collabora.com>
> ---
> drivers/gpu/drm/etnaviv/etnaviv_flop_reset.c | 9 +++++++++
> 1 file changed, 9 insertions(+)
>
> diff --git a/drivers/gpu/drm/etnaviv/etnaviv_flop_reset.c b/drivers/gpu/drm/etnaviv/etnaviv_flop_reset.c
> index c33647e96636..bf4cae4be815 100644
> --- a/drivers/gpu/drm/etnaviv/etnaviv_flop_reset.c
> +++ b/drivers/gpu/drm/etnaviv/etnaviv_flop_reset.c
> @@ -16,6 +16,9 @@ enum etnaviv_flop_reset_type {
> flop_reset_tp = 1 << 2
> };
>
> +static int etnaviv_force_flop_reset = 0;
> +module_param_named(force_flop_reset, etnaviv_force_flop_reset, int , 0);
> +
> #define PPU_IMAGE_STRIDE 64
> #define PPU_IMAGE_XSIZE 64
> #define PPU_IMAGE_YSIZE 6
> @@ -151,6 +154,12 @@ etnaviv_flop_reset_ppu_require(const struct etnaviv_chip_identity *chip_id)
> return (e->flags & flop_reset_ppu) != 0;
> }
>
> + if (etnaviv_force_flop_reset & flop_reset_ppu) {
This should at least check for chipFeatures_PIPE_3D, so you don't try
to run the flop reset on a 2D only GPU.
Regards,
Lucas
> + pr_warn("Forcing flop reset for model: 0x%04x, revision: 0x%04x\n",
> + chip_id->model, chip_id->revision);
> + return true;
> + }
> +
> return false;
> }
>
^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [PATCH v2 5/6] drm/etnaviv: Add PPU flop reset
2025-06-20 20:22 ` Lucas Stach
@ 2025-06-23 12:05 ` Gert Wollny
2025-06-23 12:25 ` Lucas Stach
0 siblings, 1 reply; 18+ messages in thread
From: Gert Wollny @ 2025-06-23 12:05 UTC (permalink / raw)
To: Lucas Stach, Russell King, Christian Gmeiner
Cc: etnaviv, dri-devel, linux-kernel
On Fri, 2025-06-20 at 22:22 +0200, Lucas Stach wrote:
>
> > @@ -1807,6 +1808,11 @@ static int etnaviv_gpu_bind(struct device
> > *dev, struct device *master,
> > ret = -ENXIO;
> > goto out_sched;
> > }
> > +
> > + if (etnaviv_flop_reset_ppu_require(&gpu->identity) &&
> > + !priv->flop_reset_data_ppu)
> > + etnaviv_flop_reset_ppu_init(priv);
> > +
> I don't see why you would need to do this in the bind callback. You
> should be able to move this to etnaviv_gpu_init(), so you have the
> needed identification data. gpu_init is also executed serially over
> all GPUs in the device, so there is no problem with potential races
> there.
I moved this here because you wrote before:
> But then you should allocate this buffer
> in etnaviv_gpu_bind to avoid races between GPUs starting up and
> trying to allocate this global memory.
If etnaviv_gpu_init() is fine, I'll move it there.
Regards,
Gert
^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [PATCH v2 5/6] drm/etnaviv: Add PPU flop reset
2025-06-23 12:05 ` Gert Wollny
@ 2025-06-23 12:25 ` Lucas Stach
0 siblings, 0 replies; 18+ messages in thread
From: Lucas Stach @ 2025-06-23 12:25 UTC (permalink / raw)
To: Gert Wollny, Russell King, Christian Gmeiner
Cc: etnaviv, dri-devel, linux-kernel
Am Montag, dem 23.06.2025 um 14:05 +0200 schrieb Gert Wollny:
> On Fri, 2025-06-20 at 22:22 +0200, Lucas Stach wrote:
> >
> > > @@ -1807,6 +1808,11 @@ static int etnaviv_gpu_bind(struct device
> > > *dev, struct device *master,
> > > ret = -ENXIO;
> > > goto out_sched;
> > > }
> > > +
> > > + if (etnaviv_flop_reset_ppu_require(&gpu->identity) &&
> > > + !priv->flop_reset_data_ppu)
> > > + etnaviv_flop_reset_ppu_init(priv);
> > > +
> > I don't see why you would need to do this in the bind callback. You
> > should be able to move this to etnaviv_gpu_init(), so you have the
> > needed identification data. gpu_init is also executed serially over
> > all GPUs in the device, so there is no problem with potential races
> > there.
>
> I moved this here because you wrote before:
>
> > But then you should allocate this buffer
> > in etnaviv_gpu_bind to avoid races between GPUs starting up and
> > trying to allocate this global memory.
>
Yea, sorry about this. I hadn't noticed the dependency on the HW
identification when I wrote this.
> If etnaviv_gpu_init() is fine, I'll move it there.
I'm not saying that I may not again miss some implicit dependency, but
as far as I can see right now moving it there should be fine.
gpu_init() fulfills the same properties with regard to init ordering
between the GPUs as gpu_bind().
Regards,
Lucas
^ permalink raw reply [flat|nested] 18+ messages in thread
* [PATCH v3 0/5] drm/etnaviv: Add support for running a PPU flop reset
2025-06-18 20:43 drm/etnaviv: Add support for running a PPU flop reset Gert Wollny
` (5 preceding siblings ...)
2025-06-18 20:43 ` [PATCH v2 6/6] drm/etnaviv: Add module parameter to force " Gert Wollny
@ 2025-06-30 20:26 ` Gert Wollny
2025-06-30 20:26 ` [PATCH v3 1/5] drm/etnaviv: Add command stream definitions required for " Gert Wollny
` (4 more replies)
6 siblings, 5 replies; 18+ messages in thread
From: Gert Wollny @ 2025-06-30 20:26 UTC (permalink / raw)
To: Lucas Stach, Russell King, Christian Gmeiner, David Airlie,
Daniel Vetter
Cc: etnaviv, dri-devel, linux-kernel
Dear all,
this is the third version of the series to add PPU flop reset.
Changes w.r.t. the previous version are:
* initialize the PPU flop reset data in etnaviv_gpu_init (Lucas)
- consequently drop the patch to identify GPU earlier
* also test feature PIPE_3D when forcing the flop reset (Lucas)
* move a few defines around and fix formatting in some places
Many thanks for any comments,
Gert
[PATCH v3 1/5] drm/etnaviv: Add command stream definitions required
[PATCH v3 2/5] drm/etnaviv: move some functions to a header to be
[PATCH v3 3/5] drm/etnaviv: Add a new function to emit a series of
[PATCH v3 4/5] drm/etnaviv: Add PPU flop reset
[PATCH v3 5/5] drm/etnaviv: Add module parameter to force PPU flop
^ permalink raw reply [flat|nested] 18+ messages in thread
* [PATCH v3 1/5] drm/etnaviv: Add command stream definitions required for a PPU flop reset
2025-06-30 20:26 ` [PATCH v3 0/5] drm/etnaviv: Add support for running a " Gert Wollny
@ 2025-06-30 20:26 ` Gert Wollny
2025-06-30 20:26 ` [PATCH v3 2/5] drm/etnaviv: move some functions to a header to be able to use them externally Gert Wollny
` (3 subsequent siblings)
4 siblings, 0 replies; 18+ messages in thread
From: Gert Wollny @ 2025-06-30 20:26 UTC (permalink / raw)
To: Lucas Stach, Russell King, Christian Gmeiner, David Airlie,
Daniel Vetter
Cc: etnaviv, dri-devel, linux-kernel, Gert Wollny
v2: move some defines that resided in etnaviv_flop_reset.c
into the header as well
v3: fix spacing/tab stops
Signed-off-by: Gert Wollny <gert.wollny@collabora.com>
---
drivers/gpu/drm/etnaviv/state_3d.xml.h | 97 ++++++++++++++++++++++++++
1 file changed, 97 insertions(+)
diff --git a/drivers/gpu/drm/etnaviv/state_3d.xml.h b/drivers/gpu/drm/etnaviv/state_3d.xml.h
index ebbd4fcf3096..b9e9b78df074 100644
--- a/drivers/gpu/drm/etnaviv/state_3d.xml.h
+++ b/drivers/gpu/drm/etnaviv/state_3d.xml.h
@@ -4,6 +4,103 @@
/* This is a cut-down version of the state_3d.xml.h file */
+#define VIVS_CL_CONFIG 0x00000900
+#define VIVS_CL_CONFIG_DIMENSIONS__MASK 0x00000003
+#define VIVS_CL_CONFIG_DIMENSIONS__SHIFT 0
+#define VIVS_CL_CONFIG_DIMENSIONS(x) (((x) << VIVS_CL_CONFIG_DIMENSIONS__SHIFT) & VIVS_CL_CONFIG_DIMENSIONS__MASK)
+#define VIVS_CL_CONFIG_TRAVERSE_ORDER__MASK 0x00000070
+#define VIVS_CL_CONFIG_TRAVERSE_ORDER__SHIFT 4
+#define VIVS_CL_CONFIG_TRAVERSE_ORDER(x) (((x) << VIVS_CL_CONFIG_TRAVERSE_ORDER__SHIFT) & VIVS_CL_CONFIG_TRAVERSE_ORDER__MASK)
+#define VIVS_CL_CONFIG_ENABLE_SWATH_X 0x00000100
+#define VIVS_CL_CONFIG_ENABLE_SWATH_Y 0x00000200
+#define VIVS_CL_CONFIG_ENABLE_SWATH_Z 0x00000400
+#define VIVS_CL_CONFIG_SWATH_SIZE_X__MASK 0x0000f000
+#define VIVS_CL_CONFIG_SWATH_SIZE_X__SHIFT 12
+#define VIVS_CL_CONFIG_SWATH_SIZE_X(x) (((x) << VIVS_CL_CONFIG_SWATH_SIZE_X__SHIFT) & VIVS_CL_CONFIG_SWATH_SIZE_X__MASK)
+#define VIVS_CL_CONFIG_SWATH_SIZE_Y__MASK 0x000f0000
+#define VIVS_CL_CONFIG_SWATH_SIZE_Y__SHIFT 16
+#define VIVS_CL_CONFIG_SWATH_SIZE_Y(x) (((x) << VIVS_CL_CONFIG_SWATH_SIZE_Y__SHIFT) & VIVS_CL_CONFIG_SWATH_SIZE_Y__MASK)
+#define VIVS_CL_CONFIG_SWATH_SIZE_Z__MASK 0x00f00000
+#define VIVS_CL_CONFIG_SWATH_SIZE_Z__SHIFT 20
+#define VIVS_CL_CONFIG_SWATH_SIZE_Z(x) (((x) << VIVS_CL_CONFIG_SWATH_SIZE_Z__SHIFT) & VIVS_CL_CONFIG_SWATH_SIZE_Z__MASK)
+
+#define VIVS_CL_CONFIG_DIMENSIONS__MASK 0x00000003
+#define VIVS_CL_CONFIG_DIMENSIONS__SHIFT 0
+#define VIVS_CL_CONFIG_DIMENSIONS(x) (((x) << VIVS_CL_CONFIG_DIMENSIONS__SHIFT) & VIVS_CL_CONFIG_DIMENSIONS__MASK)
+
+#define VIVS_CL_CONFIG_VALUE_ORDER__MASK 0x07000000
+#define VIVS_CL_CONFIG_VALUE_ORDER__SHIFT 24
+#define VIVS_CL_CONFIG_VALUE_ORDER(x) (((x) << VIVS_CL_CONFIG_VALUE_ORDER__SHIFT) & VIVS_CL_CONFIG_VALUE_ORDER__MASK)
+
+#define VIVS_CL_GLOBAL_WORK_OFFSET_X 0x0000092c
+#define VIVS_CL_GLOBAL_WORK_OFFSET_Y 0x00000934
+#define VIVS_CL_GLOBAL_WORK_OFFSET_Z 0x0000093c
+
+#define VIVS_CL_KICKER 0x00000920
+#define VIVS_CL_THREAD_ALLOCATION 0x0000091c
+#define VIVS_CL_UNK00924 0x00000924
+
+#define VIVS_CL_WORKGROUP_COUNT_X 0x00000940
+#define VIVS_CL_WORKGROUP_COUNT_Y 0x00000944
+#define VIVS_CL_WORKGROUP_COUNT_Z 0x00000948
+#define VIVS_CL_WORKGROUP_SIZE_X 0x0000094c
+#define VIVS_CL_WORKGROUP_SIZE_Y 0x00000950
+#define VIVS_CL_WORKGROUP_SIZE_Z 0x00000954
+
+#define VIVS_CL_GLOBAL_SCALE_X 0x00000958
+#define VIVS_CL_GLOBAL_SCALE_Y 0x0000095c
+#define VIVS_CL_GLOBAL_SCALE_Z 0x00000960
+
+#define VIVS_PA_VS_OUTPUT_COUNT 0x00000aa8
+#define VIVS_PS_CONTROL_EXT 0x00001030
+#define VIVS_PS_ICACHE_COUNT 0x00001094
+#define VIVS_PS_ICACHE_PREFETCH 0x00001048
+
+#define VIVS_PS_INPUT_COUNT 0x00001008
+#define VIVS_PS_INPUT_COUNT_COUNT__MASK 0x0000001f
+#define VIVS_PS_INPUT_COUNT_COUNT__SHIFT 0
+#define VIVS_PS_INPUT_COUNT_COUNT(x) (((x) << VIVS_PS_INPUT_COUNT_COUNT__SHIFT) & VIVS_PS_INPUT_COUNT_COUNT__MASK)
+
+
+#define VIVS_PS_NEWRANGE_LOW 0x0000087c
+#define VIVS_PS_NEWRANGE_HIGH 0x00001090
+#define VIVS_PS_SAMPLER_BASE 0x00001058
+
+#define VIVS_PS_UNIFORM_BASE 0x00001024
+#define VIVS_PS_INST_ADDR 0x00001028
+
+#define VIVS_PS_TEMP_REGISTER_CONTROL 0x0000100c
+#define VIVS_PS_TEMP_REGISTER_CONTROL_NUM_TEMPS__MASK 0x0000003f
+#define VIVS_PS_TEMP_REGISTER_CONTROL_NUM_TEMPS__SHIFT 0
+#define VIVS_PS_TEMP_REGISTER_CONTROL_NUM_TEMPS(x) (((x) << VIVS_PS_TEMP_REGISTER_CONTROL_NUM_TEMPS__SHIFT) & VIVS_PS_TEMP_REGISTER_CONTROL_NUM_TEMPS__MASK)
+
+#define VIVS_PS_VARYING_NUM_COMPONENTS(i0) (0x00001080 + 0x4*(i0))
+#define VIVS_PS_VARYING_NUM_COMPONENTS__ESIZE 0x00000004
+#define VIVS_PS_VARYING_NUM_COMPONENTS__LEN 0x00000004
+
+#define VIVS_SH_CONFIG 0x00015600
+#define VIVS_SH_CONFIG_RTNE_ROUNDING 0x00000002
+
+#define VIVS_SH_HALTI5_UNIFORMS(i0) (0x00036000 + 0x4*(i0))
+#define VIVS_SH_HALTI5_UNIFORMS__ESIZE 0x00000004
+#define VIVS_SH_HALTI5_UNIFORMS__LEN 0x00000800
+
+#define VIVS_VS_HALTI5_UNK008A0 0x000008a0
+#define VIVS_VS_HALTI5_UNK008A0_A__MASK 0x0000003f
+#define VIVS_VS_HALTI5_UNK008A0_A__SHIFT 0
+#define VIVS_VS_HALTI5_UNK008A0_A(x) (((x) << VIVS_VS_HALTI5_UNK008A0_A__SHIFT) & VIVS_VS_HALTI5_UNK008A0_A__MASK)
+
+
+#define VIVS_VS_ICACHE_CONTROL 0x00000868
+#define VIVS_VS_ICACHE_CONTROL_ENABLE 0x00000001
+
+#define VIVS_VS_ICACHE_INVALIDATE 0x000008b0
+
+#define VIVS_VS_OUTPUT_COUNT 0x00000804
+#define VIVS_VS_OUTPUT_COUNT_COUNT__MASK 0x000000ff
+#define VIVS_VS_OUTPUT_COUNT_COUNT__SHIFT 0
+#define VIVS_VS_OUTPUT_COUNT_COUNT(x) (((x) << VIVS_VS_OUTPUT_COUNT_COUNT__SHIFT) & VIVS_VS_OUTPUT_COUNT_COUNT__MASK)
+
#define VIVS_TS_FLUSH_CACHE 0x00001650
#define VIVS_TS_FLUSH_CACHE_FLUSH 0x00000001
--
2.49.0
^ permalink raw reply related [flat|nested] 18+ messages in thread
* [PATCH v3 2/5] drm/etnaviv: move some functions to a header to be able to use them externally
2025-06-30 20:26 ` [PATCH v3 0/5] drm/etnaviv: Add support for running a " Gert Wollny
2025-06-30 20:26 ` [PATCH v3 1/5] drm/etnaviv: Add command stream definitions required for " Gert Wollny
@ 2025-06-30 20:26 ` Gert Wollny
2025-06-30 20:26 ` [PATCH v3 3/5] drm/etnaviv: Add a new function to emit a series of states to cmd stream Gert Wollny
` (2 subsequent siblings)
4 siblings, 0 replies; 18+ messages in thread
From: Gert Wollny @ 2025-06-30 20:26 UTC (permalink / raw)
To: Lucas Stach, Russell King, Christian Gmeiner, David Airlie,
Daniel Vetter
Cc: etnaviv, dri-devel, linux-kernel, Gert Wollny
Signed-off-by: Gert Wollny <gert.wollny@collabora.com>
---
drivers/gpu/drm/etnaviv/etnaviv_buffer.c | 71 +-------------------
drivers/gpu/drm/etnaviv/etnaviv_buffer.h | 85 ++++++++++++++++++++++++
2 files changed, 86 insertions(+), 70 deletions(-)
create mode 100644 drivers/gpu/drm/etnaviv/etnaviv_buffer.h
diff --git a/drivers/gpu/drm/etnaviv/etnaviv_buffer.c b/drivers/gpu/drm/etnaviv/etnaviv_buffer.c
index b13a17276d07..9e007d977efe 100644
--- a/drivers/gpu/drm/etnaviv/etnaviv_buffer.c
+++ b/drivers/gpu/drm/etnaviv/etnaviv_buffer.c
@@ -9,6 +9,7 @@
#include "etnaviv_gpu.h"
#include "etnaviv_gem.h"
#include "etnaviv_mmu.h"
+#include "etnaviv_buffer.h"
#include "common.xml.h"
#include "state.xml.h"
@@ -17,76 +18,6 @@
#include "state_3d.xml.h"
#include "cmdstream.xml.h"
-/*
- * Command Buffer helper:
- */
-
-
-static inline void OUT(struct etnaviv_cmdbuf *buffer, u32 data)
-{
- u32 *vaddr = (u32 *)buffer->vaddr;
-
- BUG_ON(buffer->user_size >= buffer->size);
-
- vaddr[buffer->user_size / 4] = data;
- buffer->user_size += 4;
-}
-
-static inline void CMD_LOAD_STATE(struct etnaviv_cmdbuf *buffer,
- u32 reg, u32 value)
-{
- u32 index = reg >> VIV_FE_LOAD_STATE_HEADER_OFFSET__SHR;
-
- buffer->user_size = ALIGN(buffer->user_size, 8);
-
- /* write a register via cmd stream */
- OUT(buffer, VIV_FE_LOAD_STATE_HEADER_OP_LOAD_STATE |
- VIV_FE_LOAD_STATE_HEADER_COUNT(1) |
- VIV_FE_LOAD_STATE_HEADER_OFFSET(index));
- OUT(buffer, value);
-}
-
-static inline void CMD_END(struct etnaviv_cmdbuf *buffer)
-{
- buffer->user_size = ALIGN(buffer->user_size, 8);
-
- OUT(buffer, VIV_FE_END_HEADER_OP_END);
-}
-
-static inline void CMD_WAIT(struct etnaviv_cmdbuf *buffer,
- unsigned int waitcycles)
-{
- buffer->user_size = ALIGN(buffer->user_size, 8);
-
- OUT(buffer, VIV_FE_WAIT_HEADER_OP_WAIT | waitcycles);
-}
-
-static inline void CMD_LINK(struct etnaviv_cmdbuf *buffer,
- u16 prefetch, u32 address)
-{
- buffer->user_size = ALIGN(buffer->user_size, 8);
-
- OUT(buffer, VIV_FE_LINK_HEADER_OP_LINK |
- VIV_FE_LINK_HEADER_PREFETCH(prefetch));
- OUT(buffer, address);
-}
-
-static inline void CMD_STALL(struct etnaviv_cmdbuf *buffer,
- u32 from, u32 to)
-{
- buffer->user_size = ALIGN(buffer->user_size, 8);
-
- OUT(buffer, VIV_FE_STALL_HEADER_OP_STALL);
- OUT(buffer, VIV_FE_STALL_TOKEN_FROM(from) | VIV_FE_STALL_TOKEN_TO(to));
-}
-
-static inline void CMD_SEM(struct etnaviv_cmdbuf *buffer, u32 from, u32 to)
-{
- CMD_LOAD_STATE(buffer, VIVS_GL_SEMAPHORE_TOKEN,
- VIVS_GL_SEMAPHORE_TOKEN_FROM(from) |
- VIVS_GL_SEMAPHORE_TOKEN_TO(to));
-}
-
static void etnaviv_cmd_select_pipe(struct etnaviv_gpu *gpu,
struct etnaviv_cmdbuf *buffer, u8 pipe)
{
diff --git a/drivers/gpu/drm/etnaviv/etnaviv_buffer.h b/drivers/gpu/drm/etnaviv/etnaviv_buffer.h
new file mode 100644
index 000000000000..caf820d91ef5
--- /dev/null
+++ b/drivers/gpu/drm/etnaviv/etnaviv_buffer.h
@@ -0,0 +1,85 @@
+
+
+#ifndef etnaviv_buffer_h
+#define etnaviv_buffer_h
+
+#include "etnaviv_cmdbuf.h"
+#include "etnaviv_gpu.h"
+#include "etnaviv_gem.h"
+#include "etnaviv_mmu.h"
+
+#include "common.xml.h"
+#include "linux/printk.h"
+#include "state.xml.h"
+#include "state_blt.xml.h"
+#include "state_hi.xml.h"
+#include "state_3d.xml.h"
+#include "cmdstream.xml.h"
+
+static inline void OUT(struct etnaviv_cmdbuf *buffer, u32 data)
+{
+ u32 *vaddr = (u32 *)buffer->vaddr;
+
+ BUG_ON(buffer->user_size >= buffer->size);
+
+ vaddr[buffer->user_size / 4] = data;
+ buffer->user_size += 4;
+}
+
+static inline void CMD_LOAD_STATE(struct etnaviv_cmdbuf *buffer,
+ u32 reg, u32 value)
+{
+
+ u32 index = reg >> VIV_FE_LOAD_STATE_HEADER_OFFSET__SHR;
+
+ buffer->user_size = ALIGN(buffer->user_size, 8);
+
+ /* write a register via cmd stream */
+ OUT(buffer, VIV_FE_LOAD_STATE_HEADER_OP_LOAD_STATE |
+ VIV_FE_LOAD_STATE_HEADER_COUNT(1) |
+ VIV_FE_LOAD_STATE_HEADER_OFFSET(index));
+ OUT(buffer, value);
+}
+
+static inline void CMD_END(struct etnaviv_cmdbuf *buffer)
+{
+ buffer->user_size = ALIGN(buffer->user_size, 8);
+
+ OUT(buffer, VIV_FE_END_HEADER_OP_END);
+}
+
+static inline void CMD_WAIT(struct etnaviv_cmdbuf *buffer,
+ unsigned int waitcycles)
+{
+ buffer->user_size = ALIGN(buffer->user_size, 8);
+
+ OUT(buffer, VIV_FE_WAIT_HEADER_OP_WAIT | waitcycles);
+}
+
+static inline void CMD_LINK(struct etnaviv_cmdbuf *buffer,
+ u16 prefetch, u32 address)
+{
+ buffer->user_size = ALIGN(buffer->user_size, 8);
+
+ OUT(buffer, VIV_FE_LINK_HEADER_OP_LINK |
+ VIV_FE_LINK_HEADER_PREFETCH(prefetch));
+ OUT(buffer, address);
+}
+
+static inline void CMD_STALL(struct etnaviv_cmdbuf *buffer,
+ u32 from, u32 to)
+{
+ buffer->user_size = ALIGN(buffer->user_size, 8);
+
+ OUT(buffer, VIV_FE_STALL_HEADER_OP_STALL);
+ OUT(buffer, VIV_FE_STALL_TOKEN_FROM(from) | VIV_FE_STALL_TOKEN_TO(to));
+}
+
+static inline void CMD_SEM(struct etnaviv_cmdbuf *buffer, u32 from, u32 to)
+{
+ CMD_LOAD_STATE(buffer, VIVS_GL_SEMAPHORE_TOKEN,
+ VIVS_GL_SEMAPHORE_TOKEN_FROM(from) |
+ VIVS_GL_SEMAPHORE_TOKEN_TO(to));
+}
+
+#endif
--
2.49.0
^ permalink raw reply related [flat|nested] 18+ messages in thread
* [PATCH v3 3/5] drm/etnaviv: Add a new function to emit a series of states to cmd stream
2025-06-30 20:26 ` [PATCH v3 0/5] drm/etnaviv: Add support for running a " Gert Wollny
2025-06-30 20:26 ` [PATCH v3 1/5] drm/etnaviv: Add command stream definitions required for " Gert Wollny
2025-06-30 20:26 ` [PATCH v3 2/5] drm/etnaviv: move some functions to a header to be able to use them externally Gert Wollny
@ 2025-06-30 20:26 ` Gert Wollny
2025-06-30 20:26 ` [PATCH v3 4/5] drm/etnaviv: Add PPU flop reset Gert Wollny
2025-06-30 20:26 ` [PATCH v3 5/5] drm/etnaviv: Add module parameter to force " Gert Wollny
4 siblings, 0 replies; 18+ messages in thread
From: Gert Wollny @ 2025-06-30 20:26 UTC (permalink / raw)
To: Lucas Stach, Russell King, Christian Gmeiner, David Airlie,
Daniel Vetter
Cc: etnaviv, dri-devel, linux-kernel, Gert Wollny
v2: fix formatting and remove superfluous masking (Lucas)
Signed-off-by: Gert Wollny <gert.wollny@collabora.com>
---
drivers/gpu/drm/etnaviv/etnaviv_buffer.h | 13 +++++++++++++
1 file changed, 13 insertions(+)
diff --git a/drivers/gpu/drm/etnaviv/etnaviv_buffer.h b/drivers/gpu/drm/etnaviv/etnaviv_buffer.h
index caf820d91ef5..842a7ca55c44 100644
--- a/drivers/gpu/drm/etnaviv/etnaviv_buffer.h
+++ b/drivers/gpu/drm/etnaviv/etnaviv_buffer.h
@@ -41,6 +41,19 @@ static inline void CMD_LOAD_STATE(struct etnaviv_cmdbuf *buffer,
OUT(buffer, value);
}
+static inline void CMD_LOAD_STATES_START(struct etnaviv_cmdbuf *buffer,
+ u32 reg, u32 nvalues)
+{
+ u32 index = reg >> VIV_FE_LOAD_STATE_HEADER_OFFSET__SHR;
+
+ buffer->user_size = ALIGN(buffer->user_size, 8);
+
+ /* write a register via cmd stream */
+ OUT(buffer, VIV_FE_LOAD_STATE_HEADER_OP_LOAD_STATE |
+ VIV_FE_LOAD_STATE_HEADER_OFFSET(index) |
+ VIV_FE_LOAD_STATE_HEADER_COUNT(nvalues));
+}
+
static inline void CMD_END(struct etnaviv_cmdbuf *buffer)
{
buffer->user_size = ALIGN(buffer->user_size, 8);
--
2.49.0
^ permalink raw reply related [flat|nested] 18+ messages in thread
* [PATCH v3 4/5] drm/etnaviv: Add PPU flop reset
2025-06-30 20:26 ` [PATCH v3 0/5] drm/etnaviv: Add support for running a " Gert Wollny
` (2 preceding siblings ...)
2025-06-30 20:26 ` [PATCH v3 3/5] drm/etnaviv: Add a new function to emit a series of states to cmd stream Gert Wollny
@ 2025-06-30 20:26 ` Gert Wollny
2025-06-30 20:26 ` [PATCH v3 5/5] drm/etnaviv: Add module parameter to force " Gert Wollny
4 siblings, 0 replies; 18+ messages in thread
From: Gert Wollny @ 2025-06-30 20:26 UTC (permalink / raw)
To: Lucas Stach, Russell King, Christian Gmeiner, David Airlie,
Daniel Vetter
Cc: etnaviv, dri-devel, linux-kernel, Gert Wollny
The PPU flop reset is required on some hardware to clear the
temporary registers. This code follows the implementation
of the PPU flop reset as found in the public galcore kernel
module. Compared to that code some superfluous parts were
removed and only the code path for SoC chip_model = 0x8000
and revision = 0x6205 is implemented and tested.
v2: - Move flop reset data to etnaviv_drm_private and initialize it
from etnaviv_gpu_bind (Lucas)
- Prepare code for more chip IDs and other flop reset types
- Do some cleanups and rename some functions
v3: - Move initialization of flop reset data to etnaviv_gpu_init (Lucas)
- Free PPU data suballocation (Lucas)
Signed-off-by: Gert Wollny <gert.wollny@collabora.com>
---
drivers/gpu/drm/etnaviv/Makefile | 1 +
drivers/gpu/drm/etnaviv/etnaviv_buffer.c | 6 +
drivers/gpu/drm/etnaviv/etnaviv_drv.c | 3 +
drivers/gpu/drm/etnaviv/etnaviv_drv.h | 3 +
drivers/gpu/drm/etnaviv/etnaviv_flop_reset.c | 206 +++++++++++++++++++
drivers/gpu/drm/etnaviv/etnaviv_flop_reset.h | 25 +++
drivers/gpu/drm/etnaviv/etnaviv_gpu.c | 5 +
7 files changed, 249 insertions(+)
create mode 100644 drivers/gpu/drm/etnaviv/etnaviv_flop_reset.c
create mode 100644 drivers/gpu/drm/etnaviv/etnaviv_flop_reset.h
diff --git a/drivers/gpu/drm/etnaviv/Makefile b/drivers/gpu/drm/etnaviv/Makefile
index 46e5ffad69a6..903101e8751a 100644
--- a/drivers/gpu/drm/etnaviv/Makefile
+++ b/drivers/gpu/drm/etnaviv/Makefile
@@ -14,6 +14,7 @@ etnaviv-y := \
etnaviv_iommu.o \
etnaviv_mmu.o \
etnaviv_perfmon.o \
+ etnaviv_flop_reset.o \
etnaviv_sched.o
obj-$(CONFIG_DRM_ETNAVIV) += etnaviv.o
diff --git a/drivers/gpu/drm/etnaviv/etnaviv_buffer.c b/drivers/gpu/drm/etnaviv/etnaviv_buffer.c
index 9e007d977efe..a2da3212592f 100644
--- a/drivers/gpu/drm/etnaviv/etnaviv_buffer.c
+++ b/drivers/gpu/drm/etnaviv/etnaviv_buffer.c
@@ -18,6 +18,8 @@
#include "state_3d.xml.h"
#include "cmdstream.xml.h"
+#include "etnaviv_flop_reset.h"
+
static void etnaviv_cmd_select_pipe(struct etnaviv_gpu *gpu,
struct etnaviv_cmdbuf *buffer, u8 pipe)
{
@@ -100,6 +102,10 @@ u16 etnaviv_buffer_init(struct etnaviv_gpu *gpu)
/* initialize buffer */
buffer->user_size = 0;
+ /* Queue in PPU flop reset */
+ if (etnaviv_flop_reset_ppu_require(&gpu->identity))
+ etnaviv_flop_reset_ppu_run(gpu);
+
CMD_WAIT(buffer, gpu->fe_waitcycles);
CMD_LINK(buffer, 2,
etnaviv_cmdbuf_get_va(buffer, &gpu->mmu_context->cmdbuf_mapping)
diff --git a/drivers/gpu/drm/etnaviv/etnaviv_drv.c b/drivers/gpu/drm/etnaviv/etnaviv_drv.c
index 3e91747ed339..0e916e6785c8 100644
--- a/drivers/gpu/drm/etnaviv/etnaviv_drv.c
+++ b/drivers/gpu/drm/etnaviv/etnaviv_drv.c
@@ -600,6 +600,9 @@ static void etnaviv_unbind(struct device *dev)
component_unbind_all(dev, drm);
+ etnaviv_cmdbuf_free(priv->flop_reset_data_ppu);
+ kfree(priv->flop_reset_data_ppu);
+
etnaviv_cmdbuf_suballoc_destroy(priv->cmdbuf_suballoc);
xa_destroy(&priv->active_contexts);
diff --git a/drivers/gpu/drm/etnaviv/etnaviv_drv.h b/drivers/gpu/drm/etnaviv/etnaviv_drv.h
index b3eb1662e90c..20dad16fd554 100644
--- a/drivers/gpu/drm/etnaviv/etnaviv_drv.h
+++ b/drivers/gpu/drm/etnaviv/etnaviv_drv.h
@@ -48,6 +48,9 @@ struct etnaviv_drm_private {
/* list of GEM objects: */
struct mutex gem_lock;
struct list_head gem_list;
+
+ /* ppu flop reset data */
+ struct etnaviv_cmdbuf *flop_reset_data_ppu;
};
int etnaviv_ioctl_gem_submit(struct drm_device *dev, void *data,
diff --git a/drivers/gpu/drm/etnaviv/etnaviv_flop_reset.c b/drivers/gpu/drm/etnaviv/etnaviv_flop_reset.c
new file mode 100644
index 000000000000..138af3c33b5d
--- /dev/null
+++ b/drivers/gpu/drm/etnaviv/etnaviv_flop_reset.c
@@ -0,0 +1,206 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2025 Etnaviv Project
+ */
+
+#include "asm-generic/int-ll64.h"
+#include "etnaviv_buffer.h"
+#include "etnaviv_cmdbuf.h"
+#include "state_3d.xml.h"
+
+#include "etnaviv_flop_reset.h"
+
+enum etnaviv_flop_reset_type {
+ flop_reset_ppu = 1 << 0,
+ flop_reset_nn = 1 << 1,
+ flop_reset_tp = 1 << 2
+};
+
+#define PPU_IMAGE_STRIDE 64
+#define PPU_IMAGE_XSIZE 64
+#define PPU_IMAGE_YSIZE 6
+
+#define PPU_FLOP_RESET_INSTR_DWORD_COUNT 16
+
+static void
+etnaviv_emit_flop_reset_state_ppu(struct etnaviv_cmdbuf *cmdbuf,
+ u32 buffer_base,
+ u32 input_offset,
+ u32 output_offset,
+ u32 shader_offset,
+ u32 shader_size,
+ u32 shader_register_count)
+{
+ CMD_LOAD_STATE(cmdbuf, VIVS_GL_API_MODE,
+ VIVS_GL_API_MODE_OPENCL);
+ CMD_SEM(cmdbuf, SYNC_RECIPIENT_FE, SYNC_RECIPIENT_PE);
+ CMD_STALL(cmdbuf, SYNC_RECIPIENT_FE, SYNC_RECIPIENT_PE);
+
+ CMD_LOAD_STATES_START(cmdbuf, VIVS_SH_HALTI5_UNIFORMS(0), 4);
+
+ OUT(cmdbuf, buffer_base + input_offset);
+ OUT(cmdbuf, PPU_IMAGE_STRIDE);
+ OUT(cmdbuf, PPU_IMAGE_XSIZE | (PPU_IMAGE_YSIZE << 16));
+ OUT(cmdbuf, 0x444051f0);
+ OUT(cmdbuf, 0xffffffff);
+
+ CMD_LOAD_STATES_START(cmdbuf, VIVS_SH_HALTI5_UNIFORMS(4), 4);
+ OUT(cmdbuf, buffer_base + output_offset);
+ OUT(cmdbuf, PPU_IMAGE_STRIDE);
+ OUT(cmdbuf, PPU_IMAGE_XSIZE | (PPU_IMAGE_YSIZE << 16));
+ OUT(cmdbuf, 0x444051f0);
+ OUT(cmdbuf, 0xffffffff);
+
+ CMD_LOAD_STATE(cmdbuf, VIVS_CL_CONFIG,
+ VIVS_CL_CONFIG_DIMENSIONS(2) |
+ VIVS_CL_CONFIG_VALUE_ORDER(3));
+ CMD_LOAD_STATE(cmdbuf, VIVS_VS_ICACHE_INVALIDATE, 0x1f);
+ CMD_LOAD_STATE(cmdbuf, VIVS_PS_VARYING_NUM_COMPONENTS(0), 0);
+ CMD_LOAD_STATE(cmdbuf, VIVS_PS_TEMP_REGISTER_CONTROL,
+ shader_register_count);
+ CMD_LOAD_STATE(cmdbuf, VIVS_PS_SAMPLER_BASE, 0x0);
+ CMD_LOAD_STATE(cmdbuf, VIVS_PS_UNIFORM_BASE, 0x0);
+ CMD_LOAD_STATE(cmdbuf, VIVS_PS_NEWRANGE_LOW, 0x0);
+ CMD_LOAD_STATE(cmdbuf, VIVS_PS_NEWRANGE_HIGH,
+ shader_size / 16);
+ CMD_LOAD_STATE(cmdbuf, VIVS_PS_INST_ADDR,
+ buffer_base + shader_offset);
+ CMD_LOAD_STATE(cmdbuf, VIVS_SH_CONFIG,
+ VIVS_SH_CONFIG_RTNE_ROUNDING);
+ CMD_LOAD_STATE(cmdbuf, VIVS_VS_ICACHE_CONTROL,
+ VIVS_VS_ICACHE_CONTROL_ENABLE);
+ CMD_LOAD_STATE(cmdbuf, VIVS_PS_ICACHE_COUNT,
+ shader_size / 16 - 1);
+ CMD_LOAD_STATE(cmdbuf, VIVS_PS_INPUT_COUNT, 0x1f01);
+ CMD_LOAD_STATE(cmdbuf, VIVS_VS_HALTI5_UNK008A0, 0x0);
+ CMD_LOAD_STATE(cmdbuf, VIVS_PA_VS_OUTPUT_COUNT, 0x0);
+ CMD_LOAD_STATE(cmdbuf, VIVS_GL_VARYING_TOTAL_COMPONENTS, 0x0);
+ CMD_LOAD_STATE(cmdbuf, VIVS_PS_CONTROL_EXT, 0x0);
+ CMD_LOAD_STATE(cmdbuf, VIVS_VS_OUTPUT_COUNT, 0x1);
+ CMD_LOAD_STATE(cmdbuf, VIVS_GL_HALTI5_SH_SPECIALS, 0x0);
+ CMD_LOAD_STATE(cmdbuf, VIVS_PS_ICACHE_PREFETCH, 0x0);
+ CMD_LOAD_STATE(cmdbuf, VIVS_CL_UNK00924, 0x0);
+ CMD_LOAD_STATE(cmdbuf, VIVS_CL_THREAD_ALLOCATION, 0x1);
+
+ CMD_LOAD_STATE(cmdbuf, VIVS_CL_GLOBAL_WORK_OFFSET_X, 0x0);
+ CMD_LOAD_STATE(cmdbuf, VIVS_CL_GLOBAL_WORK_OFFSET_Y, 0x0);
+ CMD_LOAD_STATE(cmdbuf, VIVS_CL_GLOBAL_WORK_OFFSET_Z, 0x0);
+
+ CMD_LOAD_STATES_START(cmdbuf, VIVS_CL_WORKGROUP_COUNT_X, 9);
+ OUT(cmdbuf, 0xf);
+ OUT(cmdbuf, 0x5);
+ OUT(cmdbuf, 0xffffffff);
+ OUT(cmdbuf, 0x0);
+ OUT(cmdbuf, 0x0);
+ OUT(cmdbuf, 0x3ff);
+ OUT(cmdbuf, 0x0);
+ OUT(cmdbuf, 0x4);
+ OUT(cmdbuf, 0x1);
+ OUT(cmdbuf, 0x0);
+
+ CMD_LOAD_STATE(cmdbuf, VIVS_CL_KICKER, 0xbadabeeb);
+ CMD_LOAD_STATE(cmdbuf, VIVS_GL_FLUSH_CACHE,
+ VIVS_GL_FLUSH_CACHE_SHADER_L1 |
+ VIVS_GL_FLUSH_CACHE_UNK10 |
+ VIVS_GL_FLUSH_CACHE_UNK11);
+}
+
+static void
+etnaviv_flop_reset_ppu_fill_input(u32 *buffer, u32 size)
+{
+ for (int i = 0; i < size/4; ++i, ++buffer)
+ *buffer = 0x01010101;
+}
+
+static void
+etnaviv_flop_reset_ppu_set_shader(u8 *dest)
+{
+ const u32 inst[PPU_FLOP_RESET_INSTR_DWORD_COUNT] = {
+ /* img_load.u8 r1, c0, r0.xy */
+ 0x78011779, 0x39000804, 0x00A90050, 0x00000000,
+ /* img_load.u8 r2, c0, r0.xy */
+ 0x78021779, 0x39000804, 0x00A90050, 0x00000000,
+ /* dp2x8 r1, r1, r2, c3_512 */
+ 0xB8017145, 0x390018FC, 0x01C90140, 0x40390028,
+ /* img_store.u8 r1, c2, r0.xy, r1 */
+ 0x380007BA, 0x39001804, 0x00A90050, 0x00390018,
+ };
+ memcpy(dest, inst, sizeof(inst));
+}
+
+static struct etnaviv_flop_reset_entry {
+ u16 chip_model;
+ u16 revision;
+ u32 flags;
+} etnaviv_flop_reset_db [] = {
+ {
+ .chip_model = 0x8000,
+ .revision = 0x6205,
+ .flags = flop_reset_ppu
+ },
+};
+
+bool
+etnaviv_flop_reset_ppu_require(const struct etnaviv_chip_identity *chip_id)
+{
+ const struct etnaviv_flop_reset_entry *e = etnaviv_flop_reset_db;
+
+ for (int i = 0; i < ARRAY_SIZE(etnaviv_flop_reset_db); ++i, ++e) {
+ if (chip_id->model == e->chip_model &&
+ chip_id->revision == e->revision)
+ return (e->flags & flop_reset_ppu) != 0;
+ }
+
+ return false;
+}
+
+static const u32 image_data_size = PPU_IMAGE_STRIDE * PPU_IMAGE_YSIZE;
+static const u32 output_offset = ALIGN(image_data_size, 64);
+static const u32 shader_offset = ALIGN(output_offset + image_data_size, 64);
+static const u32 shader_size = PPU_FLOP_RESET_INSTR_DWORD_COUNT * sizeof(u32);
+static const u32 shader_register_count = 3;
+static const u32 buffer_size = shader_offset + shader_size;
+
+void
+etnaviv_flop_reset_ppu_init(struct etnaviv_drm_private *priv)
+{
+ /* Get some space from the rung buffer to put the payload
+ * (input and output image, and shader), we keep this buffer
+ * for the whole life time the driver is bound
+ */
+ priv->flop_reset_data_ppu =
+ kzalloc(sizeof(*priv->flop_reset_data_ppu), GFP_KERNEL);
+
+ etnaviv_cmdbuf_init(priv->cmdbuf_suballoc,
+ priv->flop_reset_data_ppu, buffer_size);
+
+ void *buffer_base = priv->flop_reset_data_ppu->vaddr;
+
+ u32 *input_data = (u32 *)buffer_base;
+ etnaviv_flop_reset_ppu_fill_input(input_data, image_data_size);
+
+ u8 *shader_data = (u8 *)buffer_base + shader_offset;
+ etnaviv_flop_reset_ppu_set_shader(shader_data);
+}
+
+void
+etnaviv_flop_reset_ppu_run(struct etnaviv_gpu *gpu)
+{
+ struct etnaviv_drm_private *priv = gpu->drm->dev_private;
+
+ if (!priv->flop_reset_data_ppu) {
+ pr_err("Flop reset data was not initialized, skipping\n");
+ return;
+ }
+
+ u32 buffer_base = etnaviv_cmdbuf_get_va(priv->flop_reset_data_ppu,
+ &gpu->mmu_context->cmdbuf_mapping);
+
+ etnaviv_emit_flop_reset_state_ppu(&gpu->buffer,
+ buffer_base,
+ 0,
+ output_offset,
+ shader_offset,
+ shader_size,
+ shader_register_count);
+}
diff --git a/drivers/gpu/drm/etnaviv/etnaviv_flop_reset.h b/drivers/gpu/drm/etnaviv/etnaviv_flop_reset.h
new file mode 100644
index 000000000000..f51cece75507
--- /dev/null
+++ b/drivers/gpu/drm/etnaviv/etnaviv_flop_reset.h
@@ -0,0 +1,25 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2025 Etnaviv Project
+ */
+
+
+#ifndef etnaviv_flop_reset_h
+#define etnaviv_flop_reset_h
+
+#include <linux/types.h>
+
+struct etnaviv_chip_identity;
+struct etnaviv_drm_private;
+struct etnaviv_gpu;
+
+bool
+etnaviv_flop_reset_ppu_require(const struct etnaviv_chip_identity *chip_id);
+
+void
+etnaviv_flop_reset_ppu_init(struct etnaviv_drm_private *priv);
+
+void
+etnaviv_flop_reset_ppu_run(struct etnaviv_gpu *gpu);
+
+#endif
diff --git a/drivers/gpu/drm/etnaviv/etnaviv_gpu.c b/drivers/gpu/drm/etnaviv/etnaviv_gpu.c
index cf0d9049bcf1..0aac01c1021c 100644
--- a/drivers/gpu/drm/etnaviv/etnaviv_gpu.c
+++ b/drivers/gpu/drm/etnaviv/etnaviv_gpu.c
@@ -18,6 +18,7 @@
#include "etnaviv_cmdbuf.h"
#include "etnaviv_dump.h"
+#include "etnaviv_flop_reset.h"
#include "etnaviv_gpu.h"
#include "etnaviv_gem.h"
#include "etnaviv_mmu.h"
@@ -837,6 +838,10 @@ int etnaviv_gpu_init(struct etnaviv_gpu *gpu)
goto fail;
}
+ if (etnaviv_flop_reset_ppu_require(&gpu->identity) &&
+ !priv->flop_reset_data_ppu)
+ etnaviv_flop_reset_ppu_init(priv);
+
if (gpu->identity.nn_core_count > 0)
dev_warn(gpu->dev, "etnaviv has been instantiated on a NPU, "
"for which the UAPI is still experimental\n");
--
2.49.0
^ permalink raw reply related [flat|nested] 18+ messages in thread
* [PATCH v3 5/5] drm/etnaviv: Add module parameter to force PPU flop reset
2025-06-30 20:26 ` [PATCH v3 0/5] drm/etnaviv: Add support for running a " Gert Wollny
` (3 preceding siblings ...)
2025-06-30 20:26 ` [PATCH v3 4/5] drm/etnaviv: Add PPU flop reset Gert Wollny
@ 2025-06-30 20:26 ` Gert Wollny
4 siblings, 0 replies; 18+ messages in thread
From: Gert Wollny @ 2025-06-30 20:26 UTC (permalink / raw)
To: Lucas Stach, Russell King, Christian Gmeiner, David Airlie,
Daniel Vetter
Cc: etnaviv, dri-devel, linux-kernel, Gert Wollny
v2: Check for feature PIPE_3D when forcing PPU flop reset (Lucas)
Signed-off-by: Gert Wollny <gert.wollny@collabora.com>
---
drivers/gpu/drm/etnaviv/etnaviv_flop_reset.c | 17 +++++++++++++++++
1 file changed, 17 insertions(+)
diff --git a/drivers/gpu/drm/etnaviv/etnaviv_flop_reset.c b/drivers/gpu/drm/etnaviv/etnaviv_flop_reset.c
index 138af3c33b5d..ec32128ebac5 100644
--- a/drivers/gpu/drm/etnaviv/etnaviv_flop_reset.c
+++ b/drivers/gpu/drm/etnaviv/etnaviv_flop_reset.c
@@ -16,6 +16,9 @@ enum etnaviv_flop_reset_type {
flop_reset_tp = 1 << 2
};
+static int etnaviv_force_flop_reset = 0;
+module_param_named(force_flop_reset, etnaviv_force_flop_reset, int , 0);
+
#define PPU_IMAGE_STRIDE 64
#define PPU_IMAGE_XSIZE 64
#define PPU_IMAGE_YSIZE 6
@@ -151,6 +154,20 @@ etnaviv_flop_reset_ppu_require(const struct etnaviv_chip_identity *chip_id)
return (e->flags & flop_reset_ppu) != 0;
}
+ if (etnaviv_force_flop_reset & flop_reset_ppu) {
+
+ if (!(chip_id->features & chipFeatures_PIPE_3D)) {
+ pr_warn("Feature PIPE_3D not supported, ignore request to force "
+ "PPU flop reset for model: 0x%04x, revision: 0x%04x\n",
+ chip_id->model, chip_id->revision);
+ return false;
+ }
+
+ pr_info("Force PPU flop reset for model: 0x%04x, revision: 0x%04x\n",
+ chip_id->model, chip_id->revision);
+ return true;
+ }
+
return false;
}
--
2.49.0
^ permalink raw reply related [flat|nested] 18+ messages in thread
end of thread, other threads:[~2025-06-30 20:25 UTC | newest]
Thread overview: 18+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-06-18 20:43 drm/etnaviv: Add support for running a PPU flop reset Gert Wollny
2025-06-18 20:43 ` [PATCH v2 1/6] drm/etnaviv: Add command stream definitions required for " Gert Wollny
2025-06-18 20:43 ` [PATCH v2 2/6] drm/etnaviv: move some functions to a header to be able to use them externally Gert Wollny
2025-06-18 20:43 ` [PATCH v2 3/6] drm/etnaviv: Add a new function to emit a series of states to cmd stream Gert Wollny
2025-06-18 20:43 ` [PATCH v2 4/6] drm/etnaviv: Identify GPU already when binding Gert Wollny
2025-06-20 20:11 ` Lucas Stach
2025-06-18 20:43 ` [PATCH v2 5/6] drm/etnaviv: Add PPU flop reset Gert Wollny
2025-06-20 20:22 ` Lucas Stach
2025-06-23 12:05 ` Gert Wollny
2025-06-23 12:25 ` Lucas Stach
2025-06-18 20:43 ` [PATCH v2 6/6] drm/etnaviv: Add module parameter to force " Gert Wollny
2025-06-20 20:24 ` Lucas Stach
2025-06-30 20:26 ` [PATCH v3 0/5] drm/etnaviv: Add support for running a " Gert Wollny
2025-06-30 20:26 ` [PATCH v3 1/5] drm/etnaviv: Add command stream definitions required for " Gert Wollny
2025-06-30 20:26 ` [PATCH v3 2/5] drm/etnaviv: move some functions to a header to be able to use them externally Gert Wollny
2025-06-30 20:26 ` [PATCH v3 3/5] drm/etnaviv: Add a new function to emit a series of states to cmd stream Gert Wollny
2025-06-30 20:26 ` [PATCH v3 4/5] drm/etnaviv: Add PPU flop reset Gert Wollny
2025-06-30 20:26 ` [PATCH v3 5/5] drm/etnaviv: Add module parameter to force " Gert Wollny
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).