mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
* 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; 41+ 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] 41+ 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; 41+ 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	[flat|nested] 41+ 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; 41+ 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	[flat|nested] 41+ 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; 41+ 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	[flat|nested] 41+ 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; 41+ 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	[flat|nested] 41+ 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; 41+ 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	[flat|nested] 41+ 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; 41+ 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	[flat|nested] 41+ 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; 41+ 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] 41+ 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; 41+ 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] 41+ 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; 41+ 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] 41+ 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; 41+ 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] 41+ 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; 41+ 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] 41+ 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
                     ` (5 more replies)
  6 siblings, 6 replies; 41+ 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] 41+ 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
                     ` (4 subsequent siblings)
  5 siblings, 0 replies; 41+ 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	[flat|nested] 41+ 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
                     ` (3 subsequent siblings)
  5 siblings, 0 replies; 41+ 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	[flat|nested] 41+ 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
                     ` (2 subsequent siblings)
  5 siblings, 0 replies; 41+ 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	[flat|nested] 41+ 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-10-09 21:40     ` Christian Gmeiner
  2025-06-30 20:26   ` [PATCH v3 5/5] drm/etnaviv: Add module parameter to force " Gert Wollny
  2025-11-10 14:37   ` [PATCH v4 0/5] drm/etnaviv: Add support for running a " gert.wollny
  5 siblings, 1 reply; 41+ 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	[flat|nested] 41+ 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
  2025-11-10 14:37   ` [PATCH v4 0/5] drm/etnaviv: Add support for running a " gert.wollny
  5 siblings, 0 replies; 41+ 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	[flat|nested] 41+ messages in thread

* Re: [PATCH v3 4/5] drm/etnaviv: Add PPU flop reset
  2025-06-30 20:26   ` [PATCH v3 4/5] drm/etnaviv: Add PPU flop reset Gert Wollny
@ 2025-10-09 21:40     ` Christian Gmeiner
  0 siblings, 0 replies; 41+ messages in thread
From: Christian Gmeiner @ 2025-10-09 21:40 UTC (permalink / raw)
  To: Gert Wollny
  Cc: Lucas Stach, Russell King, David Airlie, Daniel Vetter, etnaviv,
	dri-devel, linux-kernel

Hi Gert,

>
> 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"

I think you want to use #include <linux/types.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
> +};

As this patch series only adds support for flop_reset_ppu I think we should
drop this enum for now.

> +
> +#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,

Return type on separate line is unusual in kernel code - found in
multiple places.


> +                                 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;

Maybe just use memset32(..)?

> +}
> +
> +static void
> +etnaviv_flop_reset_ppu_set_shader(u8 *dest)
> +{
> +       const u32 inst[PPU_FLOP_RESET_INSTR_DWORD_COUNT] = {

static const

> +               /* 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 {

static const

> +       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
I think we need to return an error here - so let's go with an int.

> +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);
> +

Missing NULL check for priv->flop_reset_data_ppu.

> +       etnaviv_cmdbuf_init(priv->cmdbuf_suballoc,
> +                           priv->flop_reset_data_ppu, buffer_size);
> +

etnaviv_cmdbuf_init can fail too.


> +       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");

dev_err(gpu->dev, "Flop reset data was not initialized, skipping\n");


> +               return;
> +       }

How can this happen?

> +
> +       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

To keep the style consistent: __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
>

I am not sure about the overall code style - you did run checkpatch.pl ?

-- 
greets
--
Christian Gmeiner, MSc

https://christian-gmeiner.info/privacypolicy

^ permalink raw reply	[flat|nested] 41+ messages in thread

* [PATCH v4 0/5] drm/etnaviv: Add support for running a PPU flop reset
  2025-06-30 20:26 ` [PATCH v3 0/5] drm/etnaviv: Add support for running a " Gert Wollny
                     ` (4 preceding siblings ...)
  2025-06-30 20:26   ` [PATCH v3 5/5] drm/etnaviv: Add module parameter to force " Gert Wollny
@ 2025-11-10 14:37   ` gert.wollny
  2025-11-10 14:37     ` [PATCH v4 1/5] drm/etnaviv: Add command stream definitions required for " gert.wollny
                       ` (5 more replies)
  5 siblings, 6 replies; 41+ messages in thread
From: gert.wollny @ 2025-11-10 14:37 UTC (permalink / raw)
  To: Christian Gmeiner
  Cc: Lucas Stach, Russell King, David Airlie, Daniel Vetter, etnaviv,
	dri-devel, linux-kernel

Dear all, 

this is the fourth version of the series to add PPU flop reset. 

Changes w.r.t. the previous version are: 

  * Apply all changes suggested by Christian Gmeiner: 
   - replace "asm-generic/int-ll64.h" with "linux/types.h"
   - drop flop reset type enum since we only support one type here
   - move function return parameters on same line with function name
   - replace open coded for loop with memset32
   - add cnost to local static values
   - add a return value to etnaviv_flop_reset_ppu_init; handle and
     pass errors on to the caller
   - handle etnaviv_flop_reset_ppu_init return value
   - use dev_err for flop reset error message
   - fix include guard to be consistent with the other driver code
   - fix license header and formatting

  * run "checkpatch" and fix issues reported by it: 
   - don't initialize module parameter to zero
   - avoid multi-line string in warning message

Many thanks for any comments,
Gert

[PATCH v4 1/5] drm/etnaviv: Add command stream definitions required
[PATCH v4 2/5] drm/etnaviv: move some functions to a header to be
[PATCH v4 3/5] drm/etnaviv: Add a new function to emit a series of
[PATCH v4 4/5] drm/etnaviv: Add PPU flop reset
[PATCH v4 5/5] drm/etnaviv: Add module parameter to force PPU flop

^ permalink raw reply	[flat|nested] 41+ messages in thread

* [PATCH v4 1/5] drm/etnaviv: Add command stream definitions required for a PPU flop reset
  2025-11-10 14:37   ` [PATCH v4 0/5] drm/etnaviv: Add support for running a " gert.wollny
@ 2025-11-10 14:37     ` gert.wollny
  2025-11-10 15:54       ` Christian Gmeiner
  2025-11-10 14:37     ` [PATCH v4 2/5] drm/etnaviv: move some functions to a header to be able to use them externally gert.wollny
                       ` (4 subsequent siblings)
  5 siblings, 1 reply; 41+ messages in thread
From: gert.wollny @ 2025-11-10 14:37 UTC (permalink / raw)
  To: Christian Gmeiner
  Cc: Lucas Stach, Russell King, David Airlie, Daniel Vetter, etnaviv,
	dri-devel, linux-kernel, Gert Wollny

From: Gert Wollny <gert.wollny@collabora.com>

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.51.0


^ permalink raw reply	[flat|nested] 41+ messages in thread

* [PATCH v4 2/5] drm/etnaviv: move some functions to a header to be able to use them externally
  2025-11-10 14:37   ` [PATCH v4 0/5] drm/etnaviv: Add support for running a " gert.wollny
  2025-11-10 14:37     ` [PATCH v4 1/5] drm/etnaviv: Add command stream definitions required for " gert.wollny
@ 2025-11-10 14:37     ` gert.wollny
  2025-11-10 15:53       ` Christian Gmeiner
  2025-11-10 14:37     ` [PATCH v4 3/5] drm/etnaviv: Add a new function to emit a series of states to cmd stream gert.wollny
                       ` (3 subsequent siblings)
  5 siblings, 1 reply; 41+ messages in thread
From: gert.wollny @ 2025-11-10 14:37 UTC (permalink / raw)
  To: Christian Gmeiner
  Cc: Lucas Stach, Russell King, David Airlie, Daniel Vetter, etnaviv,
	dri-devel, linux-kernel, Gert Wollny

From: Gert Wollny <gert.wollny@collabora.com>

v2: Add license info to header

Signed-off-by: Gert Wollny <gert.wollny@collabora.com>
---
 drivers/gpu/drm/etnaviv/etnaviv_buffer.c | 71 +------------------
 drivers/gpu/drm/etnaviv/etnaviv_buffer.h | 86 ++++++++++++++++++++++++
 2 files changed, 87 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 d4f1307d574f..5be9978e34d9 100644
--- a/drivers/gpu/drm/etnaviv/etnaviv_buffer.c
+++ b/drivers/gpu/drm/etnaviv/etnaviv_buffer.c
@@ -10,6 +10,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"
@@ -18,76 +19,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..ae1ba1db6c8a
--- /dev/null
+++ b/drivers/gpu/drm/etnaviv/etnaviv_buffer.h
@@ -0,0 +1,86 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2014-2025 Etnaviv Project
+ */
+
+#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.51.0


^ permalink raw reply	[flat|nested] 41+ messages in thread

* [PATCH v4 3/5] drm/etnaviv: Add a new function to emit a series of states to cmd stream
  2025-11-10 14:37   ` [PATCH v4 0/5] drm/etnaviv: Add support for running a " gert.wollny
  2025-11-10 14:37     ` [PATCH v4 1/5] drm/etnaviv: Add command stream definitions required for " gert.wollny
  2025-11-10 14:37     ` [PATCH v4 2/5] drm/etnaviv: move some functions to a header to be able to use them externally gert.wollny
@ 2025-11-10 14:37     ` gert.wollny
  2025-11-17  8:27       ` Christian Gmeiner
  2025-11-10 14:37     ` [PATCH v4 4/5] drm/etnaviv: Add PPU flop reset gert.wollny
                       ` (2 subsequent siblings)
  5 siblings, 1 reply; 41+ messages in thread
From: gert.wollny @ 2025-11-10 14:37 UTC (permalink / raw)
  To: Christian Gmeiner
  Cc: Lucas Stach, Russell King, David Airlie, Daniel Vetter, etnaviv,
	dri-devel, linux-kernel, Gert Wollny

From: Gert Wollny <gert.wollny@collabora.com>

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 ae1ba1db6c8a..9388a686edcf 100644
--- a/drivers/gpu/drm/etnaviv/etnaviv_buffer.h
+++ b/drivers/gpu/drm/etnaviv/etnaviv_buffer.h
@@ -43,6 +43,19 @@ static inline void CMD_LOAD_STATE(struct etnaviv_cmdbuf *buffer, u32 reg,
 	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.51.0


^ permalink raw reply	[flat|nested] 41+ messages in thread

* [PATCH v4 4/5] drm/etnaviv: Add PPU flop reset
  2025-11-10 14:37   ` [PATCH v4 0/5] drm/etnaviv: Add support for running a " gert.wollny
                       ` (2 preceding siblings ...)
  2025-11-10 14:37     ` [PATCH v4 3/5] drm/etnaviv: Add a new function to emit a series of states to cmd stream gert.wollny
@ 2025-11-10 14:37     ` gert.wollny
  2025-11-17  8:57       ` Christian Gmeiner
  2025-11-10 14:37     ` [PATCH v4 5/5] drm/etnaviv: Add module parameter to force " gert.wollny
  2025-11-19 16:45     ` [PATCH v5 0/5] drm/etnaviv: Add support for running a " gert.wollny
  5 siblings, 1 reply; 41+ messages in thread
From: gert.wollny @ 2025-11-10 14:37 UTC (permalink / raw)
  To: Christian Gmeiner
  Cc: Lucas Stach, Russell King, David Airlie, Daniel Vetter, etnaviv,
	dri-devel, linux-kernel, Gert Wollny

From: Gert Wollny <gert.wollny@collabora.com>

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)

v4: As suggested by Christian Gmeiner:
    - replace "asm-generic/int-ll64.h" with "linux/types.h"
    - drop flop reset type enum since we only support one type here
    - move function return parameters on same line with function name
    - replace open coded for loop with memset32
    - add cnost to local static values
    - add a return value to etnaviv_flop_reset_ppu_init; handle and
      pass errors on to the caller
    - handle etnaviv_flop_reset_ppu_init return value
    - use dev_err for flop reset error message
    - fix include guard to be consistent with the other driver code
    - fix license header and formatting

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 | 204 +++++++++++++++++++
 drivers/gpu/drm/etnaviv/etnaviv_flop_reset.h |  21 ++
 drivers/gpu/drm/etnaviv/etnaviv_gpu.c        |  11 +
 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 5be9978e34d9..7b5f4da85a1f 100644
--- a/drivers/gpu/drm/etnaviv/etnaviv_buffer.c
+++ b/drivers/gpu/drm/etnaviv/etnaviv_buffer.c
@@ -19,6 +19,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)
 {
@@ -101,6 +103,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 54ceae87b401..bb1b84eecec8 100644
--- a/drivers/gpu/drm/etnaviv/etnaviv_drv.c
+++ b/drivers/gpu/drm/etnaviv/etnaviv_drv.c
@@ -601,6 +601,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..7c0112b3b3ad
--- /dev/null
+++ b/drivers/gpu/drm/etnaviv/etnaviv_flop_reset.c
@@ -0,0 +1,204 @@
+/* SPDX-License-Identifier: GPL-2.0
+ *
+ * Copyright (C) 2025 Etnaviv Project
+ */
+
+#include "asm-generic/errno-base.h"
+#include "linux/dev_printk.h"
+#include "linux/string.h"
+#include "linux/types.h"
+#include "etnaviv_buffer.h"
+#include "etnaviv_cmdbuf.h"
+#include "state_3d.xml.h"
+
+#include "etnaviv_flop_reset.h"
+
+#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)
+{
+	memset32(buffer, 0x01010101, size / 4);
+}
+
+static void etnaviv_flop_reset_ppu_set_shader(u8 *dest)
+{
+	static 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 const struct etnaviv_flop_reset_entry {
+	u16 chip_model;
+	u16 revision;
+	u32 flags;
+} etnaviv_flop_reset_db[] = {
+	{
+		.chip_model = 0x8000,
+		.revision = 0x6205,
+	},
+};
+
+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 true;
+	}
+
+	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;
+
+int 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);
+
+	if (!priv->flop_reset_data_ppu)
+		return -ENOMEM;
+
+	int ret = etnaviv_cmdbuf_init(priv->cmdbuf_suballoc,
+				      priv->flop_reset_data_ppu, buffer_size);
+	if (ret)
+		return ret;
+
+	void *buffer_base = priv->flop_reset_data_ppu->vaddr;
+	u32 *input_data = (u32 *)buffer_base;
+	u8 *shader_data = (u8 *)buffer_base + shader_offset;
+
+	etnaviv_flop_reset_ppu_fill_input(input_data, image_data_size);
+	etnaviv_flop_reset_ppu_set_shader(shader_data);
+
+	return 0;
+}
+
+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) {
+		dev_err(gpu->dev,
+			"Oops: 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..e6dee1db788f
--- /dev/null
+++ b/drivers/gpu/drm/etnaviv/etnaviv_flop_reset.h
@@ -0,0 +1,21 @@
+/* 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);
+
+int 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 ca0be293f5fe..839ffa445ce2 100644
--- a/drivers/gpu/drm/etnaviv/etnaviv_gpu.c
+++ b/drivers/gpu/drm/etnaviv/etnaviv_gpu.c
@@ -20,6 +20,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"
@@ -839,6 +840,16 @@ int etnaviv_gpu_init(struct etnaviv_gpu *gpu)
 		goto fail;
 	}
 
+	if (etnaviv_flop_reset_ppu_require(&gpu->identity) &&
+	    !priv->flop_reset_data_ppu) {
+		ret = etnaviv_flop_reset_ppu_init(priv);
+		if (ret) {
+			dev_err(gpu->dev,
+				"Unable to initialize PPU flop reset date\n");
+			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");
-- 
2.51.0


^ permalink raw reply	[flat|nested] 41+ messages in thread

* [PATCH v4 5/5] drm/etnaviv: Add module parameter to force PPU flop reset
  2025-11-10 14:37   ` [PATCH v4 0/5] drm/etnaviv: Add support for running a " gert.wollny
                       ` (3 preceding siblings ...)
  2025-11-10 14:37     ` [PATCH v4 4/5] drm/etnaviv: Add PPU flop reset gert.wollny
@ 2025-11-10 14:37     ` gert.wollny
  2025-11-19 15:30       ` Christian Gmeiner
  2025-11-19 16:45     ` [PATCH v5 0/5] drm/etnaviv: Add support for running a " gert.wollny
  5 siblings, 1 reply; 41+ messages in thread
From: gert.wollny @ 2025-11-10 14:37 UTC (permalink / raw)
  To: Christian Gmeiner
  Cc: Lucas Stach, Russell King, David Airlie, Daniel Vetter, etnaviv,
	dri-devel, linux-kernel, Gert Wollny

From: Gert Wollny <gert.wollny@collabora.com>

v2: Check for feature PIPE_3D when forcing PPU flop reset (Lucas)

v3: - drop use of ppu_flop_reset enum (Christian Gmeiner)
    - don't initialize module parameter to zero (checkpatch)
    - avoid multi-line string in warning message (checkpatch)

Signed-off-by: Gert Wollny <gert.wollny@collabora.com>
---
 drivers/gpu/drm/etnaviv/etnaviv_flop_reset.c | 16 ++++++++++++++++
 1 file changed, 16 insertions(+)

diff --git a/drivers/gpu/drm/etnaviv/etnaviv_flop_reset.c b/drivers/gpu/drm/etnaviv/etnaviv_flop_reset.c
index 7c0112b3b3ad..75fe8cce1177 100644
--- a/drivers/gpu/drm/etnaviv/etnaviv_flop_reset.c
+++ b/drivers/gpu/drm/etnaviv/etnaviv_flop_reset.c
@@ -13,6 +13,9 @@
 
 #include "etnaviv_flop_reset.h"
 
+static int etnaviv_force_flop_reset;
+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
@@ -148,6 +151,19 @@ bool etnaviv_flop_reset_ppu_require(const struct etnaviv_chip_identity *chip_id)
 			return true;
 	}
 
+	if (etnaviv_force_flop_reset) {
+		if (!(chip_id->features & chipFeatures_PIPE_3D)) {
+			pr_warn("Etnaviv: model: 0x%04x, revision: 0x%04x does not support PIPE_3D\n",
+				chip_id->model, chip_id->revision);
+			pr_warn("Request to force PPU flop reset ignored.\n");
+			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.51.0


^ permalink raw reply	[flat|nested] 41+ messages in thread

* Re: [PATCH v4 2/5] drm/etnaviv: move some functions to a header to be able to use them externally
  2025-11-10 14:37     ` [PATCH v4 2/5] drm/etnaviv: move some functions to a header to be able to use them externally gert.wollny
@ 2025-11-10 15:53       ` Christian Gmeiner
  0 siblings, 0 replies; 41+ messages in thread
From: Christian Gmeiner @ 2025-11-10 15:53 UTC (permalink / raw)
  To: gert.wollny
  Cc: Lucas Stach, Russell King, David Airlie, Daniel Vetter, etnaviv,
	dri-devel, linux-kernel

Hi, thanks for the patch.

>
> From: Gert Wollny <gert.wollny@collabora.com>
>
> v2: Add license info to header
>
> Signed-off-by: Gert Wollny <gert.wollny@collabora.com>
> ---
>  drivers/gpu/drm/etnaviv/etnaviv_buffer.c | 71 +------------------
>  drivers/gpu/drm/etnaviv/etnaviv_buffer.h | 86 ++++++++++++++++++++++++
>  2 files changed, 87 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 d4f1307d574f..5be9978e34d9 100644
> --- a/drivers/gpu/drm/etnaviv/etnaviv_buffer.c
> +++ b/drivers/gpu/drm/etnaviv/etnaviv_buffer.c
> @@ -10,6 +10,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"
> @@ -18,76 +19,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..ae1ba1db6c8a
> --- /dev/null
> +++ b/drivers/gpu/drm/etnaviv/etnaviv_buffer.h
> @@ -0,0 +1,86 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * Copyright (C) 2014-2025 Etnaviv Project
> + */
> +
> +#ifndef etnaviv_buffer_h
> +#define etnaviv_buffer_h

#ifndef __ETNAVIV_BUFFER_H__
#define __ETNAVIV_BUFFER_H__

> +
> +#include "etnaviv_cmdbuf.h"
> +#include "etnaviv_gpu.h"
I don't think we need this include."

> +#include "etnaviv_gem.h"
I don't think we need this include."

> +#include "etnaviv_mmu.h"
I don't think we need this include."

> +
> +#include "common.xml.h"
> +#include "linux/printk.h"
I don't think we need this include."

> +#include "state.xml.h"
> +#include "state_blt.xml.h"
I don't think we need this include."

> +#include "state_hi.xml.h"
I don't think we need this include."

> +#include "state_3d.xml.h"
I don't think we need this include."

> +#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.51.0
>

-- 
greets
--
Christian Gmeiner, MSc

https://christian-gmeiner.info/privacypolicy

^ permalink raw reply	[flat|nested] 41+ messages in thread

* Re: [PATCH v4 1/5] drm/etnaviv: Add command stream definitions required for a PPU flop reset
  2025-11-10 14:37     ` [PATCH v4 1/5] drm/etnaviv: Add command stream definitions required for " gert.wollny
@ 2025-11-10 15:54       ` Christian Gmeiner
  0 siblings, 0 replies; 41+ messages in thread
From: Christian Gmeiner @ 2025-11-10 15:54 UTC (permalink / raw)
  To: gert.wollny
  Cc: Lucas Stach, Russell King, David Airlie, Daniel Vetter, etnaviv,
	dri-devel, linux-kernel

>
> From: Gert Wollny <gert.wollny@collabora.com>
>
> 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>

Reviewed-by: Christian Gmeiner <cgmeiner@igalia.com>

-- 
greets
--
Christian Gmeiner, MSc

https://christian-gmeiner.info/privacypolicy

^ permalink raw reply	[flat|nested] 41+ messages in thread

* Re: [PATCH v4 3/5] drm/etnaviv: Add a new function to emit a series of states to cmd stream
  2025-11-10 14:37     ` [PATCH v4 3/5] drm/etnaviv: Add a new function to emit a series of states to cmd stream gert.wollny
@ 2025-11-17  8:27       ` Christian Gmeiner
  0 siblings, 0 replies; 41+ messages in thread
From: Christian Gmeiner @ 2025-11-17  8:27 UTC (permalink / raw)
  To: gert.wollny
  Cc: Lucas Stach, Russell King, David Airlie, Daniel Vetter, etnaviv,
	dri-devel, linux-kernel

> From: Gert Wollny <gert.wollny@collabora.com>
>
> v2: fix formatting and remove superfluous masking (Lucas)
>
> Signed-off-by: Gert Wollny <gert.wollny@collabora.com>

Reviewed-by: Christian Gmeiner <cgmeiner@igalia.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 ae1ba1db6c8a..9388a686edcf 100644
> --- a/drivers/gpu/drm/etnaviv/etnaviv_buffer.h
> +++ b/drivers/gpu/drm/etnaviv/etnaviv_buffer.h
> @@ -43,6 +43,19 @@ static inline void CMD_LOAD_STATE(struct etnaviv_cmdbuf *buffer, u32 reg,
>         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.51.0
>


-- 
greets
--
Christian Gmeiner, MSc

https://christian-gmeiner.info/privacypolicy

^ permalink raw reply	[flat|nested] 41+ messages in thread

* Re: [PATCH v4 4/5] drm/etnaviv: Add PPU flop reset
  2025-11-10 14:37     ` [PATCH v4 4/5] drm/etnaviv: Add PPU flop reset gert.wollny
@ 2025-11-17  8:57       ` Christian Gmeiner
  0 siblings, 0 replies; 41+ messages in thread
From: Christian Gmeiner @ 2025-11-17  8:57 UTC (permalink / raw)
  To: gert.wollny
  Cc: Lucas Stach, Russell King, David Airlie, Daniel Vetter, etnaviv,
	dri-devel, linux-kernel

> From: Gert Wollny <gert.wollny@collabora.com>
>
> 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)
>
> v4: As suggested by Christian Gmeiner:
>     - replace "asm-generic/int-ll64.h" with "linux/types.h"
>     - drop flop reset type enum since we only support one type here
>     - move function return parameters on same line with function name
>     - replace open coded for loop with memset32
>     - add cnost to local static values
>     - add a return value to etnaviv_flop_reset_ppu_init; handle and
>       pass errors on to the caller
>     - handle etnaviv_flop_reset_ppu_init return value
>     - use dev_err for flop reset error message
>     - fix include guard to be consistent with the other driver code
>     - fix license header and formatting
>
> 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 | 204 +++++++++++++++++++
>  drivers/gpu/drm/etnaviv/etnaviv_flop_reset.h |  21 ++
>  drivers/gpu/drm/etnaviv/etnaviv_gpu.c        |  11 +
>  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 5be9978e34d9..7b5f4da85a1f 100644
> --- a/drivers/gpu/drm/etnaviv/etnaviv_buffer.c
> +++ b/drivers/gpu/drm/etnaviv/etnaviv_buffer.c
> @@ -19,6 +19,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)
>  {
> @@ -101,6 +103,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 54ceae87b401..bb1b84eecec8 100644
> --- a/drivers/gpu/drm/etnaviv/etnaviv_drv.c
> +++ b/drivers/gpu/drm/etnaviv/etnaviv_drv.c
> @@ -601,6 +601,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..7c0112b3b3ad
> --- /dev/null
> +++ b/drivers/gpu/drm/etnaviv/etnaviv_flop_reset.c
> @@ -0,0 +1,204 @@
> +/* SPDX-License-Identifier: GPL-2.0
> + *
> + * Copyright (C) 2025 Etnaviv Project
> + */
> +
> +#include "asm-generic/errno-base.h"

#include <linux/errno.h>


> +#include "linux/dev_printk.h"
> +#include "linux/string.h"
> +#include "linux/types.h"

#include <linux/dev_printk.h>
#include <linux/string.h>
#include <linux/types.h>


> +#include "etnaviv_buffer.h"
> +#include "etnaviv_cmdbuf.h"
> +#include "state_3d.xml.h"
> +
> +#include "etnaviv_flop_reset.h"
> +
> +#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)
> +{
> +       memset32(buffer, 0x01010101, size / 4);
> +}
> +
> +static void etnaviv_flop_reset_ppu_set_shader(u8 *dest)
> +{
> +       static 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 const struct etnaviv_flop_reset_entry {
> +       u16 chip_model;
> +       u16 revision;
> +       u32 flags;
> +} etnaviv_flop_reset_db[] = {
> +       {
> +               .chip_model = 0x8000,
> +               .revision = 0x6205,
> +       },
> +};
> +
> +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 true;
> +       }
> +
> +       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;
> +
> +int 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);
> +
> +       if (!priv->flop_reset_data_ppu)
> +               return -ENOMEM;
> +
> +       int ret = etnaviv_cmdbuf_init(priv->cmdbuf_suballoc,
> +                                     priv->flop_reset_data_ppu, buffer_size);
> +       if (ret)

We are leaking priv->flop_reset_data_ppu here.

> +               return ret;
> +
> +       void *buffer_base = priv->flop_reset_data_ppu->vaddr;
> +       u32 *input_data = (u32 *)buffer_base;
> +       u8 *shader_data = (u8 *)buffer_base + shader_offset;
> +
> +       etnaviv_flop_reset_ppu_fill_input(input_data, image_data_size);
> +       etnaviv_flop_reset_ppu_set_shader(shader_data);
> +
> +       return 0;
> +}
> +
> +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) {
> +               dev_err(gpu->dev,
> +                       "Oops: 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..e6dee1db788f
> --- /dev/null
> +++ b/drivers/gpu/drm/etnaviv/etnaviv_flop_reset.h
> @@ -0,0 +1,21 @@
> +/* 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);
> +
> +int 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 ca0be293f5fe..839ffa445ce2 100644
> --- a/drivers/gpu/drm/etnaviv/etnaviv_gpu.c
> +++ b/drivers/gpu/drm/etnaviv/etnaviv_gpu.c
> @@ -20,6 +20,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"
> @@ -839,6 +840,16 @@ int etnaviv_gpu_init(struct etnaviv_gpu *gpu)
>                 goto fail;
>         }
>
> +       if (etnaviv_flop_reset_ppu_require(&gpu->identity) &&
> +           !priv->flop_reset_data_ppu) {
> +               ret = etnaviv_flop_reset_ppu_init(priv);
> +               if (ret) {
> +                       dev_err(gpu->dev,
> +                               "Unable to initialize PPU flop reset date\n");

typo: should be data and not date

> +                       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");
> --
> 2.51.0
>


-- 
greets
--
Christian Gmeiner, MSc

https://christian-gmeiner.info/privacypolicy

^ permalink raw reply	[flat|nested] 41+ messages in thread

* Re: [PATCH v4 5/5] drm/etnaviv: Add module parameter to force PPU flop reset
  2025-11-10 14:37     ` [PATCH v4 5/5] drm/etnaviv: Add module parameter to force " gert.wollny
@ 2025-11-19 15:30       ` Christian Gmeiner
  0 siblings, 0 replies; 41+ messages in thread
From: Christian Gmeiner @ 2025-11-19 15:30 UTC (permalink / raw)
  To: gert.wollny
  Cc: Lucas Stach, Russell King, David Airlie, Daniel Vetter, etnaviv,
	dri-devel, linux-kernel

> From: Gert Wollny <gert.wollny@collabora.com>
>
> v2: Check for feature PIPE_3D when forcing PPU flop reset (Lucas)
>
> v3: - drop use of ppu_flop_reset enum (Christian Gmeiner)
>     - don't initialize module parameter to zero (checkpatch)
>     - avoid multi-line string in warning message (checkpatch)
>
> Signed-off-by: Gert Wollny <gert.wollny@collabora.com>

Reviewed-by: Christian Gmeiner <cgmeiner@igalia.com>

-- 
greets
--
Christian Gmeiner, MSc

https://christian-gmeiner.info/privacypolicy

^ permalink raw reply	[flat|nested] 41+ messages in thread

* [PATCH v5 0/5] drm/etnaviv: Add support for running a PPU flop reset
  2025-11-10 14:37   ` [PATCH v4 0/5] drm/etnaviv: Add support for running a " gert.wollny
                       ` (4 preceding siblings ...)
  2025-11-10 14:37     ` [PATCH v4 5/5] drm/etnaviv: Add module parameter to force " gert.wollny
@ 2025-11-19 16:45     ` gert.wollny
  2025-11-19 16:45       ` [PATCH v5 1/5] drm/etnaviv: Add command stream definitions required for " gert.wollny
                         ` (5 more replies)
  5 siblings, 6 replies; 41+ messages in thread
From: gert.wollny @ 2025-11-19 16:45 UTC (permalink / raw)
  To: Christian Gmeiner
  Cc: Lucas Stach, Russell King, David Airlie, Daniel Vetter,
	Marek Vasut, etnaviv, dri-devel, linux-kernel

Dear all, 

this is the fifth version of the series to add PPU flop reset.

Changes w.r.t. the previous version are:

  * Apply all changes suggested by Christian Gmeiner:
   - fix a memory leak that would occure when PPU data 
     initialization fails
   - remove unneeded includes
   - move includes to the files where they are actuall needed
   - fix include style for "linux" headers
   - fix typo in error message 

  * add Reviewed-by tags to the according commits 

Many thanks for any comments,
Gert


^ permalink raw reply	[flat|nested] 41+ messages in thread

* [PATCH v5 1/5] drm/etnaviv: Add command stream definitions required for a PPU flop reset
  2025-11-19 16:45     ` [PATCH v5 0/5] drm/etnaviv: Add support for running a " gert.wollny
@ 2025-11-19 16:45       ` gert.wollny
  2025-11-19 16:45       ` [PATCH v5 2/5] drm/etnaviv: move some functions to a header to be able to use them externally gert.wollny
                         ` (4 subsequent siblings)
  5 siblings, 0 replies; 41+ messages in thread
From: gert.wollny @ 2025-11-19 16:45 UTC (permalink / raw)
  To: Christian Gmeiner
  Cc: Lucas Stach, Russell King, David Airlie, Daniel Vetter,
	Marek Vasut, etnaviv, dri-devel, linux-kernel, Gert Wollny,
	Christian Gmeiner

From: Gert Wollny <gert.wollny@collabora.com>

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>
Reviewed-by: Christian Gmeiner <cgmeiner@igalia.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 ebbd4fcf3..b9e9b78df 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.51.0


^ permalink raw reply	[flat|nested] 41+ messages in thread

* [PATCH v5 2/5] drm/etnaviv: move some functions to a header to be able to use them externally
  2025-11-19 16:45     ` [PATCH v5 0/5] drm/etnaviv: Add support for running a " gert.wollny
  2025-11-19 16:45       ` [PATCH v5 1/5] drm/etnaviv: Add command stream definitions required for " gert.wollny
@ 2025-11-19 16:45       ` gert.wollny
  2025-11-28  8:56         ` Christian Gmeiner
  2025-11-19 16:45       ` [PATCH v5 3/5] drm/etnaviv: Add a new function to emit a series of states to cmd stream gert.wollny
                         ` (3 subsequent siblings)
  5 siblings, 1 reply; 41+ messages in thread
From: gert.wollny @ 2025-11-19 16:45 UTC (permalink / raw)
  To: Christian Gmeiner
  Cc: Lucas Stach, Russell King, David Airlie, Daniel Vetter,
	Marek Vasut, etnaviv, dri-devel, linux-kernel, Gert Wollny

From: Gert Wollny <gert.wollny@collabora.com>

v2: Add license info to header

v3: remove unused headers (Christian Gmainer)

Signed-off-by: Gert Wollny <gert.wollny@collabora.com>
---
 drivers/gpu/drm/etnaviv/etnaviv_buffer.c | 71 +--------------------
 drivers/gpu/drm/etnaviv/etnaviv_buffer.h | 79 ++++++++++++++++++++++++
 2 files changed, 80 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 384df1659..829f8497d 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 000000000..4cf77cdee
--- /dev/null
+++ b/drivers/gpu/drm/etnaviv/etnaviv_buffer.h
@@ -0,0 +1,79 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2014-2025 Etnaviv Project
+ */
+
+#ifndef etnaviv_buffer_h
+#define etnaviv_buffer_h
+
+#include "etnaviv_cmdbuf.h"
+
+#include "common.xml.h"
+#include "state.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.51.0


^ permalink raw reply	[flat|nested] 41+ messages in thread

* [PATCH v5 3/5] drm/etnaviv: Add a new function to emit a series of states to cmd stream
  2025-11-19 16:45     ` [PATCH v5 0/5] drm/etnaviv: Add support for running a " gert.wollny
  2025-11-19 16:45       ` [PATCH v5 1/5] drm/etnaviv: Add command stream definitions required for " gert.wollny
  2025-11-19 16:45       ` [PATCH v5 2/5] drm/etnaviv: move some functions to a header to be able to use them externally gert.wollny
@ 2025-11-19 16:45       ` gert.wollny
  2025-11-19 16:45       ` [PATCH v5 4/5] drm/etnaviv: Add PPU flop reset gert.wollny
                         ` (2 subsequent siblings)
  5 siblings, 0 replies; 41+ messages in thread
From: gert.wollny @ 2025-11-19 16:45 UTC (permalink / raw)
  To: Christian Gmeiner
  Cc: Lucas Stach, Russell King, David Airlie, Daniel Vetter,
	Marek Vasut, etnaviv, dri-devel, linux-kernel, Gert Wollny,
	Christian Gmeiner

From: Gert Wollny <gert.wollny@collabora.com>

v2: fix formatting and remove superfluous masking (Lucas)

Signed-off-by: Gert Wollny <gert.wollny@collabora.com>
Reviewed-by: Christian Gmeiner <cgmeiner@igalia.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 4cf77cdee..c5a0d1fb9 100644
--- a/drivers/gpu/drm/etnaviv/etnaviv_buffer.h
+++ b/drivers/gpu/drm/etnaviv/etnaviv_buffer.h
@@ -36,6 +36,19 @@ static inline void CMD_LOAD_STATE(struct etnaviv_cmdbuf *buffer, u32 reg,
 	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.51.0


^ permalink raw reply	[flat|nested] 41+ messages in thread

* [PATCH v5 4/5] drm/etnaviv: Add PPU flop reset
  2025-11-19 16:45     ` [PATCH v5 0/5] drm/etnaviv: Add support for running a " gert.wollny
                         ` (2 preceding siblings ...)
  2025-11-19 16:45       ` [PATCH v5 3/5] drm/etnaviv: Add a new function to emit a series of states to cmd stream gert.wollny
@ 2025-11-19 16:45       ` gert.wollny
  2025-11-28  8:53         ` Christian Gmeiner
  2025-11-19 16:45       ` [PATCH v5 5/5] drm/etnaviv: Add module parameter to force " gert.wollny
  2025-11-21 20:47       ` [PATCH v5 0/5] drm/etnaviv: Add support for running a " Marek Vasut
  5 siblings, 1 reply; 41+ messages in thread
From: gert.wollny @ 2025-11-19 16:45 UTC (permalink / raw)
  To: Christian Gmeiner
  Cc: Lucas Stach, Russell King, David Airlie, Daniel Vetter,
	Marek Vasut, etnaviv, dri-devel, linux-kernel, Gert Wollny

From: Gert Wollny <gert.wollny@collabora.com>

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)

v4: As suggested by
    - replace "asm-generic/int-ll64.h" with "linux/types.h"
    - drop flop reset type enum since we only support one type here
    - move function return parameters on same line with function name
    - replace open coded for loop with memset32
    - add cnost to local static values
    - add a return value to etnaviv_flop_reset_ppu_init; handle and
      pass errors on to the caller
    - handle etnaviv_flop_reset_ppu_init return value
    - use dev_err for flop reset error message
    - fix include guard to be consistent with the other driver code
    - fix license header and formatting

v5: As suggested by Christian Gmeiner:
    - add required header that is no longer pulled in by etnaviv_buffer.h
    - fix include style of linux headers
    - free flop_reset_data_ppu when command buffer initialization fails
    - fix typo in error message

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_buffer.h     |   7 +
 drivers/gpu/drm/etnaviv/etnaviv_drv.c        |   3 +
 drivers/gpu/drm/etnaviv/etnaviv_drv.h        |   3 +
 drivers/gpu/drm/etnaviv/etnaviv_flop_reset.c | 208 +++++++++++++++++++
 drivers/gpu/drm/etnaviv/etnaviv_flop_reset.h |  21 ++
 drivers/gpu/drm/etnaviv/etnaviv_gpu.c        |  11 +
 8 files changed, 260 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 46e5ffad6..903101e87 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 829f8497d..463a6f556 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_buffer.h b/drivers/gpu/drm/etnaviv/etnaviv_buffer.h
index c5a0d1fb9..9388a686e 100644
--- a/drivers/gpu/drm/etnaviv/etnaviv_buffer.h
+++ b/drivers/gpu/drm/etnaviv/etnaviv_buffer.h
@@ -7,9 +7,16 @@
 #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)
diff --git a/drivers/gpu/drm/etnaviv/etnaviv_drv.c b/drivers/gpu/drm/etnaviv/etnaviv_drv.c
index f9bc837e2..21a42a1f4 100644
--- a/drivers/gpu/drm/etnaviv/etnaviv_drv.c
+++ b/drivers/gpu/drm/etnaviv/etnaviv_drv.c
@@ -569,6 +569,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 b3eb1662e..20dad16fd 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 000000000..6ed2471f3
--- /dev/null
+++ b/drivers/gpu/drm/etnaviv/etnaviv_flop_reset.c
@@ -0,0 +1,208 @@
+/* SPDX-License-Identifier: GPL-2.0
+ *
+ * Copyright (C) 2025 Etnaviv Project
+ */
+
+#include <linux/errno.h>
+#include <linux/dev_printk.h>
+#include <linux/string.h>
+#include <linux/types.h>
+
+#include "etnaviv_buffer.h"
+#include "etnaviv_cmdbuf.h"
+#include "etnaviv_gpu.h"
+#include "state_3d.xml.h"
+
+#include "etnaviv_flop_reset.h"
+
+#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)
+{
+	memset32(buffer, 0x01010101, size / 4);
+}
+
+static void etnaviv_flop_reset_ppu_set_shader(u8 *dest)
+{
+	static 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 const struct etnaviv_flop_reset_entry {
+	u16 chip_model;
+	u16 revision;
+	u32 flags;
+} etnaviv_flop_reset_db[] = {
+	{
+		.chip_model = 0x8000,
+		.revision = 0x6205,
+	},
+};
+
+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 true;
+	}
+
+	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;
+
+int 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);
+
+	if (!priv->flop_reset_data_ppu)
+		return -ENOMEM;
+
+	int ret = etnaviv_cmdbuf_init(priv->cmdbuf_suballoc,
+				      priv->flop_reset_data_ppu, buffer_size);
+	if (ret) {
+		kfree(priv->flop_reset_data_ppu);
+		return ret;
+	}
+
+	void *buffer_base = priv->flop_reset_data_ppu->vaddr;
+	u32 *input_data = (u32 *)buffer_base;
+	u8 *shader_data = (u8 *)buffer_base + shader_offset;
+
+	etnaviv_flop_reset_ppu_fill_input(input_data, image_data_size);
+	etnaviv_flop_reset_ppu_set_shader(shader_data);
+
+	return 0;
+}
+
+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) {
+		dev_err(gpu->dev,
+			"Oops: 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 000000000..e6dee1db7
--- /dev/null
+++ b/drivers/gpu/drm/etnaviv/etnaviv_flop_reset.h
@@ -0,0 +1,21 @@
+/* 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);
+
+int 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 33586e3f2..b5257e0a7 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"
@@ -789,6 +790,16 @@ int etnaviv_gpu_init(struct etnaviv_gpu *gpu)
 		goto fail;
 	}
 
+	if (etnaviv_flop_reset_ppu_require(&gpu->identity) &&
+	    !priv->flop_reset_data_ppu) {
+		ret = etnaviv_flop_reset_ppu_init(priv);
+		if (ret) {
+			dev_err(gpu->dev,
+				"Unable to initialize PPU flop reset data\n");
+			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");
-- 
2.51.0


^ permalink raw reply	[flat|nested] 41+ messages in thread

* [PATCH v5 5/5] drm/etnaviv: Add module parameter to force PPU flop reset
  2025-11-19 16:45     ` [PATCH v5 0/5] drm/etnaviv: Add support for running a " gert.wollny
                         ` (3 preceding siblings ...)
  2025-11-19 16:45       ` [PATCH v5 4/5] drm/etnaviv: Add PPU flop reset gert.wollny
@ 2025-11-19 16:45       ` gert.wollny
  2025-11-21 20:47       ` [PATCH v5 0/5] drm/etnaviv: Add support for running a " Marek Vasut
  5 siblings, 0 replies; 41+ messages in thread
From: gert.wollny @ 2025-11-19 16:45 UTC (permalink / raw)
  To: Christian Gmeiner
  Cc: Lucas Stach, Russell King, David Airlie, Daniel Vetter,
	Marek Vasut, etnaviv, dri-devel, linux-kernel, Gert Wollny,
	Christian Gmeiner

From: Gert Wollny <gert.wollny@collabora.com>

v2: Check for feature PIPE_3D when forcing PPU flop reset (Lucas)

v3: - drop use of ppu_flop_reset enum (Christian Gmeiner)
    - don't initialize module parameter to zero (checkpatch)
    - avoid multi-line string in warning message (checkpatch)

Signed-off-by: Gert Wollny <gert.wollny@collabora.com>
Reviewed-by: Christian Gmeiner <cgmeiner@igalia.com>
---
 drivers/gpu/drm/etnaviv/etnaviv_flop_reset.c | 16 ++++++++++++++++
 1 file changed, 16 insertions(+)

diff --git a/drivers/gpu/drm/etnaviv/etnaviv_flop_reset.c b/drivers/gpu/drm/etnaviv/etnaviv_flop_reset.c
index 6ed2471f3..a78119e0a 100644
--- a/drivers/gpu/drm/etnaviv/etnaviv_flop_reset.c
+++ b/drivers/gpu/drm/etnaviv/etnaviv_flop_reset.c
@@ -15,6 +15,9 @@
 
 #include "etnaviv_flop_reset.h"
 
+static int etnaviv_force_flop_reset;
+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
@@ -150,6 +153,19 @@ bool etnaviv_flop_reset_ppu_require(const struct etnaviv_chip_identity *chip_id)
 			return true;
 	}
 
+	if (etnaviv_force_flop_reset) {
+		if (!(chip_id->features & chipFeatures_PIPE_3D)) {
+			pr_warn("Etnaviv: model: 0x%04x, revision: 0x%04x does not support PIPE_3D\n",
+				chip_id->model, chip_id->revision);
+			pr_warn("Request to force PPU flop reset ignored.\n");
+			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.51.0


^ permalink raw reply	[flat|nested] 41+ messages in thread

* Re: [PATCH v5 0/5] drm/etnaviv: Add support for running a PPU flop reset
  2025-11-19 16:45     ` [PATCH v5 0/5] drm/etnaviv: Add support for running a " gert.wollny
                         ` (4 preceding siblings ...)
  2025-11-19 16:45       ` [PATCH v5 5/5] drm/etnaviv: Add module parameter to force " gert.wollny
@ 2025-11-21 20:47       ` Marek Vasut
  2026-01-06 15:48         ` Christian Gmeiner
  5 siblings, 1 reply; 41+ messages in thread
From: Marek Vasut @ 2025-11-21 20:47 UTC (permalink / raw)
  To: gert.wollny, Christian Gmeiner
  Cc: Lucas Stach, Russell King, David Airlie, Daniel Vetter,
	Marek Vasut, etnaviv, dri-devel, linux-kernel, kernel

On 11/19/25 5:45 PM, gert.wollny@collabora.com wrote:

Hello Gert,

> this is the fifth version of the series to add PPU flop reset.
> 
> Changes w.r.t. the previous version are:
> 
>    * Apply all changes suggested by Christian Gmeiner:
>     - fix a memory leak that would occure when PPU data
>       initialization fails
>     - remove unneeded includes
>     - move includes to the files where they are actuall needed
>     - fix include style for "linux" headers
>     - fix typo in error message
> 
>    * add Reviewed-by tags to the according commits
For the whole series:

Tested-by: Marek Vasut <marek.vasut@mailbox.org> # STM32MP255C DHCOS DHSBC

Thank you !

^ permalink raw reply	[flat|nested] 41+ messages in thread

* Re: [PATCH v5 4/5] drm/etnaviv: Add PPU flop reset
  2025-11-19 16:45       ` [PATCH v5 4/5] drm/etnaviv: Add PPU flop reset gert.wollny
@ 2025-11-28  8:53         ` Christian Gmeiner
  0 siblings, 0 replies; 41+ messages in thread
From: Christian Gmeiner @ 2025-11-28  8:53 UTC (permalink / raw)
  To: gert.wollny
  Cc: Lucas Stach, Russell King, David Airlie, Daniel Vetter,
	Marek Vasut, etnaviv, dri-devel, linux-kernel

Am Mi., 19. Nov. 2025 um 17:43 Uhr schrieb <gert.wollny@collabora.com>:
>
> From: Gert Wollny <gert.wollny@collabora.com>
>
> 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)
>
> v4: As suggested by
>     - replace "asm-generic/int-ll64.h" with "linux/types.h"
>     - drop flop reset type enum since we only support one type here
>     - move function return parameters on same line with function name
>     - replace open coded for loop with memset32
>     - add cnost to local static values
>     - add a return value to etnaviv_flop_reset_ppu_init; handle and
>       pass errors on to the caller
>     - handle etnaviv_flop_reset_ppu_init return value
>     - use dev_err for flop reset error message
>     - fix include guard to be consistent with the other driver code
>     - fix license header and formatting
>
> v5: As suggested by Christian Gmeiner:
>     - add required header that is no longer pulled in by etnaviv_buffer.h
>     - fix include style of linux headers
>     - free flop_reset_data_ppu when command buffer initialization fails
>     - fix typo in error message
>
> Signed-off-by: Gert Wollny <gert.wollny@collabora.com>

Reviewed-by: Christian Gmeiner <cgmeiner@igalia.com>

> ---
>  drivers/gpu/drm/etnaviv/Makefile             |   1 +
>  drivers/gpu/drm/etnaviv/etnaviv_buffer.c     |   6 +
>  drivers/gpu/drm/etnaviv/etnaviv_buffer.h     |   7 +
>  drivers/gpu/drm/etnaviv/etnaviv_drv.c        |   3 +
>  drivers/gpu/drm/etnaviv/etnaviv_drv.h        |   3 +
>  drivers/gpu/drm/etnaviv/etnaviv_flop_reset.c | 208 +++++++++++++++++++
>  drivers/gpu/drm/etnaviv/etnaviv_flop_reset.h |  21 ++
>  drivers/gpu/drm/etnaviv/etnaviv_gpu.c        |  11 +
>  8 files changed, 260 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 46e5ffad6..903101e87 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 829f8497d..463a6f556 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_buffer.h b/drivers/gpu/drm/etnaviv/etnaviv_buffer.h
> index c5a0d1fb9..9388a686e 100644
> --- a/drivers/gpu/drm/etnaviv/etnaviv_buffer.h
> +++ b/drivers/gpu/drm/etnaviv/etnaviv_buffer.h
> @@ -7,9 +7,16 @@
>  #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 <linux/printk.h> and move it to the top.

>  #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)
> diff --git a/drivers/gpu/drm/etnaviv/etnaviv_drv.c b/drivers/gpu/drm/etnaviv/etnaviv_drv.c
> index f9bc837e2..21a42a1f4 100644
> --- a/drivers/gpu/drm/etnaviv/etnaviv_drv.c
> +++ b/drivers/gpu/drm/etnaviv/etnaviv_drv.c
> @@ -569,6 +569,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 b3eb1662e..20dad16fd 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 000000000..6ed2471f3
> --- /dev/null
> +++ b/drivers/gpu/drm/etnaviv/etnaviv_flop_reset.c
> @@ -0,0 +1,208 @@
> +/* SPDX-License-Identifier: GPL-2.0
> + *
> + * Copyright (C) 2025 Etnaviv Project
> + */
> +
> +#include <linux/errno.h>
> +#include <linux/dev_printk.h>
> +#include <linux/string.h>
> +#include <linux/types.h>
> +
> +#include "etnaviv_buffer.h"
> +#include "etnaviv_cmdbuf.h"
> +#include "etnaviv_gpu.h"
> +#include "state_3d.xml.h"
> +
> +#include "etnaviv_flop_reset.h"
> +
> +#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)
> +{
> +       memset32(buffer, 0x01010101, size / 4);
> +}
> +
> +static void etnaviv_flop_reset_ppu_set_shader(u8 *dest)
> +{
> +       static 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 const struct etnaviv_flop_reset_entry {
> +       u16 chip_model;
> +       u16 revision;
> +       u32 flags;
> +} etnaviv_flop_reset_db[] = {
> +       {
> +               .chip_model = 0x8000,
> +               .revision = 0x6205,
> +       },
> +};
> +
> +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 true;
> +       }
> +
> +       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;
> +
> +int 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);
> +
> +       if (!priv->flop_reset_data_ppu)
> +               return -ENOMEM;
> +
> +       int ret = etnaviv_cmdbuf_init(priv->cmdbuf_suballoc,
> +                                     priv->flop_reset_data_ppu, buffer_size);
> +       if (ret) {
> +               kfree(priv->flop_reset_data_ppu);
> +               return ret;
> +       }
> +
> +       void *buffer_base = priv->flop_reset_data_ppu->vaddr;
> +       u32 *input_data = (u32 *)buffer_base;
> +       u8 *shader_data = (u8 *)buffer_base + shader_offset;
> +
> +       etnaviv_flop_reset_ppu_fill_input(input_data, image_data_size);
> +       etnaviv_flop_reset_ppu_set_shader(shader_data);
> +
> +       return 0;
> +}
> +
> +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) {
> +               dev_err(gpu->dev,
> +                       "Oops: 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 000000000..e6dee1db7
> --- /dev/null
> +++ b/drivers/gpu/drm/etnaviv/etnaviv_flop_reset.h
> @@ -0,0 +1,21 @@
> +/* 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);
> +
> +int 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 33586e3f2..b5257e0a7 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"
> @@ -789,6 +790,16 @@ int etnaviv_gpu_init(struct etnaviv_gpu *gpu)
>                 goto fail;
>         }
>
> +       if (etnaviv_flop_reset_ppu_require(&gpu->identity) &&
> +           !priv->flop_reset_data_ppu) {
> +               ret = etnaviv_flop_reset_ppu_init(priv);
> +               if (ret) {
> +                       dev_err(gpu->dev,
> +                               "Unable to initialize PPU flop reset data\n");
> +                       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");
> --
> 2.51.0
>

In order to save you from doing another round, I will fix the last
nit, if that is okay
for you.

Reviewed-by: Christian Gmeiner <cgmeiner@igalia.com>

-- 
greets
--
Christian Gmeiner, MSc

https://christian-gmeiner.info/privacypolicy

^ permalink raw reply	[flat|nested] 41+ messages in thread

* Re: [PATCH v5 2/5] drm/etnaviv: move some functions to a header to be able to use them externally
  2025-11-19 16:45       ` [PATCH v5 2/5] drm/etnaviv: move some functions to a header to be able to use them externally gert.wollny
@ 2025-11-28  8:56         ` Christian Gmeiner
  2025-11-28 13:39           ` Gert Wollny
  0 siblings, 1 reply; 41+ messages in thread
From: Christian Gmeiner @ 2025-11-28  8:56 UTC (permalink / raw)
  To: gert.wollny
  Cc: Lucas Stach, Russell King, David Airlie, Daniel Vetter,
	Marek Vasut, etnaviv, dri-devel, linux-kernel

Am Mi., 19. Nov. 2025 um 17:43 Uhr schrieb <gert.wollny@collabora.com>:
>
> From: Gert Wollny <gert.wollny@collabora.com>
>
> v2: Add license info to header
>
> v3: remove unused headers (Christian Gmainer)
>
> Signed-off-by: Gert Wollny <gert.wollny@collabora.com>
> ---
>  drivers/gpu/drm/etnaviv/etnaviv_buffer.c | 71 +--------------------
>  drivers/gpu/drm/etnaviv/etnaviv_buffer.h | 79 ++++++++++++++++++++++++
>  2 files changed, 80 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 384df1659..829f8497d 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 000000000..4cf77cdee
> --- /dev/null
> +++ b/drivers/gpu/drm/etnaviv/etnaviv_buffer.h
> @@ -0,0 +1,79 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * Copyright (C) 2014-2025 Etnaviv Project
> + */
> +
> +#ifndef etnaviv_buffer_h
> +#define etnaviv_buffer_h
> +

You missed my comment from the previous review.

> +#include "etnaviv_cmdbuf.h"
> +
> +#include "common.xml.h"
> +#include "state.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.51.0
>

In order to save you from doing another round, I will fix the
last nit, if that is okay for you.

Reviewed-by: Christian Gmeiner <cgmeiner@igalia.com>

-- 
greets
--
Christian Gmeiner, MSc

https://christian-gmeiner.info/privacypolicy

^ permalink raw reply	[flat|nested] 41+ messages in thread

* Re: [PATCH v5 2/5] drm/etnaviv: move some functions to a header to be able to use them externally
  2025-11-28  8:56         ` Christian Gmeiner
@ 2025-11-28 13:39           ` Gert Wollny
  0 siblings, 0 replies; 41+ messages in thread
From: Gert Wollny @ 2025-11-28 13:39 UTC (permalink / raw)
  To: Christian Gmeiner
  Cc: Lucas Stach, Russell King, David Airlie, Daniel Vetter,
	Marek Vasut, etnaviv, dri-devel, linux-kernel

On Fri, 2025-11-28 at 09:56 +0100, Christian Gmeiner wrote:
> 
> > +#ifndef etnaviv_buffer_h
> > +#define etnaviv_buffer_h
> > +
> 
> You missed my comment from the previous review.

Sorry about that. 
> 
> 
> 
> In order to save you from doing another round, I will fix the
> last nit, if that is okay for you.
> 
Sure, that's fine with me, thanks a lot, 

Gert 



^ permalink raw reply	[flat|nested] 41+ messages in thread

* Re: [PATCH v5 0/5] drm/etnaviv: Add support for running a PPU flop reset
  2025-11-21 20:47       ` [PATCH v5 0/5] drm/etnaviv: Add support for running a " Marek Vasut
@ 2026-01-06 15:48         ` Christian Gmeiner
  0 siblings, 0 replies; 41+ messages in thread
From: Christian Gmeiner @ 2026-01-06 15:48 UTC (permalink / raw)
  To: Marek Vasut
  Cc: gert.wollny, Lucas Stach, Russell King, David Airlie,
	Daniel Vetter, Marek Vasut, etnaviv, dri-devel, linux-kernel,
	kernel

>
> On 11/19/25 5:45 PM, gert.wollny@collabora.com wrote:
>
> Hello Gert,
>
> > this is the fifth version of the series to add PPU flop reset.
> >
> > Changes w.r.t. the previous version are:
> >
> >    * Apply all changes suggested by Christian Gmeiner:
> >     - fix a memory leak that would occure when PPU data
> >       initialization fails
> >     - remove unneeded includes
> >     - move includes to the files where they are actuall needed
> >     - fix include style for "linux" headers
> >     - fix typo in error message
> >
> >    * add Reviewed-by tags to the according commits
> For the whole series:
>
> Tested-by: Marek Vasut <marek.vasut@mailbox.org> # STM32MP255C DHCOS DHSBC
>
> Thank you !

Applied to drm-misc-next.

-- 
greets
--
Christian Gmeiner, MSc

https://christian-gmeiner.info/privacypolicy

^ permalink raw reply	[flat|nested] 41+ messages in thread

end of thread, other threads:[~2026-01-06 15:48 UTC | newest]

Thread overview: 41+ 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-10-09 21:40     ` Christian Gmeiner
2025-06-30 20:26   ` [PATCH v3 5/5] drm/etnaviv: Add module parameter to force " Gert Wollny
2025-11-10 14:37   ` [PATCH v4 0/5] drm/etnaviv: Add support for running a " gert.wollny
2025-11-10 14:37     ` [PATCH v4 1/5] drm/etnaviv: Add command stream definitions required for " gert.wollny
2025-11-10 15:54       ` Christian Gmeiner
2025-11-10 14:37     ` [PATCH v4 2/5] drm/etnaviv: move some functions to a header to be able to use them externally gert.wollny
2025-11-10 15:53       ` Christian Gmeiner
2025-11-10 14:37     ` [PATCH v4 3/5] drm/etnaviv: Add a new function to emit a series of states to cmd stream gert.wollny
2025-11-17  8:27       ` Christian Gmeiner
2025-11-10 14:37     ` [PATCH v4 4/5] drm/etnaviv: Add PPU flop reset gert.wollny
2025-11-17  8:57       ` Christian Gmeiner
2025-11-10 14:37     ` [PATCH v4 5/5] drm/etnaviv: Add module parameter to force " gert.wollny
2025-11-19 15:30       ` Christian Gmeiner
2025-11-19 16:45     ` [PATCH v5 0/5] drm/etnaviv: Add support for running a " gert.wollny
2025-11-19 16:45       ` [PATCH v5 1/5] drm/etnaviv: Add command stream definitions required for " gert.wollny
2025-11-19 16:45       ` [PATCH v5 2/5] drm/etnaviv: move some functions to a header to be able to use them externally gert.wollny
2025-11-28  8:56         ` Christian Gmeiner
2025-11-28 13:39           ` Gert Wollny
2025-11-19 16:45       ` [PATCH v5 3/5] drm/etnaviv: Add a new function to emit a series of states to cmd stream gert.wollny
2025-11-19 16:45       ` [PATCH v5 4/5] drm/etnaviv: Add PPU flop reset gert.wollny
2025-11-28  8:53         ` Christian Gmeiner
2025-11-19 16:45       ` [PATCH v5 5/5] drm/etnaviv: Add module parameter to force " gert.wollny
2025-11-21 20:47       ` [PATCH v5 0/5] drm/etnaviv: Add support for running a " Marek Vasut
2026-01-06 15:48         ` Christian Gmeiner

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox

all inboxes | Powered by JetHome®