[PATCH v3 0/5] drm/etnaviv: Add support for running a PPU flop reset

Gert Wollny posted 5 patches 7 months, 1 week ago
There is a newer version of this series
[PATCH v3 0/5] drm/etnaviv: Add support for running a PPU flop reset
Posted by Gert Wollny 7 months, 1 week ago
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
[PATCH v4 0/5] drm/etnaviv: Add support for running a PPU flop reset
Posted by gert.wollny@collabora.com 2 months, 4 weeks ago
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
[PATCH v5 0/5] drm/etnaviv: Add support for running a PPU flop reset
Posted by gert.wollny@collabora.com 2 months, 2 weeks ago
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
Re: [PATCH v5 0/5] drm/etnaviv: Add support for running a PPU flop reset
Posted by Marek Vasut 2 months, 2 weeks ago
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 !
Re: [PATCH v5 0/5] drm/etnaviv: Add support for running a PPU flop reset
Posted by Christian Gmeiner 1 month ago
>
> 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
[PATCH v5 1/5] drm/etnaviv: Add command stream definitions required for a PPU flop reset
Posted by gert.wollny@collabora.com 2 months, 2 weeks ago
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
[PATCH v5 2/5] drm/etnaviv: move some functions to a header to be able to use them externally
Posted by gert.wollny@collabora.com 2 months, 2 weeks ago
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
Re: [PATCH v5 2/5] drm/etnaviv: move some functions to a header to be able to use them externally
Posted by Christian Gmeiner 2 months, 1 week ago
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
Re: [PATCH v5 2/5] drm/etnaviv: move some functions to a header to be able to use them externally
Posted by Gert Wollny 2 months, 1 week ago
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 
[PATCH v5 3/5] drm/etnaviv: Add a new function to emit a series of states to cmd stream
Posted by gert.wollny@collabora.com 2 months, 2 weeks ago
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
[PATCH v5 4/5] drm/etnaviv: Add PPU flop reset
Posted by gert.wollny@collabora.com 2 months, 2 weeks ago
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
Re: [PATCH v5 4/5] drm/etnaviv: Add PPU flop reset
Posted by Christian Gmeiner 2 months, 1 week ago
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
[PATCH v5 5/5] drm/etnaviv: Add module parameter to force PPU flop reset
Posted by gert.wollny@collabora.com 2 months, 2 weeks ago
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
[PATCH v4 1/5] drm/etnaviv: Add command stream definitions required for a PPU flop reset
Posted by gert.wollny@collabora.com 2 months, 4 weeks ago
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
Re: [PATCH v4 1/5] drm/etnaviv: Add command stream definitions required for a PPU flop reset
Posted by Christian Gmeiner 2 months, 4 weeks ago
>
> 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
[PATCH v4 2/5] drm/etnaviv: move some functions to a header to be able to use them externally
Posted by gert.wollny@collabora.com 2 months, 4 weeks ago
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
Re: [PATCH v4 2/5] drm/etnaviv: move some functions to a header to be able to use them externally
Posted by Christian Gmeiner 2 months, 4 weeks ago
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
[PATCH v4 3/5] drm/etnaviv: Add a new function to emit a series of states to cmd stream
Posted by gert.wollny@collabora.com 2 months, 4 weeks ago
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
Re: [PATCH v4 3/5] drm/etnaviv: Add a new function to emit a series of states to cmd stream
Posted by Christian Gmeiner 2 months, 3 weeks ago
> 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
[PATCH v4 4/5] drm/etnaviv: Add PPU flop reset
Posted by gert.wollny@collabora.com 2 months, 4 weeks ago
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
Re: [PATCH v4 4/5] drm/etnaviv: Add PPU flop reset
Posted by Christian Gmeiner 2 months, 3 weeks ago
> 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
[PATCH v4 5/5] drm/etnaviv: Add module parameter to force PPU flop reset
Posted by gert.wollny@collabora.com 2 months, 4 weeks ago
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
Re: [PATCH v4 5/5] drm/etnaviv: Add module parameter to force PPU flop reset
Posted by Christian Gmeiner 2 months, 2 weeks ago
> 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